Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Interaction between Flex and Javascript

DZone's Guide to

Interaction between Flex and Javascript

· Web Dev Zone
Free Resource

Tips, tricks and tools for creating your own data-driven app, brought to you in partnership with Qlik.

When you think of a Flex application, what do you think of? An application that fills the entire screen and handles all the user interaction? That’s what I used to think of . . . until I spent some time using Pandora. For those of you who have not visited the Pandora web site, it is a website that allows you to input your favorite music artist or song name so that it can build a play list for you of many different artists that it thinks you may like. The service can be a lifesaver for anyone who, like me, is stuck working in a cubicle farm.

While viewing the site, I noticed a piece of functionality that made a lot of sense. After every few tracks the advertising would change. Now most people will not think of this as a big ticket item, but when you think that a flash or Flex application is designed to provide all your content to you without having to load a new page, this actually is a big deal. In a day and age when advertising rules the internet and everything is judged by clicks and impressions, updating your advertisements on a page is critical. What stuck out most about the advertisements was that the advertisements in both the player application and the HTML wrapper of the application changed simultaneously to the same advertising campaign.

It was then that I realized that the advertising of the page was being dictated by the player itself. Because I normally thought of a Flex application as a full page piece, I had never thought of the power that one can still have when only a few hundred pixels wide.

Combining Flex with Javascript gives you full control over the entire page, and combining this with the jQuery library allows you to easily manipulate the page and add effects and functionality. Accessing this functionality lies in what I like to call the “Flex One-Liners” category – a category of features in Flex that only take one line of code. Obviously, you will want to add additional lines of code for error handling and data checking, but the brains of these functions are only one line.

Flex talking to Javascript

To communicate with functionality outside of the Flex application, you will want to use the ExternalInterface Class. This class allows you to call functions that are available to the main page (wrapper) of the application. If you can call the function from the wrapper, you can call it from the Flex application. Making the call is easy; simply specify the function to call and then pass in the arguments, just like this:

ExternalInterface.call("remoteFunction",arg1,arg2);

In this example we are calling a Javascript function called remoteFunction and passing it the values arg1 and arg2, which are both variables in the main application. To consume this data in the main HTML page we would have a Javascript function like this:

function remoteFunction(val1,val2){
alert('Received data: ' + val1 + ' and: ' + val2);
}

It seems pretty simple, right? Well actually, it is that simple. Passing in your arguments in this fashion may not seem as efficient as you are used to. Possibly you are more used to passing in objects rather than simple values to your functions. Using the ExternalInterface Class, you have the ability to pass in complex objects if you wish. Here is a more complex example:

Flex:

private function sendData():void{
var obj:Object = new Object();
obj.firstName = "Simon";
obj.lastName = "Free";
ExternalInterface.call("receiveData", obj);
}

Javascript:

function receiveData(obj) {
alert("Hello " + obj.firstName + " " + obj.lastName + "!");
}

In this example the sendData function, which exists in the Flex application, builds an object with firstName and lastName and sends it to the Javascript function in the wrapper file. The receiveData function, which exists in the wrapper file, then takes the data and alerts the user of it. Even though in this example we are still only passing strings through in the object, you can pass in more complex data such as arrays if you need to.

Ok, now that we have seen the example, let's look at how we would put all this together in an actual application. As we only need to demonstrate the functionality right now, we won’t be creating an application that would necessarily be a real world example. In this example we will create a Flex application that lets the user select a color using a color picker and then sets the page’s background to that color.

First, let's look at the Flex code:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="400">
<mx:Script>
<![CDATA[
private function sendData():void{
if (ExternalInterface.available) {
ExternalInterface.call("updateBackground",cPicker.selectedColor.toString(16));
} else {
trace('Wrapper not available');
}
}
]]>
</mx:Script>
<mx:Label text="Please select a color:" horizontalCenter="0" fontSize="15"/>
<mx:ColorPicker id="cPicker" change="sendData()" horizontalCenter="0" />
</mx:Application>

As you can see in this example, we have a colorPicker that is set to call the sendData function when the color is changed. The sendData function does two things. The first thing it does is check to make sure that external interfaces are available. This check is making sure that the Flex application is actually being called from a page and not being called as an SWF directly. If the SWF is being called directly, then none of the wrapper will exist, and none of the function calls will be successful. The second thing it does is call the updateBackground function on the wrapper and pass in the selected color. Note that when using a color picker you will want to convert the value to a format that CSS can use. This is done by calling toString(16). Without this you will just get an integer value, and the background will not update.

Next let's look at the Javascript:

function updateBackground(color){
$("body").css("background-color",color);
}

In this extremely simple function, using jQuery, we select the body object and update the background color CSS property with the color passed in through Flex. Remember, when creating functionality in your Flex application that needs to access Javascript, you should add it to the index.template.html file in your projects html-template folder/ This way, when you run your code, the Javascript will be built with it.

Now that we have looked at Flex communicating with Javascript, we should look at the reverse of this. Just like Flex communicating with Javascript, Javascript communicating with Flex is pretty simple. As before, I had never really thought much about the necessity of it, especially when thinking of real world uses. It wasn’t until a few months ago that I really saw a use for it. As part of Apple’s Mac vs. PC advertising campaign, Apple placed two flash banner adds on the homepage of CNN. One banner was placed in the header, and the other was placed down the right hand side of the page. The advertisement involved PC climbing up the side of the screen and entering the header advertisement. This functionality could be accomplished through using timers within the advertisement, but what if there were load time issues between the two banners so that one banner loaded before the other. If timers were used, the flash movies would be out of synch and would lose some of the wow factor. Creating functionality that allows one flash movie to signal to the other either that it is ready or that a specific event has occurred would allow you to keep both movies in synch. This may sound a little complicated, but you will soon see that it is not. Let's take a look.

