swfJavascript for Flash/Flex


Javascript embedding for Flash/Flex

This component allows you to embed javascript into an SWF file and have that javascript be made available (injected) to the browser context so it can be used as normal.

To make this possible we have created a Flash/Flex component that will inject any javascript on runtime and an easy to use desktop application (build with AIR) to generate an actionscript class from javascript that can be embedded into your project.

 

Who is it for?

swfJavascript is perfect for developers who use Flash or Flex technology combined with javascript in a web environment but without the need to attach external javascripts to the HTML page.

Distribution and dependancies

In situations were an SWF communicates with the browser via the External API, it's no longer required to manually attach javascript files to the header of an HTML document since the javascript can now be embedded within the SWF file.

This will prove a considerable advantage for creators of flash content that will be distributed on many different websites (think flash ads), since having to distribute a single SWF that contains its own javascript dependancies is simpler.

Compression

Some web servers may use transparent compression for javascript files on the fly, but this technique depends on factors such as server configuration and client support. When using our method a highly compressed (up to ±80%) javascript is guaranteed.

Code obfuscation

Since javascript is embedded within the SWF file this method obfuscates javascript code from any casual curiosity as their is no attached javascript source to view. This might be of some importance to your project.

Saving on development resources

swfJavascript takes the hassle out of embedding and injecting javascripts manually and therefore saves you time. We have done extensive testing to ensure that javascript that is known to run without errors as externally attached files can be embedded into an SWF file. Even the more complicated scripts which use javascript's 'eval' method (such as scriptaculous's effects script) are candidates for embedding and work across all major browsers provided that they supports actionscript's External API.

 

I would love to see this in action!

We have created a simple project for you to evaluate. This project consists of a color picker that will enable the user to change the (HTML) background- and/or text color. The color change has a tween effect. Note that the top of the page (the colorpicker) is SWF and the rest is regular HTML.

The tween effect requires some custom written javascript functions (to be called from Flash). The Scriptaculous- and Prototype libraries are also required. 3 Separate javascript files need to be referenced in the HTML document.

The project shows two windows with the exact same content. The window on the left has some external javascript files attached. The window on the right our method is used and no external javascripts are required. We encourage you to download the demo and see for yourself.

SHOW EXAMPLE

 

Great! So, how does this actually work?

To embed javascript just two simple steps are required which can be performed when a project is ready for 'packaging'. Meaning it can be done at the end of the development cycle when you are confident the javascript - SWF interaction does what it's supposed to.

First step is to generate a 'payload' class from the javascript source file. A payload class is nothing more than a javascript file (or multiple files) embedded into a static actionscript class so it can be compiled into the final SWF file.

Once a payload class has been generated the developer can deliver its javascript contents to the browser with just one statement.

Javascript Payloader application

The Javascript Payloader is a desktop application written in Adobe's AIR. It can package javascript into an actionscript class. This actionscript payload can then be used in your actionscript 3 projects (Flash or Flex) in conjunction with the injector component.

Main Features

  • Simple drag and drop interface.
  • Generates an actionscript payload class from one or multiple javascript source files.
  • Maintains the order in which you select multiple javascript files.

Usage

Javascript Payloader is a simple application to use. Select one or more javascript files by dragging and dropping them. Then enter an actionscript class name plus an optional package name. After processing the file(s) the application will ask for a location to save the generated payload class. swfJavascript honors the order in which files are selected so if the used javascript files have any interdependencies, make sure you select them in the correct order. They will be injected in that same order.

Note on compression

Javascript Payloader does not change or modify any javascript it processes. Compression is not achieved by any minification process (not even comments are removed). Therefore it can and probably will be an advantage if javascript files are preprocessed beforehand. Since minification is subject to personal preference, this is an optional step and any preferred javascript minifier can be used. We like YUI Compressor.

Injector component

Once a payload class has been generated from your javascript file(s) the payload can be delivered by adding the component to your project (see installation) and calling the static inject method that the generated payload class contains. At this point the javascript is available for usage as normal.

Usage

With just one statement to inject the javascript payload and deliver its contents to the browser usage couldn't be simpler. Check out the following code examples.

package {
  import myPackage.myPayload;

  public class myClass
  {
    public function myClass()
    {
        myPayload.inject();
    }
  }
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[
      import mx.events.FlexEvent;
      import myPackage.myPayload;

      private function onCreationComplete(e:FlexEvent):void {
        myPayload.inject();
      }
    ]]>
  </mx:Script>
</mx:Application>

Advanced Usage

Some example code showing the force parameter, using the Injector.call() method and an more elaborate example were we use the External API.

