This article tells the story of how Flash 8 movies learnt to fluently converse with Javascript using the ExternalInterface “API” in XHTML strict.
The ExternalInterface is an ActionScript class that was introduced in Flash 8. It allows a Flash movie to communicate with the Flash Player container using ActionScript code. The Flash Player container is in 99.9% of cases a web page, hence the Flash movie is most often calling Javascript functions, either standard built-in Javascript functions or Javascript functions defined by us, usually in an external *.js file. Using the ExternalInterface class, we’re also able to let Javascript functions invoke ActionScript functions defined in the SWF movie. These Javascript and ActionScript functions can bear arguments and return values, and there can be as many of them existing on both sides of the communication bridge. Let’s keep that in mind.
The communication will fail when :
allowscriptaccess is not set to “always”. (An exception to this is Firefox : testing locally with allowscriptaccess set to “always” won’t work, due to security reasons. In Internet Explorer, if you allow “active content” to be run locally, then you will not run into any problem.) The biggest challenge is certainly to get a handle to the XHTML element in the Document Object Model (DOM) tree that stores the Flash movie. It’s through getting that handle (a handle to an element node) that we can open communication back and fro the Flash Player and our Javascript code. Most Flash books and the Macromedia documentation presents a quick and dirty way for getting such handle, under the cover of “you don't need to understand what's going on here”, a method based on the way Flash “objects" are usually embedded in HTML, using both the object and embed tags. This article provides an alternative method that will have as repercussions that 1- we won’t be shooting in the dark, not understanding what the hell we’re doing, and also that 2- our web page will validate as strict HTML or XHTML.
We can use a Javascript library to properly embed a Flash “object” on a web page, or we can simply use W3C-compliant (X)HTML markup.
The disadvantage of using a Javascript library is that we’re using Javascript. (But then again, if we use the ExternalInterface class, we’re gonna use Javascript anyway to allow communication between the movie and the web page.) One advantage of using Javascript is that in Internet Explorer version 6 and higher, the movie won’t have to be activated with a click of the mouse in order to start playing. It will start playing automatically as soon as the embedding script is run.
| Name | Link | Size | License | By | From | Ease |
|---|---|---|---|---|---|---|
| UFO | v3.20 | 11k | CC-GNU & Open Source | Bobby van der Sluis | Amsterdam | +++easy |
| SWFObject | v1.4 | 7k | MIT | Geoff Stearns | Indianapolis | +easy |
Important thing to keep in mind : The SWFObject and UFO *.js files are scripts that allow us to add one ore more Flash movies to the DOM (Document Object Model) tree, after that Document Object Model tree has been built, that is, when all the xhtml has been parsed. How do we know when the DOM tree is built ? We wait till the browser event window.onload is captured. Then, a few calls to the SWFObject or UFO Javascript library result in the dynamic insertion of a Flash movie in the document tree. We will not see any Flash movie markup when we do a View Source in the browser : we will only see a placeholder element with a specified id attribute. To examine the Flash “object” as part of the document, and as content of the “placeholder element”, we need to inspect the DOM tree. Free tools are available to inspect the DOM tree in Internet Explorer and Firefox.
The Commercial License for the IE WebDeveloper (formerly known as the IE DOM Inspector) is 79 US$ while the Non-Commercial License is 59 US$. You may download the “add-on” evaluation version and try it for 15 days, then kiss it good-bye. You may download the older version (good old IE DOM Inspector) and try it for 15 days then kiss it good-bye as well. A much better and extremely suitable alternative is to install the free beta Internet Explorer Developer Toolbar. Works in IE6 and IE7. For ever. Then click on “View DOM”.
Give the Flash “object” in the document tree a unique id attribute.
Set the Flash allowscriptaccess parameter to “always” if we are to test our web page locally. By locally, we mean NOT a server. (In Firefox, testing locally with allowscriptaccess set to “always” won’t work, due to security reasons. In Internet Explorer, if we allow “active content” to be run locally, then we will not run into any problem.) If we test the page by typing http://localhost/index.html in the browser, we are not testing locally, hence we do not require to set the allowscriptaccess parameter to “always”, and as a matter of fact we do not need to set it to anything :
For Flash movies played in Flash Player 8 or any later version, the default value for the
allowscriptaccessparameter is “sameDomain”. That means that if we do NOT set this value ourselves, the Flash player decides that the behavior of the movie is to be as if this parameter was set to “sameDomain”. If theallowscriptaccessparameter is set to “sameDomain”, or is not set to any value, Flash-Javascript communication is possible if the *.swf file and the html web page are contained in the same web root folder, that is, reside in the same “domain”.
Copy the ufo.js file in your scripts folder.
Link the file in, in the <head> of your XHTML file :
<script type="text/javascript" src="javascript/ufo.js"> </script>Create a new .js file and link it in as well.
In that Javascript file, type this code (you may already be capturing the window.onload event in another file ; in that case add a function call in the other file, and define that function here) :
var FO = { movie:"movie.swf", width:"550", height:"100", majorversion:"8", build:"0", id:"ufoElementNodeId" };
window.onload = init;
function init() {
UFO.create(FO, "ufoPlaceHolder");
}For the FO (flash object) variable, the first five parameters are required, including the build number. To use the ExternalInterface, we absolutely need to specify an additional id parameter : this will give the element node that will store the Flash movie a unique id, and we need this id to invoke ActionScript functions defined in the Flash movie. Add an allowscriptaccess parameter and set it to “always” if you’re testing locally. The parameters for the FO variable (within brackets) can be listed in any order. Other parameters can be added, such as “wmode”. UFO is a static class : in other words, don’t change that word, UFO. The second argument passed to the UFO method create() is the unique id we’ll give to the placeholder element of the Flash movie in the next step. Do not confuse 1- the element that stores the Flash movie with 2- the element that contains that element, a.k.a the placeholder element. The placeholder element has an id attribute set to “ufoPlaceHolder” in our example (you can substitute with any other value). The placeholder element can be a <div>, a <span>, or a <p>. Whereas the element that will store the Flash object is either an embed element or an object element, depending on the browser. (In Firefox and IE7, it’s an object.)
Determine the location in the XHTML file where you want your movie.swf to be inserted. Create an element (a paragraph, a div or a span), and put in that element whatever you want the browser to display if the movie cannot be loaded and played. Do not put anything else in there. If the movie can be loaded and played, all content of that element will be replaced with the Flash element (object or embed element) :
<div id="ufoPlaceHolder">
<p><a href="http://www.macromedia.com/go/getflashplayer"><img src="http://www.macromedia.com/images/shared/download_buttons/get_flash_player.gif" alt="Get macromedia Flash Player" /></a></p>
</div>Test run your xhtml file. Is the Flash movie displayed ? Are your testing on a server, local or remote ?
Take note of the unique id you gave to the UFO Flash object. In our example, it was ufoElementNodeId.
Inspect the DOM tree.
Troubleshoot.
Take a break.
The UFO class uses a Javascript object literal notation. The advantage is that you can pass to it any number of parameters in any order : myObject = { x:1, y:2, z:3... }.
Copy the swfobject.js file to your scripts folder.
Link the file in, in the <head> of your XHTML file :
<script type="text/javascript" src="javascript/swfobject.js"> </script>Create a new .js file and link it in as well.
In that Javascript file, type this code (you may already be capturing the window.onload event in another file ; in that case add a function call in the other file, and define that function here) :
var so = new SWFObject("movie.swf", "swfObjectElementNodeId", "550", "100", "8", "#000");
window.onload = init;
function init() {
so.write("swfObjectPlaceHolder");
}The constructor of the SWFObject takes 6 arguments, and all are required. The second argument specifies a unique id for the Flash object. We will use that id to invoke ActionScript functions defined in the Flash movie. You can specify additional Flash parameters using the method addParam(). For example, if you are testing locally, you will add this line before invoking the write() method :
so.addParam("allowscriptaccess", "always");The argument that is passed to the method write() is the unique id we’ll give to the placeholder element of the Flash movie in our next step. Do not confuse 1- the element that stores the Flash movie with 2- the element that contains that element, a.k.a the placeholder element. The placeholder element has an id attribute set to “swfObjectPlaceHolder” in our example (you can substitute with any other value). The placeholder element can be a <div>, a <span>, or a <p>. Whereas the element that will store the Flash object is either an embed element or an object element, depending on the browser. (In Firefox and IE7, it’s an object.)
Determine the location in the XHTML file where you want your movie.swf to be inserted. Create an element (a paragraph, a div or a span), and put in that element whatever you want the browser to display if the movie cannot be loaded and played. Do not put anything else in there. If the movie can be loaded and played, all content of that element will be replaced with the Flash element (object or embed element) :
<div id="swfObjectPlaceHolder">
<p><a href="http://www.macromedia.com/go/getflashplayer"><img src="http://www.macromedia.com/images/shared/download_buttons/get_flash_player.gif" alt="Get macromedia Flash Player" style="border: none;" /></a></p>
</div>Test run your xhtml file. Is the Flash movie displayed ? Are your testing on a server, local or remote ?
Take note of the unique id you gave to the SWFObject Flash object. In our example, it was swfObjectElementNodeId.
Inspect the DOM tree.
Troubleshoot.
Take a break.
We can embed the Flash object without any embed tag, and without Javascript. The result is strict xhtml that validates :
<object type="application/x-shockwave-flash" data="movie.swf" width="550" height="100" id="flashMovieId">
<param name="movie" value="movie.swf" />
</object>The Flash movie id in this example is flashMovieId. Take note of the id you choose to give to the object element. You will need it to invoke ActionScript functions defined in the Flash movie, from your Javascript code.
The Strict xhtml Document Type Definition states without ambiguity that the <object> element is an inline element, not a block element.
A block-level element is laid down on the page as if there was a linebreak before and after it. The <p> element is an example of a block element. Block-level elements pile up one on top of the other. Headlines, blockquotes, <div> tags, tables and lists are other examples of block-level elements. Inline elements don’t create a linebreak before or after them. They appear on the same line as content and elements beside them, they are inline with the text. They are laid next to one another horizontally, from left to right, until they fill the width of the container element, then they continue on, on the next line. That means that if you put two Flash objects side by side in the markup, they will end up side by side on the page if the width of the container (parent) element is large enough to accomodate their width.
While we’re at it, let’s list the five subsets of inline elements, as specified by the Strict xhtml DDT :
- First, there is the
%specialsubset : br, span, bdo, object, applet, img, map, iframe.- Then we have the presentational markup subset : tt (teletype), i, big, small, u, s, strike, font, basefont.
- Then we get the
phrase markupsubset : em, strong, dfn, code, q, sub, sup, samp, kbd, var, cite, abbr, acronym.- We also have the form markup subset : input, select, textarea, label, button.
- In the fifth subset, we have elements which, depending on their container element, are either inline or block elements : ins, del, script, noscript.
A question that we may ask ourselves is : can we put a Flash <object> inside an anchor element, to make it clickable, just like we can with text or an image ? The answer is yes, we can put an <object> element between <a> tags.
According to the Strict xhtml DDT :
- An anchor element cannot contain another anchor element.
- An anchor element can contain any other inline element (see list in the preceding box). The definition is clear : the child element of an anchor element can be an <object> element, as the object element is part of the %special inline subset.
If we do put a Flash object element inside an anchor element, will it be clickable, and will the browser load the page with the URL specified in the href attribute... in the window ? The answer is yes in Firefox, and no in Internet Explorer. A quick and dirty way to circumvent the limitation (bug?) in Internet Explorer is to add a behavior to the Flash movie clip in the Flash Development Interface (do not bother writing ActionScript for this if the url is a constant) : the action would be Go to Web Page... and the event would be On Press. If you want to code it yourself, use the ActionScript function getURL(url:string, target:string). Use "_self" as target if you want the browser to open the page in the current window.

