Update: A few months after writing this journal entry, I developed SCORM class files for ActionScript 2 and ActionScript 3 (both require ExternalInterface). Check them out here.

For the last week, I’ve been doggedly attempting to create a hybrid of Flash-to-JavaScript communication techniques for creating cross-browser SCORM-conformant courses that work with almost any version of Flash Player. Today I threw in the towel. Here’s my story.

Some background on SCORM in regards to JavaScript and ActionScript

  • SCORM is a standardized method of communicating between a web-based course and a Learning Management System (LMS).
  • SCORM communication is most commonly handled by JavaScript.
  • A Flash-based course therefore needs to communicate with the JavaScript in an HTML file in order to send SCORM calls to the LMS.

It looks like this:

course communication: AS to JS to LMS

Unfortunately, even though they’re both part of the ECMAScript family, ActionScript and JavaScript cannot natively communicate; a ‘communication system’ has to be installed in each Flash-JavaScript project if you want them to talk. Think of it as needing a cell phone to call your mom because she lives in another part of the country!

[ you > cellphone < mom ]

[ actionscript > communication system < javascript ]

Flash-JavaScript Communication: Old-School Versus New-School

Flash-to-JavaScript communication has long been a heavily-discussed topic. Let me try and get you up to speed on it without getting too technical. Old-School refers to Flash Players v6-7, while New-School refers to Flash Players v8+.

Old-School #1: FSCommand

The first old-school technique is to use FSCommand. FSCommand allows synchronous communication, and is pretty straightforward to implement. It’s arguably the most widely-used old-school method for Flash-JavaScript communication in Flash-based SCORM-conformant online courses. (Wow, that’s a lot of hyphens!) But FSCommand has a huge downside: it isn’t cross-platform. It’s specific to Windows machines, and will fail on Macs and Linux boxes.

Old-School #2: GetURL and SetVariable

The second old-school technique is to use ActionScript’s getURL() coupled with SetVariable in JavaScript. For a while, this technique seemed to be popular with a segment of Flash-based course developers who worked with SCORM. The technique basically works like this:

getURL in ActionScript invokes a function contained in the JavaScript. The JavaScript function contains a reference to the SWF, and invokes a method (function) called ‘SetVariable’ in the SWF.

Example:

//ActionScript
getURL("javascript:'myFunction(\'myVariable\')'");Code language: JavaScript (javascript)
//JavaScript
var myVar2 = "Send me to Flash!";

function myFunction(v){
   var swf = window.document.mySwfId;
   swf.SetVariable("myVariable", myVar2);
}Code language: JavaScript (javascript)
//ActionScript:
//watch() or setInterval() used here to detect
//when variable "myVar" has been updated.Code language: JSON / JSON with Comments (json)

This technique wasn’t very popular because it was hard to implement, could only pass strings (no object, arrays, etc.), and was also asynchronous.

Being asynchronous was probably the biggest sticking point for most people, because it meant you couldn’t return the data from JavaScript into ActionScript right away — no var myVariable = getURL("javascript:'myFunction(\'myVariable\')'");; you had to send your request from ActionScript to JS, then wait for it to come back. This required some ugly tricks such as object.watch and setInterval to check if the variable had been updated before you could use it in Flash.

Old-School #3: The Flash-JavaScript Integration Kit

The third old-school technique is to use a proxy SWF and LocalConnection. I believe this was first discussed by the guys at MustardLab, and was turned into a full-blown system — the Flash-JavaScript Integration Kit (FJIK) — by two Macromedia employees. I’ll try and explain this as simply as I can.

First, a few things to note about loading external variables into a SWF:

  1. When a Flash SWF first loads on a page, it’s really easy to pass variables into the SWF from your HTML page using FlashVars.
  2. If an HTML page has two SWFs embedded on it, passing variables between the two SWFs is (relatively) easy using LocalConnection.
  3. Passing variables to a SWF AFTER the SWF has already been embedded to the page is the tricky part.

(Warning: this may be a gross oversimplification.)

The main idea behind the FJIK method is to dynamically embed a second SWF to your HTML page whenever you want your original SWF to load a variable from JavaScript. This second SWF is usually referred to as a proxy or gateway SWF. The data is loaded into the second SWF using FlashVars as it gets embedded in the HTML. The data is then transferred from the second SWF to the first SWF using LocalConnection. When the transfer is complete, the second SWF can be deleted.

Sounds reasonable, right? This biggest benefit of the FJIK method is that it isn’t limited to passing strings; it supports passing different variable types, such as objects and arrays. It proved to be a popular technique, but it had a few significant drawbacks: transfer speed (you have to wait for a new SWF and FlashVars to load each time you make a call), the required use of 4 or 5 external files (.as, .js, and .swf) is cumbersome, and — like the getURL method — the data is returned asynchronously. No instant ‘return’ statements.

New-School: ExternalInterface

