« The advantages of going open source with Flex 3 | Main | Building a Rest Server with Zend and retrieve data with Flex and the HTTPService »

Creating an ObjectManager for improving the Flex interaction with Ajax or Javascript

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.

TrackBack

TrackBack URL for this entry:
http://blog.comtaste.com/mt-tb.cgi/16

Comments (3)

Pavel Simek:

To handle this issue, we use a flash variable containing the name of the JS function that has to be called after the SWF is loaded and inited (FlashVars="onInit=myFunction").

This is the only FlashVar needed (all further params and calls are implemented using FABridge).

Why any more complicated solution?

Anonymous reader:

I agree that the Flex + FABridge may seem like an acceptable solution, but only so, when the job is small. Most people won't be impressed to know how much memory load a couple of Flex components within a HTML page will add to the browser memory usage, specially in IE. Every control will have it's own instance of a Flash player engine with all it's glory, making the use of flash with an Ajax application an expensive trade-off.

Furthermore, Flex + FABridge fails badly in applications which intensely manipulate the browser DOM:

For the start, browsers seem to reload the flash player content every time that a DOM node containing a flash object is momentarily detached from the tree and put back in again (This is typical of an Ajax application). Subsequently the control state is lost.

Secondly the FABridge will become really confused and crashes. This behaviour slightly changes from browser to browser.

IMHO your best to do your whole application in Flex if you're from the Flash camp or otherwise stick to browser's native controls. Mixing the two will only get you so far, which indicates that the Flex + FABridge is not yet ready to play a big part in Ajax applications.

Adobe, please be advised.

Your solution works well when you want to call a Javascript function on a Flex event.
In the case of "onload" event it is possible to use your solution because JS always starts earlier then flash movie.

But in our context your approach does not work.
In fact if you have a Javascript event (i.e. onmousedown on an HTML button) that needs to call an Actionscript 3 method,
you don't know if the swf movie has been already loaded.

The solution of using an ObjectManager, that I'll share with you soon, will solve all the issues.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About

This page contains a single entry from the blog posted on July 6, 2007 3:58 PM.

The previous post in this blog was The advantages of going open source with Flex 3.

The next post in this blog is Building a Rest Server with Zend and retrieve data with Flex and the HTTPService.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.33