Javascript talking to Flex

Before we jump right into creating a page that has two Flex apps communicating with each other, let's first look at how we can pass data from Javascript to a Flex app. Just like before, we will be using the ExternalInterface Class. When creating your Flex application you will need to add a callback handler so that your application will know what to do when a call is made. This is very similar to adding an event listener, but since you do not have anything to add an event listener to, you should use the ExternalInterface Class instead. To add the callback you would use the following code:

ExternalInterface.addCallback("dataPosted", dataPostedHandler);

Using the addCallback function of the ExternalInterface Class, you specify the function you are listening for, in this case dataPosted, and you specify the function to call within your application when the function has been called, in this case dataPostedHandler. The dataPostedHandler function will accept the arguments that were passed to the application and will handle them as necessary. Here is a look at the example dataPostedHandler function:

private function dataPostedHandler(txt:String):void{
trace(txt);
}

In this example, only one argument is passed to the function and then traced within the application. As before, multiple arguments, as well as complex data types, can be passed to the function. If using complex data types, you must remember to change the data type of the accepted argument within the argument declarations. Otherwise you will receive an error.

To make the call in Javascript you would use the same syntax you normally would when making a call on any object, Flex or otherwise.

private function dataPostedHandler(txt:String):void{
trace(txt);
}

In this example, we are calling a function, sendData, which calls the dataPosted function on the myApp object. The myApp object is the ID of the Flex application dictated in the object tag in the HTML. The function then passes in the value of a text input that is located in the HTML of the page.

While developing your application, rather than using the ID of the object, you could place the function in the index.template.html file and use one of the variables that is replaced when the code is generated. Doing that would result in a function that looks like this:

function sendData(){
${application}.dataPosted(document.getElementById("supText").value);
}

The ${application} variable is the same used for the ID of your generated object tag. If you use this method, you do not have to worry about naming issues.

Now that we have seen how the basic tags look, let's delve into a real application. This application will demonstrate two Flex applications, each of which talks to the other and triggers events that the other will pick up. This is similar to the Mac vs. PC example, although it is less of a real world scenario. In this example we will have two arrows, one that will traverse the two Flex applications from left to right and one that will traverse the two Flex applications from right to left. The tricky thing here is that instead of creating 2 separate applications, we will create one application that will be placed twice on the page.

Rather than show you all the code, which has a lot of code specific to the example and not the communication, I am going to point out a few key pieces of functionality and let you review the rest of the code at your leisure.

The first important part of the application is in the init function. Within this function we decide which application we are, the left one (appID of 1) or the right one (appID of 2). This information is extracted from the FlashVars in the object tag in the wrapper. This value will be used for most of the decision making processes in the application. The second important part of the init function is adding the callback, which will listen for the receiveArrow call, to the ExternalInterface Class. Remember, no matter which version of the application it is, left or right, they both will have the receiveArrow function called on them, and both of them will dispatch the sendArrow externalInterface call. The left application dispatches the blue arrow and receives the red arrow, and the right application dispatches the red arrow and receives the blue arrow.

The next important part of the application is the startAction function. This function is called by clicking on the button at the bottom of the application. Depending on which application it is that you are clicking on, it will build the required arrow image, set up the parameters of the move object, and then start the move object. Once this has begun, it will start a timer which will periodically check the location of the image via the monitorPosition function. If at any time the monitorPosition function finds that the x co-ordinate has reached a certain point, it will make the externalReference call to the sendArrow function and pass in the ID for the other application. Notice that I chose to use a timer (rather than the tweenUpdate event of the Move object) to check the position of the image. The tweenUpdate event fires extremely fast, as there are many updates that occur. Because of this, it is very difficult to trap the initial time that the image has moved into the area at which you want to fire the command. As a result, if you use the tweenUpdate event to check the position of the image, the command will fire 10 - 20 times before you can flag it as having already occurred. The result is that as soon as one of the arrows gets to the other side of the application, 10 - 20 arrows suddenly appear on the other application. It may look comical, but it does not have the effect we are looking for. Using a timer gives us just enough of a gap between calls to register the first occurrence and block the rest.

The final piece of code I want to draw your attention to in the Flex application is the receiveArrowHandler function. This function is called via Javascript when one of the applications has an arrow that it wants to pass over. This function, depending on which application it is called by, fires the corresponding arrow to complete the effect of an arrow passing all the way from one application to another.

The necessary Javascript for the application pales in comparison to the lines of Flex code needed, which to be honest is not that many in the first place. The Javascript function needed on the wrapper page is:

function sendArrow(appID){
if(appID == 1){
${application}1.receiveArrow(appID);
}else{
${application}2.receiveArrow(appID);
}
}

As you can see, the function simply receives the appID from the calling application and then sends that appID to the other application, thus allowing for communication to occur between the two applications.

As you have seen in these examples, it is very easy to allow Flex applications to communicate with Javascript and Javascript to communicate with Flex applications. The biggest hurdle to get over is the vision that a Flex application by default must consume the entire page or that all its inputs must be received through the Flex application or remote calls. Once you have gotten over that hurdle and opened your mind to the different possibilities, you will be able to expand your applications into the realms of Pandora and Apple advertising campaigns. One final note of caution is that when creating applications that can have functionality called on them, do not allow those functions to access sensitive data. These calls can be hijacked, since everything that runs through Javascript can easily be monitored. Even passing a secret key between applications would not be a good form of security, because an application such as Firebug could easily find out the data. The best form of security for this form of communication is simply to not create functionality that can manipulate sensitive or important data.

Explore data-driven apps with less coding and query writing, brought to you in partnership with Qlik.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}