The new-school technique is to use ExternalInterface, which was specifically designed by Macromedia Adobe to make Flash-JavaScript communication much easier. By most accounts, they did an excellent job — data can now be called from ActionScript and returned from JavaScript synchronously, which means your ActionScript and JavaScript can work as one. The code has some kinks, but generally speaking has worked pretty well.

Back to the point: Why the attempt at a hybrid?

You might ask: Why was I trying to make a hybrid of old and new techniques in the first place? The new-school ExternalInterface method works fine and is super-easy!

Answer: ExternalInterface works fine for people with Flash Player 8 and above. That eliminates the majority of the student population I’m targeting. Yes, I know Flash Players v8-9 are supposed to be ubiquitous, but the IT dept. at my workplace installed Flash Player 7 in early 2005 and hasn’t updated most of the machines since then. Employees have no admin rights on their computers, and therefore way to update Flash without calling IT to come do it. When you have over 5,000 employees, this becomes a big issue. It will be at least a few months before the majority of users get Flash Player upgrades.

I also have a colleague in a similar situation, except his target audience is mostly Mac users! This means FSCommand won’t work for him, and can’t hold him over until his end users get Flash Player upgrades.

Simply put, I was hoping to devise a solution for both our problems: a Flash-JavaScript communication method that doesn’t care what version of Flash you have or what platform you’re using! What a dream, huh?

How I hoped it would work

I wanted to create an abstraction layer that separates the SCORM calls from any particular Flash-JavaScript communication method. I was hoping I could do something as simple as this:

//ActionScript

var canDoEI:Boolean = ExternalInterface.available;
getURL("javascript:setCanDoEI(" +canDoEI +")");

function getDataFromJS(v){
   if(canDoEI){
      //external interface call
   } else {
      //old-school method
   }
}Code language: JavaScript (javascript)
//JavaScript

var canDoEI = false;

function setCanDoEI(v){
   canDoEI = v;
}

function sendDataToFlash(v){
   if(canDoEI){
      //external interface call
   } else {
      //SetVariable method
   }
}Code language: JavaScript (javascript)

This would have allowed me to use the same function calls in Flash Player v6-7 as in Flash Player v8-9, regardless of what technique was being implemented under-the-hood. However, because ExternalInterface and the FJIK each rely on imported classes, have such different syntax, and aren’t both synchronous (only ExternalInterface is synchronous), it would have been a huge headache to try and cram these very different techniques into one course. Bah humbug.

Why not use getURL/SetVariable instead of FJIK?

Granted, the getURL/SetVariable method is much easier to implement than the FJIK method, but it’s also limited to passing strings, and is asynchronous. The asynchronous nature of the getURL/SetVariable method is the main sticking point for me… it’s really tricky to set up the watchers/intervals needed to detect when the variable has successfully been returned from JavaScript. It doesn’t mix well with the synchronous and much speedier ExternalInterface.

So whatcha gonna do?

Wait until we upgrade to Flash Player 9. Sucks, but it’s a pragmatic choice.

I’m in a unique situation in that our IT dept. only supports Internet Explorer on Windows PCs. So far I’ve been able to use the easy-to-implement (and PC-only) FSCommand. I’ll be the first to admit this is something I’ve never been happy about, but hey, it has been a practical and fully-functioning solution for over 2 years. When I developed my current Flash course interface, I knew ExternalInterface was over the horizon, so I didn’t bother with getURL or the FJIK (which hadn’t been released yet). Little did I know that over 2 years later we’d still be supporting Flash Player 7!

In my own defense, I must say that I haven’t ignored standards and best-practices: everything else I’ve built is been cross-browser and cross-platform, including course content. But my guilt is catching up to me, along with a new crop of Mac users at work! It’s in all of our best interests for me to stop using FSCommand in our SCORM courses. If it weren’t for that stinkin’ Flash Player 7 on our older computers… grrr.

So my plan for now is to develop an ExternalInterface version of our Flash-based course interface, and have it ready for that fateful day when the IT guys tell me Flash Player 9 is up and running on (most of) our machines. Sigh… I was hoping for a happier ending!

Related links

Here are some interesting articles I encountered while doing my research:

Similar Posts

3 Comments

  1. Excellent wrap-up of this very nagging issue. If it’s any consolation, my organization is in the exact same boat as yours. Luckily for me, as the big E-learning expert AND the big (supposedly) Flash expert in my enterprise, we are on the verge of migrating to Flash 9 player… because I said so. It’s a nice place to be, but in the meantime, being stuck to Flash 7 sucks hardcore.

    On another note, with me being the author or a contributor on three of the four articles you mentioned — thanks for making me feel like an even bigger nerd. 🙂

    -a-

  2. Nice work Philip. Well written entry. It was a joy to read. You summarized the awkward space that exists when trying to develop a solution that reconciles the limitations of different flash player versions – operating systems – and browsers. It was interesting as an aside to read about Brad’s ExternalInterface accelerator code, and wonder if the performance boost is necessary when sending small strings back and forth with SCORM?
    -j

Comments are closed.