/**
 * Whether forcing injection of scripts that already have been injected is useful depends
 * on the contents of the payload 
 */        
package {
  import flash.display.Sprite;
  import myPackage.myPayload;

  public class myClass extends Sprite
  {
    public function myClass()
    {
        myPayload.inject();

        // inject even when previously injected
        myPayload.inject(true);
    }
  }
}
/**
 * Call javascript directly (after injection) with the Injector.call() method.
 * Note that import the Injector class but not External API
 */        
package {
  import flash.display.Sprite;
  import myPackage.myPayload;
  import com.zillizi.Injector;
            
  public class myClass extends Sprite
  {
    public function myClass()
    {
      var injected:Boolean = myPayload.inject();
      if (injected) Injector.call('someMethod', 'any', 'number', 'of', 'arguments')
    }
  }
}
            
/**
 * Example showing usage with callback (calling actionscript from javascript).
 * 
 * This is the javascript contained in the payload
 * 
 * function init() {
 * 	alert('inited');
 * 
 * 	// calls registered function in flash in 1 second
 * 	setTimeout(callFlashInASec, 1000);
 * }
 * 
 * function callFlashInASec() {
 * 	test.callFlash();
 * }
 * 
 * function finallyFromFlash() {
 * 	alert('finally, the last method called from flash.');	
 * }
 * 
 */        
package {
  import com.zillizi.Injector;
  
  import flash.display.Sprite;
  import myPackage.myPayload;
  import flash.external.ExternalInterface;

  public class myClass extends Sprite
  {
    public function myClass():void
    {
      var injected:Boolean = myPayload.inject();
      if (injected) {
        ExternalInterface.addCallback('callFlash', calledFromJavascript);
        ExternalInterface.call('init');
      }
    }
    public function calledFromJavascript():void
    {
      // we call our last method in javascript
      ExternalInterface.call('finallyFromFlash');
    }
  }
}
            

API

The following table describes all the public methods & properties available in the generated payload class as in the Injector class.

Payload Class Methods
myPayload.inject(force:Boolean):Boolean

Static method that attempts to inject the payload through the Injector component. It will return a boolean indicating its success and does not throw exceptions (errors go to trace). Note: when you reinjecting a previously successful injected payload TRUE will be return even though no re-injection will be performed unless you set the force parameter.

force:Boolean
optional value (default to false) indicating if the payload should be injected regardless whether it might have been injected allready.
Injector Class Methods and Constants
Injector.PAYLOAD_TYPE_PACKED : String = "PACKED"

Static constant defining a payload type.

Injector.VERSION : String = "1.0.1"

Static constant defining the version of the API.

Injector.inject(payload:String, type:String=Injector.PAYLOAD_TYPE_PACKED):Boolean

Static method that attempts to inject the payload. It will return a boolean indicating its success. You should never have to use this method directly, it is used in the payload class.

payload:String
a string representing an payload
type:String
optional value representing the payload type
Injector.call(method:String, ...:*):Boolean

Convenience method which is an alias of ExternalInterface.call

method:String
name of javascript method being called
...:*
any optional parameters passed along with the javascript method
 
download fully functional demo

Installation of Javascript Payloader application

  • Make sure you have Adobe® AIR™ installed.
  • Double click the JSPayloader.air file and follow onscreen instructions.

Installation of the Injector Component

Flash

  • Double click Injector.mxp to have the component installed to the Flash components panel by the Extension Manager.
  • Restart Flash and drag the component from the components panel to your project library. You do not need to place the component on the stage.

Flash Builder

  • Place the Injector.swc file in a directory (convention calls it 'libs') in your Flex project.
  • Add that directory to the Flex Library Build Path in project properties.

Note: when you use Flash to compile your projects and use Flex Builder as an IDE, we recommend you to also install the Flex version of the component to avoid compile errors and enable code completion within the Flex IDE.

Download a fully working demo

You can download a fully functional version of the complete package.

The package contains two versions of the Injector component (one for Flash, one for Flex) and the Javascript Payloader application.

Payloads generated with an unregistered version of Javascript Payloader will display a reminder message in the browser. This message will show randomly once per 5 reloads so it shouldn't too annoying while evaluating the component. This does mean that after activating the Javascript Payloader application you must regenerate you payload classes and recompile the SWF file.

Requirements

  • Actionscript 3.0
  • Flash Builder or Flash to use the components.
  • Any system capable of running Adobe® AIR™ applications to generate the payload classes.

Adobe© Air™Adobe© Flex™Adobe© Flash™