At this point, we should have scribbled on a post-IT the id value of our Flash <object> (and not the id attribute of its placeholder element). But the thing is, we won’t need this value just yet. We will need it in the next section, when our Javascript will talk to our Actionscript.
If we’ve used verbatim the code from the preparation section (STEP 1 of 3), this id will have the following value — given that we’ve used either the UFO library, the SWFObject library, or just plain XHTML markup :
| Method | id attribute |
|---|---|
| UFO | ufoElementNodeId |
| SWFObject | swfObjectElementNodeId |
| XHTML markup | flashMovieId |
Open your *.fla file in Flash 8. Find the layer and frame where you put your ActionScript code. Type in this line :
Let’s take a look at the ExternalInterface class. In the Actions panel, in the upper-left corner, look under ActionScript 2.0 classes → flash.external package. We have only two methods at our disposal : call and addCallback. We can do anything with them. Call-ing is picking up the phone to reach Javascript, whereas addCallback is leaving Javascript with a business card : If you need to call me, here’s my number. You may call me at any time. That number is for asking me how I’m doing. I am sitting by the phone, not exactly waiting for you, but always ready to pick up. I have this other number if you need me to ask you how you’re doing.
In this section, we will use the method call.
| Method | Description | How to use the method (blueprint) |
|---|---|---|
| addCallback | Registers an ActionScript function as callable from the container (i.e. browser). | public static addCallback(functionNameInJavascript:String, instance:Object, method:Function):Boolean |
| call | Calls a function exposed by the Flash Player container, passing zero or more arguments to it. | public static call(functionNameInJavascript:String, [argument1:Object]):Object |
The “public” keyword means that we can call these methods from outside of the class definition (i.e. we can use them, period). The keyword “static” means that we call these methods on the class itself. We need not create any instance of the ExternalInterface class. It really is just like the Math class : we use the class Math by calling methods on Math, such as Math.random(). With the ExternalInterface, it’s the same thing.
So many things can turn sour when trying to use the ExternalInterface... At this point, we ought be able to call a built-in-core Javascript function such as alert(), to engage the browser into a one-way conversation. Try this before anything else :
We can pass any number of arguments, required by our Javascript function, to the method ExternalInterface.call(). Arguments have to be separated by a comma. The second argument passed to the ExternalInterface.call() method will become the first argument used by our Javascript function. The third argument passed to ExternalInterface.call() will become the second argument used in our Javascript function. And so on.
In addition to this, we may record whatever value is returned by our Javascript function. To do this, we simply record the value returned by the call method. The method is ready to return an Object, that is, anything at all :
public static call(functionNameInJavaScript:String, [argument1:Object]):Object
Again, let’s try something ultra-simple. Core Javascript comes with a prompt() function, that prompts the “user”, through a dialog box, for a value.
We call the function prompt like this : prompt(question, defaultAnswer);
null.Let’s call that built-in function and display the value provided by the user in the Flash movie. On the stage, create a dynamic input text area with the following properties :

