Archive for the ‘Gotchas’ Category

Using JavaScript to handle Flash (ActionScript) events

September 10, 2007


While working on a recent project which involved building a video player, I came across an interesting design requirement.  I needed to have an integrated web page where events occurring in a Flash movie (Flash CS3 / ActionScript 3) could be handled by JavaScript functions.   To make it more fun, I didn’t know ahead of time what JavaScript functions might want to listen to the events, or even how many.  So, my conundrum  was:  How to create a multicast delegate in Flash that could be assigned in Javascript.  Fun, huh? 


Many of you may know already that Flash supports a number of methods for enabling communication from and to Javascript.  These have been well documented elsewhere, so I’m just going to focus on the method I chose, ExternalInterface. 

Now, ExternalInterface makes it pretty easy in most modern browsers to set up Flash-JavaScript communications.  It has a simple interface of two functions, one to expose an ActionScript function to JavaScript, and another to call a known JavaScript function.  The basic syntax is:“JsFunctionName”[, args]); // calls a JavaScript function from inside your Flash or Actionscript file, passing arguments as additional parameters after the string function name of the JavaScript function.

ExternalInterface.addCallback(“JsFunctionName”, AsMethod); // exposes the ActionScript method AsMethod to javascript under the javascript function name JsFunctioName, which is passed as a string. 

As a quick example, you could write“alert”,”Hello, world”); to have Flash instruct JavaScript to fire off an alert box that says “Hello, world”.  Alternatively, if you want to have JavaScript pass in style information to a Flash movie, you’d expose a setStyle() function from ActionScript like so:


and then have the JavaScript access it like so:

movieObject.setStyle(/*style information you’re passing*/);

A Few Notes and Gotchas

I did encounter some trouble in Paradise getting this far, when I did it the first time.  First ‘gotcha’, I needed to abstract the whole thing out as a component that could be loaded via javascript; I wasn’t going to directly mark up the html.  That’s not a huge problem, but for background purposes it meant I wanted to write a JavaScript object that could instantiate the movie when its constructor is called.  To save time developing that piece of the solution, I made use of the excellent SWFObject  library which takes care of most of the heavy lifting there for me.  Because the <object> / <embed> tags are being dynamically generated, I have the added advantage of bypassing the “click to activate” message you get with static flash tags.

The next note is that I needed to make sure that my JavaScript object maintained a reference to that embedded movie object, since I’d need to call those exposed ActionScript methods against that movie object.  So, one of the lines of code called when my JS object is instantiated is:

this._component = (window[this._id]) ? window[this._id] : window.document[this._id];

An odd line of code, resulting from the need to be cross-browser.  Basically, browsers get references to Flash movie tags differently, so this line tests to see if the first method (window[this._id]) returns anything.  If it does, then it sets this._component as a reference to it, and if not, it tries to get window.document[this._id]. 

Another gotcha which I discovered after quite a while is that IE (naturally…) doesn’t destroy instances of the movie correctly when a page is reloaded or the like. In fact, it fouls up the whole works.  To get it to work, in my constructor, I call,

if(navigator.appName.indexOf(‘Microsoft’) != -1)
window[this._id] = new Object();

that gotcha is well documented at Steve Kamerman’s blog and that’s how I got my object working correctly.

Adding the Event Callbacks

So, that all worked pretty well.  I came up with a plan to handle my need for multicast delegates by having my Flash movie maintain a list of javascript event listeners for each event that I was going to expose; more or less an Observer Pattern -inspired technique, but with the Observer being an actual function rather than an object implementing a given interface. 

As an example, my video component raises an event when the video starts playing, and then another event periodically to notify listeners what the current elapsed time is.  So, I created a list property which holds the external handlers and each external handler has to indicate which event it’s listening to,and provide a string name of the javascript function it’s going to call.  It does this by calling a function I exposed through ExternalInterface called

As registerJSListener gets called, the list of listeners is appended to.  I then have an Actionscript function that listens for, say, “play” events and iterates over the list of external handlers to fire them off in turn.  It looks something like this:

