In the latest years the growing demand for Rich Internet Applications submitted the following question to the developers' community: which to choose between the Ajax + JavaScript solution on one hand, and the Flash player based Adobe Flex technology on the other hand? The choice is definitely hard, as in most cases both solutions are suitable without particular indications or limitations, and we can insert both Ajax and Flex with no difficulty in the same web pages and applications in case of particular requirements.
What if we want that Flex interacts with Ajax/JavaScript in the same application to render a virtually unlimited user experience? What if we need our Flex application interacts with third parties' applications (e.g. Google Maps)?
Flex Ajax Bridge is a free small library which in such circumstances allows the developer to save many lines of code. Through Flex Ajax Bridge , which is now included in Adobe LiveCycle Data Services 2.5, you can make your ActionScript classes available to JavaScript without any additional coding. After you insert the library, essentially anything you can do with ActionScript, you can do with JavaScript.
While the functionalities offered by the External Interface class of the Flash Player can solve the easiest cases of ActionScript/JavaScript interaction, it is advisable to use the FABridge (Flex Ajax Bridge) in the most complex situations, in presence of user-defined classes or when we should define an interface to make JavaScript dialog with ActionScript and vice-versa.
In both cases we would face a little limit: it causes a problem trying to access Flex component just after html loads using body tags onload attributes while the swf files is not loaded yet.
It seems a marginal issue, but quite often it happens that our Flex movie will be initialized after the onload event is launched.
A possible solution could be the one of waiting a few seconds by using the Javascript function setTimeout(code,millisec,lang) , however what assures the movie will be ready in that time? If the movie were not ready, either an error is generated or the input to the Flex component goes lost.
The solution on the Flex 3 side is to make our Flex application disabled by using JavaScript :
To get the DOM object of our SWF file we'll use the ExternalInterface class standard function:
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
In Flex we register the ActionScript method we want to call from the JavaScript side with the addCallback method :
ExternalInterface.addCallback("disableApplication", disableFunction);
We could call the method registering it on the creationComplete Flex event or any other system event.
Then we invoke the function that will call the method exposed by the ExternalInterface class, disableApplication in our case :
function disableMovie(movieName) {
var myMovie = thisMovie(movieName);
if(myMovie == null || myMovie.disableApplication == null)
{
setTimeout("disableFilter("+movieName+")", 100);
}
else
{
myMovie.disableApplication();
}
}
If the SWF file has not been loaded yet or the ExternalInterface.addCallback function has not been invoked on the Flex side, the movie will wait 100 milliseconds to disable the application again.
This method is known as busy waiting, and it's not a CPU intensive processing method, but it continuously calls the JavaScript function until it gets the value.
It's easy to implement this solution for small applications but it has several problems as soon as more and more applications run concurrently or there are race conditions. A more complicated solution to solve some of these problems can be to use some global variables to hold the objects returned by setTimeout() function, so we could call a clearTimeout() when needed.
As you can note, this method could generate unwanted effects when there are several functions and a medium size application.
This example is based on the ExternalInterface class but such a problem comes in also when using Flex Ajax Bridge, as mentioned in the Adobe Labs Wiki.
In the next part of the post we'll create an ObjectManager in JavaScript to handle this issue.