You would like to easily read/write any JavaScript variable from within Flex
Create a Proxy object and extend the getProperty and setProperty methods to set or retrieve JavaScript variables.
Interacting with an HTML page can be time consuming, and often requires special methods be written. In many cases it is much easier to simply allow a Flex application to blindly access any JavaScript variables available in the HTML page. This can be easily accomplished by extending the Proxy class to act as a passthrough to the ExternalInterface.call() method.
Please note that this recipe does not perform any security checking on the passed variables. Depending on your objectives and requirements, this may not be the best solution.
To complete this recipe, you will have to complete four steps:
While this is not a necessarily a time consuming step, it is nevertheless critical that "allowScriptAccess" in your SWF Embed and Object tags is set to "sameDomain" or "always". If this is not the case, then you will not be able to interface with the Javascript environment using ExternalInterface.
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
width="100" height="100"
codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
<param name="movie" value="yourApplication.swf" />
<param name="allowScriptAccess" value="sameDomain" />
<embed src="yourApplication.swf" quality="high" bgcolor="${bgcolor}"
width="100" height="100"
allowScriptAccess="sameDomain"
type="application/x-shockwave-flash"
pluginspage="http://www.adobe.com/go/getflashplayer">
</embed>
</object>
When creating a new proxy class, it is important to remember two things. First, the class must be dynamic- this tells the compiler and Actionscript Virtual Machine that any method or variable on the object may be invoked, thus avoiding many compile or runtime errors. Secondly, we must include the flash.utils.flash_proxy namespace, which lets us extend the backend functionality provided by the Proxy class. In the below code I am also including ExternalInterface since we will shortly be using it.
package com.practicalflash.examples
{
import flash.external.ExternalInterface;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class JavascriptVariableProxy extends Proxy
{
}
}
Whenever a variable is set or requested on a class instance which extends flash.utils.Proxy, it will attempt to call one of two special methods to handle that action. The first is called getProperty(), which acts as a global getter method, and the second is called setProperty() which acts as the corresponding setter. These two methods are declared in the flash_proxy namespace to avoid name collision, and thus we have to extend them in kind.
As you can see below, we are invoking an instantly created JavaScript method using ExternalInterface.call(). The reason this works is because ExternalInterface will execute anything that resolves to a function, including anything declared inline. I've written a more detailed recipe on how to take full advantage of this feature called "Export and invoke a Javascript Method from Flex", however for our purpose the simple inline invocation works fine.
override flash_proxy function getProperty(name:*):*
{
return ExternalInterface.call("function() { return " + name.toString() + "; }");
}
override flash_proxy function setProperty(name:*, value:*):void
{
ExternalInterface.call("function() { " + name + " = '" + value.toString() + "'; }");
}
Finally, you can create an instance of your class and directly access any variable within the HTML page. This is easily done simply by creating a class instance and accessing a property directly on the object.
var proxy : JavascriptVariableProxy = new JavascriptVariableProxy(); proxy.foo = 'bar'; proxy.bar = 'foo'; trace(proxy.foo); trace(proxy.bar);
Here is the full sample class. It has been included in the sample Flex application attached in Examples.zip.
package com.practicalflash.examples
{
import flash.external.ExternalInterface;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class JavascriptVariableProxy extends Proxy
{
/**
* Retrieves the variable from the javascript environment.
*
* @private
*/
override flash_proxy function getProperty(name:*):*
{
return ExternalInterface.call("function() { return " + name.toString() + "; }");
}
/**
* Passes the variable through to the javascript environment.
*
* @private
*/
override flash_proxy function setProperty(name:*, value:*):void
{
ExternalInterface.call("function() { " + name + " = '" + value.toString() + "'; }");
}
}
}