private function onPlay(ev:Event){
      var len = _externalHandlers.length;
      if(len <= 0) return;
      for (var i:uint=0;i<len;i++){
            var h:Object = _externalHandlers[i];
            if(h.event.toLowerCase() == ‘play’)

Interestingly, the object ‘ev’ is passed into the JavaScript function and all its basic type data elements (anything that can serialize into JavaScript) are available for use.  You can also pass a custom object if you want custom data to pass down, again so long as its properties are serializeable into JS (generally, I’ve stayed with basic types such as string, boolean, and integers so far).

One Last Gotcha…

I was feeling pretty good about myself after getting all that figured out and wrapped by my JavaScript proxy class (the registerJSListener call gets made by the proxy in response to another object calling its observe method, which looked like this:

observe : function(eventName,observer){
      if(typeof(observer).toLowerCase() != “string”)
               throw “Target of VideoPlayer.observe must be the string representation of a function name”;


  I wanted to keep that part syntactially in line with Prototype, since that’s what I was planning on using for the rest of the integration).  So, in my page load handler I tried the following:

var video = new VideoPlayer($(‘content’)); //where ‘content’ is the element I want the html inserted into.



and… I got an error in Javascript stating that _videoComponent didn’t have any properties.  _videoComponent is a private field in the VideoPlayer object that stores a reference to the flash player instance that my video is supposed to be playing in…

After a bit of debugging, I figured out that what was happening was that the movie wasn’t done downloading and getting ‘wired up’ so to speak with the flash player, and so it hadn’t exposed its ExternalInterface callbacks by the time my JavaScript was trying to execute them.

To solve the problem, I created an observer queue in the JS proxy that would hold onto those requests until the Flash component was done loading (at which point I had it call an onload function via which I set up to notify the proxy that it was safe to run those callbacks).  The new observe method looks like this:

observe : function(eventName,observer){
     if(typeof(observer).toLowerCase() != “string”)
          throw “Target of VideoPlayer.observe must be the string representation of a function name”

     if(this._loaded == false){ // the onLoad function hasn’t been called yet
          this._jsListenerQueue.push({evt:eventName,obs:observer}); // queue it up!


In order to allow the flash component to call that specific instance of the video player proxy in Javascript, I created some static methods (functions) in JS that were scoped to the page (in case I wanted to let other flash components use the same framework to add to the page). 

Those were:

flash = {}  // Just an empty object

// These next two are a pattern I found in the ASP.Net Ajax Framework for creating a singleton-style effect in JS.
flash._movies = null;
flash.getMovies = function(){
          flash._movies = [];
     return flash._movies;

/* When a Flash movie proxy starts loading the .swf for itself, it needs to register with the flash object; the id returned
     get_id needs to be included in the context variables (flashvars or other) so that the flash movie can get ahold of it
    through the root.loaderInfo.parameters collection. */
flash.registerMovieLoading = function(movieInstance){
    if(!movieInstance.get_id) throw ‘Movie proxy must implement get_id to uniquely identify itself’ on the page
     var m = flash.getMovies();
     m[movieInstance.get_id()] = movieInstance;

/* In the constructor of the flash object assigned as the document class of the .fla file,
     (‘flash.notifyFlashLoaded’) is called. */
flash.notifyFlashLoaded = function(id){
     var m = flash.getMovies();
     var movie = m[id];
     if(movie && movie.onLoad)


That’s basically it.  Let me know if there are any confusing parts that I can explain better.  This is a pretty handy technique and once its in place it makes communicating with Flash fairly transparent to other javascript objects. 

ASP.Net 2.0 Profile Gotcha — duplicate users

August 23, 2007

Had a bit of a brain dump that lead to way longer than I would’ve liked debugging, and I wanted to pass it on.  I was working on an admin page for user profiles and kept getting a new user created every time I tried to edit a profile.  After much wailing and gnashing of teeth I ended up finding that I’d set up my membership and roles providers earlier, and just now got to setting up the profile provider.  Well, as luck would have it I managed to *not* set the applciationName in the profile provider, where I *did* set it in the membership and roles providers.  I also had anonymous profiles enabled…   So, every time I tried to persist a profile element (or elements), the application would create a new anonymous user in a different application than my other users were in, but it would look to me like I was duplicating users b/c I was telling the app to create a profile for the user w/ the same name as the currently logged in User in the event that said User dind’t already have one.  Clear as mud?  Well, in any event, the Gotcha is that when you tell the Profile provider to create a profile for someone, it’ll also happily create a User object for that person if a User by that name doesn’t already exist, with no warning.  Nice feature, huh?  🙂