FlashObject turns 1

I just realized that it’s been over a year (a year and four days to be exact) since I first posted the FlashObject script.

Since then it has been used on countless websites, ranging from tiny sites to entertainment sites to huge mega-corporation sites. It has also been distributed with Adobe Photoshop, and included in a Javascript library (I heard there were plans to include a version of it with MochiKit, but I think Bob was side-tracked).

It has support for all the latest Flash goodies like ExpressInstall, ExternalInterface, and has been tested for accessibility and passed with flying colors (even though they spelled my name wrong).

It has also been packaged up as a Dreamweaver plugin, a WordPress plugin, and a Textpattern plugin.

Normally something like this would have to be accompanied by giving stuff away, but since FlashObject is already free, I guess that idea is shot.

Instead, I’d like to give everyone a chance to show off the sites they have used FlashObject on by including a link to the site in the comments of this post.

Drawing with Javascript and Flash

David Flanagan (you probably have his O’reilly Javascript book next to your desk right now) has been doing some experimentation with exposing the Flash drawing API -vector, not the bitmap stuff (yet)- to Javascript. In his example he uses the ExternalInterface class to expose a few of the drawing methods and then uses those to draw shapes in the Flash movie.

His example only had an embed tag, so here is another example embedded with FlashObject so you IE people can see it too.

Note: Opera does not support ExternalInterface (yet), so if you want to see it in action, use just about any other browser. Opera users: you may want to take a moment to send a new feature request to Opera and tell them to add in the NPRuntime stuff so this will work!

RegExp in Flash 8 using ExternalInterface

After posting about the new ExternalInterface class in Flash 8, there was a comment suggesting the use of it to get Regular Expression functionality into Flash. Well, I thought that was a fine idea, and it turns out it’s pretty easy to implement.

I’ve already covered some of the uses of ExternalInterface in this other blog post. It focuses on sending values from an HTML page into the Flash movie. That’s only half of what makes ExternalInterface so cool. Another way to use it is to call a Javascript function in your HTML page from your Flash movie and have it return a value.

If you want to jump right in, here’s my RegEx in Flash example page.

For this example I added two methods to the String class: String.match and String.replace. I used the prototype object because it’s the quickest way to add it in. Here’s the code in Flash:

// add match to String
String.prototype.match = function(reg) {
   var arr = ExternalInterface.call("reMatch", escape(this.toString()), escape(reg));
   for (var i=0;i<arr.length;i++) {
      arr[i] = unescape(arr[i]);
   }
   return arr;
}
// add replace to String 
String.prototype.replace = function(reg, rep) {
	return ExternalInterface.call("reReplace", escape(this.toString()), escape(reg), escape(rep));
}

As you can see, the code is very simple. When using ExternalInterface.call, the first argument is the name of the function you want to call in your HTML document, and the rest are arguments you want to pass in to it. The Flash player takes those values, passes them to your Javascript function and sends the result back in real time.

In my HTML document, I added two functions to handle the RegExp calls and return the values:

// RegEx replace
function reReplace(str, reg, rep) {
   var s = unescape(str);
   var re = new RegExp(eval(unescape(reg)));
   return s.replace(re, unescape(rep));
}
// RegEx match
function reMatch(str, reg) {
   var s = unescape(str);
   return s.match(eval(unescape(reg)));
}

// escape the values in the array because 
// ExternalInterface doesn't escape some properly
function encodeArray(arr) {
   for (var i=0; i<arr.length;i++) {
      arr[i] = escape(arr[i]);
   }
   return arr;
}

There’s a few more lines added in that test for the existence of ExternalInterface by checking the ExternalInterface.available variable. If that returns false, I redirect the user to an upgrade message inside the swf file.

For most people this would be plenty of support for RegExp, but if you wanted even more control, it should be fairly easy to write an entire RegExp class that uses ExternalInterface and some Javascript functions to get full Regular Expression support into Flash.

Here’s a link to the example page again:
RegExp in Flash 8 using ExternalInterface.

UPDATE: Just wanted to add a link to a little RegExp class I found via Google. Looks like a nice alternative if you don’t mind the 20k file size.

UPDATE (2-24-2005): Updated this code to fix a couple bugs with non-escaped chars. This all works except when trying to match spaces. It looks like the Flash player has issues encoding spaces when using ExternalInterface. If you try to match something like /s/g, you’ll get an array of ‘null’s back. I’ve also recreated the original fla file and zipped it up for download.

UPDATE: I went ahead and added a few more lines to the code so all the characters are properly escaped. Every regex you throw at it should work now.

How accessible is your Flash embed?

There’s an interesting article over on the Macromedia Accessibility blog. They take a look at some popular Flash embed techniques and see how they perform in screen readers. The thing that caught my eye, though, was the performance of the Flash Satay embed method. It looks like if you are using Flash Satay, JAWS won’t read your Flash content.

Unfortunately, they didn’t test FlashObject, but they did test UFO – which works in a very similar way – so I think it’s pretty safe to say that they would behave the same way in a screen reader.

Flash 8: Using ExternalInterface

Another cool new feature in Flash 8 is the ExternalInterface class. This is a new method of talking to the Flash player using Javascript. It works by registering functions inside the Flash movie that external Javascripts can call. It works in all the major browsers including Internet Explorer 5.0+, Firefox 1.0+, Mozilla 1.7.5+, Netscape 8+, and Safari 1.3+. Opera is left out because apparently it doesn’t support a new plugin scripting standard, specifically the ‘NPRuntime interface’ which was recently developed jointly by a bunch of browser and plugin makers. But I suppose one could argue that Opera 8 is not a ‘major browser.’

Here’s how it works (view ExternalInterface example page):

Set up a function in your Flash movie that you want to be accessible from Javascript.

function callMeFromJavascript(arg1, arg2, ...) {
    // do stuff
}

Then, to make the function available to the browser, you use the ExternalInterface class to register the name of the function:

var connection = ExternalInterface.addCallback("myFunctionId", null, callMeFromJavascript);

This registers the function in your Flash movie (callMeFromJavascript) as “myFunctionId” outside of the player. The null value is meant to be an object or movieclip that the ‘this’ keyword would reference in your function. If you don’t get this part it’s fine, for most uses you won’t need to use it and can just use null. Then, when you want to call the function from your Javascript, you would use this code:

var myFlashMovie = document.getElementById("flashId");
myFlashMovie.myFunctionId();

Notice that we use the ID of the Flash movie’s object/embed tag to call the internal Actionscript functions. This means that you must have an ID on your object tag and your embed tag. Now the catch to that is IDs on HTML elements are supposed to be unique in each page. The way we get around this is by using FlashObject. When FlashObject detects the Flash player, it also chooses whether to use an object tag or an embed tag to embed the movie in the page, and since it picks one or the other, it can put the ID on whichever tag it chooses and you won’t have any duplicate IDs on the page.

If you are not using FlashObject, you must use slightly different code to access the internal Actionscript functions. Here’s an example of what it might look like:

var myFlashMovie = document.embedName;

That’s it. Here’s my example page that sends some basic calls into the Flash movie. Unfortunately, I can’t release the source fla file until Flash 8 is released, but the code you need is all here, so you can get to work testing it out using Flash 7 if you just jump through some hoops to make a Flash 8 swf.

Also keep in mind that ExternalInterface is not just for HTML pages. Darron Schall has put together a little C# wrapper that can talk to Flash using ExternalInterface.