How to work around the lack of ExternalInterface.objectID in ActionScript 2

I would guess that not very many of those who read this blog have used ActionScript 2 lately. I have had the unfortunate luck of having to write some of it during the past few weeks and I don’t recommend it. However, I ran into a problem that I’d like to share the solution to, if anyone else would even find themselves in my position.

In ActionScript 3 there is a property on ExternalInterface called objectID that gives you the ID of the object or embed node in which the Flash movie is embedded. This makes it possible to get hold of this node and do all sorts of things with it, resize it, find out it’s position on the page, etc.

No such luck in ActionScript 2, there is to the best of my knowledge any way to get this value. Since part of my job was to find a way to get the position of the Flash movie on the page I had to find a way around this.

My solution is to scan through all object and embed nodes on the page and look for one with a uniquely named property. This property is actually a callback that I set using ExternalInterface.addCallback. It’s a bit of a strange situation that I can set properties on the node I’m looking for, but I can’t get the value of any properties. Since my code expects to run on a page with other Flash movies doing the same thing, it’s important that the property name is unique. I use a prefix and a random number between 0 and 1000 for this.

The code that scans through all nodes looks like this (prettyfied of course, in reality all whitespace is compressed and it’s stored in a string in the ActionScript code):

function findFlashNode( callbackName ) {
  var i;

  for ( i = 0; i < document.embeds.length; i++ ) {
    if ( document.embeds[i][callbackName] ) {
      return document.embeds[i].name;
    }
  }

  var objectNodes = document.getElementsByTagName("object");

  for( i = 0; i < objectNodes.length; i++ ) { 
    if ( objectNodes[i][callbackName] ) {
      return objectNodes[i].id;
    }
  }
}

I’d like to be able to shorten it further, because size is an issue in this case. Unfortunately getElementsByTagName returns a silly thing called NodeList, which isn’t an array, and doesn’t have the concat method, so two loops it is.

The complete ActionScript code looks like this (with the JavaScript above replaced by “…” to make it readable):

// generate a unique name
var name = "helloWorld" + Math.floor(Math.random() * 1000);

// add a property with the name by adding a callback
ExternalInterface.addCallback(name, this, function( ) { });

// run the code that scans the DOM for a node with the name
var objectId = ExternalInterface.call("...", name);

It’s an incredibly silly thing to have to do, but it works…

I really hope I haven’t missed anything… if there’s a simpler way to achieve this please let me know either in the comments or by answering this question on Stack Overflow.

3 Responses to “How to work around the lack of ExternalInterface.objectID in ActionScript 2”

  1. John Says:

    Well, I don’t really have anything substantive to add, except I never knew about ExternalInterface.objectID before this post! That totally changes the way I do things, such as resizing from javascript. Thanks for the inadvertent tip :)

  2. mmk Says:

    I found a strange behavior.

    Removing “classid” param from the object/embed code breaks that functionality.

  3. Zeh Fernando » Blog Archive » Getting the SWF’s HTML object/embed id from within the Flash movie itself Says:

    [...] also similar to this solution suggested by Flavio Caccamo, although at first I overlooked the article thinking it was too [...]

Leave a Reply