Then type in the following code in your *.fla file :
Republish the movie (making sure not to overwrite your html file), clear the cache in your browser and reload the web page. A dialog box will pop up. Try cancelling the dialog box ; reload the page, and try to ok the dialog without changing the default value ; and finally, reload and change the value then press ok.

We first determine if the value returned is defined. If it is, we “type-cast” that value into the type (String, Number) that was used by the Javascript function. Thereafter, the value is “ready to use” in our Actionscript.
| The type we want | “Type cast” |
|---|---|
| String | String(someValue) |
| Number | Number(someValue) |
There is absolutely nothing special about calling custom Javascript functions, compared to what we’ve seen so far. We have to define these functions in our Javascript file, a file with extension *.js (and link in that file in the web page <head>). That’s the only extra step. In the next section, we’ll make sure that a function defined on the Actionscript side of the communication bridge works “as is”, i.e. behaves as it should when called in our Actionscript code. In the same way, we really should make sure that our Javascript functions work on their own, when called from the *.js file, before we attempt any communication back and fro. That’s it for this section !
At this point, we’ll finally make good use of the id value of our Flash <object> (and, again, that’s not the id attribute of its placeholder element). We will call Actionscript functions from our *.js file using very basic Document Object Model scripting :
If we’ve used verbatim the code from the preparation section (STEP 1 of 3), our id will have the following value — given that we’ve used either the UFO library, the SWFObject library, or just plain XHTML markup :
| Method | id attribute |
|---|---|
| UFO | ufoElementNodeId |
| SWFObject | swfObjectElementNodeId |
| XHTML markup | flashMovieId |
Open your *.fla file in Flash 8. Find the layer and frame where you put your ActionScript code. Type in this line :
Let’s take yet another look at the ExternalInterface class. In the Actions panel, in the upper-left corner, look under ActionScript 2.0 classes → flash.external package. The ExternalInterface class has two methods : call and addCallback. Using the method addCallback is like leaving Javascript with a particular business card : If you need to call me because you want me to do this very precise thing, dial that number. You may call me at any time. I am sitting by the phone, not exactly waiting for your call (I have movies to play), but I am ready to pick up. And oh, I have this other number if you need me for this other thing...
In the previous section of this article, we invoked the method call whenever we needed to say something to the browser. With addCallback, we leave our number once. However, we leave as many different numbers as there are tasks we’re ready to perform.
| Method | Description | How to use the method (blueprint) |
|---|---|---|
| addCallback | Exports an Actionscript function so that it becomes callable from the container (i.e. browser in our case). | public static addCallback(functionNameInJavascript:String, instance:Object, method:Function):Boolean |
| call | Calls a function exposed by the Flash Player container (i.e. a named Javascript function), passing zero or more arguments to it, and getting a return value | public static call(functionNameInJavascript:String, [argument1:Object]):Object |
The “public” keyword means that the call and addCallback methods are exposed to the outside world, and not only used internally in the class definition. The keyword “static” means that we call the methods on the class itself, using the dot syntax : ExternalInterface.method(). We need not create any instance of the ExternalInterface class.
While the first parameter “functionNameInOurJavascript” is a string, and is the phone number we give to our Javascript, myFunction is the name of a function defined in our ActionScript, “only for internal use”. Communication takes place in the following way : whenever our Javascript makes the following “phone call” :
The Flash player, who has that phone registered in its phone book (for the Flash movie with unique id flashMovieId) invokes the corresponding ActionScript function myFunction.
Our example will involve actual talk, even if that’s not very original. From our Javascript, we will send some text to display (nicely) in the Flash movie. We need an XHTML form for this, with a text input and a submit button. When the DOM tree is built, we will register an event-handler function on this form onsubmit property.
Here is some basic markup for the form :
The form is very basic. We should style it using CSS.
In our *.js file, we register our event-handler function on the form’s onsubmit property once the web page is loaded :
The Javascript updateFlash() function needs to be defined. This function will dial-up the phone number associated with a particular Flash task. In our example, this phone number, as it is defined in the Flash *.fla file, will be sendTextToFlash.
There are two things we need to do for each task that Flash is ready to accomplish “on call” : give out a card with a phone number, and set up a function to accomplish the corresponding task.
In our example, the Flash movie will have to display text that Javascript will send to it. On the stage, we create a dynamic input text area with the following properties :

On the layer and in the frame where we put our ActionScript code, we type this :
Again, “sendTextToFlash” is a phone number, it is to be used by the container, i.e. in the Javascript. Whereas updateText is the name of an Actionscript function, that we need to define — and test locally !
If Javascript is calling our “phone number” with arguments, we need to mirror the way both these functions are constructed : sendTextToFlash in our Javascript, and updateText in our Actionscript. We set our type-casting in the way that we define the function updateText(). The value someValue sent when calling sendTextToFlash(someValue) in the Javascript — whether that’d be a number or a string — will be type-casted into a String in our ActionScript if we say it so in our function’s definition :
...