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.

Using Flash Player Express Install with FlashObject

Please note that the newest version of FlashObject (1.3) changes how ExpressInstall is invoked when using FlashObject. Check out the FlashObject page for examples of using ExpressInsatll.

I’ve just updated FlashObject (now version 1.2.3) to support the new Macromedia Flash Player Express Install.

Macromedia recently introduced a new feature of the Flash Player called “Express Install.” This new method of upgrading offers a few very nice benefits:

  • No need to redirect your users to Macromedia.com to upgrade their player.
  • No need to rely on built in browser upgrade mechanisms. Internet Explorer users have become more and more wary of trusting the ActiveX install dialog box that pops up all the time and is generally associated with spyware or malware. While Firefox has an excellent plugin finder, other browsers that use the Netscape plugin architecture aren’t so fancy.
  • Nearly full control over the upgrade experience, which means no matter what platform your users are running, you will be able to walk them through a nearly identical install proccess.

Because of these benefits, Express Install is now my recommended upgrade method. When used in conjunction with FlashObject, it offers the best possible user experience for your users who need to upgrade their Flash player.

Here’s how it works:

First, add Express Install support to each of the swf files that may require an upgrade. These files need to be at least 215px x 138px in size. This is so the entire upgrade dialog can be seen by the user if the Express Install is triggered. It may also be a good idea to only place one swf with Express Install functionality on each page. This way users won’t be greeted with multiple upgrade dialog boxes and be forced to choose one (keep it simple for your users!).

I’ve included a new AS2.0 class in the latest version of the FlashObject script called ExpressInstall.as – this class contains all the code needed to invoke the Express Install process. All you need to do is place the script somewhere in your Flash class path, and place this code on the first frame of your swf:

if (ExpressInstall.init()) {
    stop();
}

The ExpressInstall.init() function returns true or false depending on whether the Express Install was started. If it starts, it returns true, if it doesn’t start, it returns false.

All other functionality should be moved to at least the second frame of the swf. This ensures that even someone running Flash player 6.0.65 can view the first frame of the movie and will see the upgrade dialog.

Next, you’ll need to upgrade your FlashObject script from 1.2.2 to 1.2.3 (you can get FlashObject here) and alter the embed code slightly only for the swf files that contain the Express Install code.

The new embed code should look like this (view example page):

var fo = new FlashObject("myswf.swf", "myswf", "400", "300", "8.0.22", "#fffff", true);

The only thing that changes is one more parameter after the color set to true. This does three things:

  1. Tells the FlashObject script that you want to allow for ExpressInstall. The script then gathers the needed information and passes that information into your Flash movie using flashvars.
  2. Checks to make sure the user has at least Flash player version 6.0.65 installed – this is the lowest version that supports the Express Install process.
  3. Then, if the user has at least version 6.0.65, but also has a version less than the required version specified in the FlashObject embed (in this example it was “8.0.22”), the Express Install process is started.

Once the install is completed, the installer launches a new browser window, and the user is redirected back to your original page with the new plugin.

And that’s it. You can grab the newest version of FlashObject with the ExpressInstall class here: http://blog.deconcept.com/flashobject/ or you can view an example page that uses this method.

UPDATE (08-18-2005): Macromedia recently updated the Express Install feature, and because of this, my ExpressInstall class was broken. I’ve just fixed it, however, and you can get the latest version by downloading the latest version of FlashObject here.

UPDATE (08-29-2005): If you are not using Actionscript 2, or are exporting your classes on a frame after frame 1, you can use this adaptation of my ExpressInstall class that Carlos Rovira wrote.

UPDATE (12-22-2005): If you are using ExpressInstall on your site, go tell Macromedia what you think about it.