Flash demos for SCORM ActionScript classes now available

Finally got around to making some Flash files that demonstrate the pipwerks SCORM ActionScript classes. I’ve created examples for both AS2 and AS3. You can get them here.

Both of these examples have been successfully tested using the latest ADL test suites for SCORM 1.2 and 2004.

A word about the code in the Flash examples

I just thought I should point out that there are many ways to build a course in Flash, and the method I used for these examples is just one. I kept it very simple, and wanted to stick to the basics; these examples are designed to show you how easy it is to integrate the SCORM class into a course, and not much else!

There’s a bunch of extra error-checking and debugging code in there to help illustrate the course-to-LMS communication facilitated by the SCORM JS wrapper and AS classes.

Note: Although the ActionScript 2 example uses SCORM 1.2 and the ActionScript 3 example uses SCORM 2004, when creating your own courses with these wrappers, you can mix and match any way you like. You can use AS2 with SCORM 2004 or AS3 with SCORM 1.2… it’s completely up to you.


Why don’t more e-learning developers use standards?

Question: Why don’t more e-learning developers use standards?

I don’t know for sure, but I have a number of guesses. Here’s a quick list off the top of my head:

  • Lack of knowledge about standards
  • Confusing or obtuse documentation
  • Competing standards
  • Misconceptions about cost effectiveness
  • Difficulty / Lack of support in development tools

This is a sort of stream-of-consciousness post, so I’m sure I’m missing a few things. Feel free to add your two cents.

Lack of knowledge about standards

It’s my opinion that a large number of e-learning developers are non-technical, or are mid-level techies who came into the field from other areas. Not having a background in web development, many of these developers probably don’t know that using tables for layout purposes is a faux-pas, or realize the power of well-written CSS. Many of these developers probably rely on their e-learning development tools to handle that stuff for them.

And for those who know all about web standards, e-learning standards are a whole ‘nother beast. Being a master with CSS doesn’t mean you’ll easily grasp the depths of SCORM’s murky sequencing features. Which leads us to…

Confusing or obtuse documentation

I like SCORM. I also hate SCORM. Such is life.

There are a number of proposed standards for e-learning courseware, with SCORM and AICC probably leading the way. However, AICC is considered out of date, and SCORM is considered difficult to use. As with many proposed standards, I believe SCORM’s steep learning curve lies largely in the really hard-to-read documentation and unclear examples.

My apologies to those who wrote the documentation — I do think it’s very thorough — but for someone who isn’t familiar with SCORM, trying to get a handle on it by reading those documents is a very frustrating experience. I think Claude Ostyn’s Cooking Up a SCORM and Eye of the SCORM documents were the most reader-friendly SCORM documents available, but with his unfortunate and untimely passing, they probably won’t be updated.

Competing standards

SCORM isn’t the only standard out there. As some of you may recall from my previous post, the IMS Global Learning Consortium (among others) has created a number of proposed standards for the world to use, including the IMS manifest (which accompanies every SCORM course), the Question and Test Interoperability specification, and most recently, the ultra-secretive Common Cartridge proposal.

Having tried my hand at using these IMS standards, lemme tell ya, they are not easy or fun to use. Big disincentive from the start. (The IMS takes inconvenience one step further by making it difficult to even figure out exactly what their standards are.)

The IMS is working on the Common Cartridge Alliance. According to some, it’s a SCORM killer that will revolutionize e-learning courseware.

However, SCORM is much more established, and has been adopted by every major LMS vendor. Assuming the Common Cartridge is as good as promised (and the specification ever becomes publicly available), it will force developers to choose sides.

Backing off of e-learning standards for a minute, what about other competing standards? There are no shortage of standards to choose from: HTML 4 versus XHTML 1.0 (and soon HTML 5 versus XHTML 2.0); Internet Explorer (and its proprietary ActiveX controls) versus Firefox/Safari/Opera/et al, Adobe Flash versus the new kid on the block Microsoft Silverlight, etc.

Making sound choices involves homework on the issues. Oftentimes, I think people make their choice based on ease of use (“does my WYSIWYG editor support it?”) or cost. This is a fair point; after all, we can only do what our budgets allow, right? Well…

Misconceptions about cost effectiveness

One of the biggest arguments against standards and best practices is the amount of time it takes to get up and running with standards.

When it comes to web standards such as valid XHTML markup and CSS-based layouts (separating content from presentation), I think a small amount of time getting acquainted with the techniques pays big dividends in the long run. When using standards and best practices, you’ll spend less time troubleshooting browser compatibility, less time updating the look and feel (external CSS makes it so much easier!), and less effort making the course work in different mediums (standard web browser versus mobile versus text reader, etc.).

Using standards also ensures your courseware will have a longer shelf life.

It’s too expensive to NOT use standards and best practices.

Difficulty / Lack of support in development tools

A hot topic of late is the quality and capabilities of e-learning development tools. Personally, I don’t use them very much except for special needs, such as making animated screen captures in Captivate and/or Camtasia. I normally stick to standard web development tools such as Dreamweaver and Flash Professional.

However, I totally understand the needs of many others out there who don’t have the time and/or expertise to make courseware from scratch; there’s a reason the e-learning development tool field has really bloomed the last few years, and it won’t slow down anytime soon.

But as I’ve mentioned before, these tools most often do not support web standards or best practices. What’s worse, they often completely ignore standards while making the purchaser/user of the software think they’re getting top-notch, state-of-the-art stuff. It’s false advertising, but it’s also effective marketing. Very effective.

I wish the e-learning tools market would shape up and self-regulate! (Riiiight…) Hey tool developers: Use standards because they matter. Use best practices because they’re best practices for a reason. If you incorporate standards and best practices in this young niche market, you could very well find yourself top-shelf in a matter of months. If you were already top-shelf, you could become uber-elite. Think about it.

So what can we do?

I know I keep espousing standards without really giving enough concrete know-how and direction. Honestly, I’ll be the first to admit I don’t have the answers — but maybe together we can do something about it. I’m proposing we create a community-defined set of simplified e-learning development standards that can be viewed more as ‘rules of thumb’ than law.

For starters, a standard like SCORM is very intimidating because of its intricacies and density. Claude Ostyn’s writings were enlightening if only because the first thing he did was show an extremely simple example of a single-page course. His point was that just because SCORM can be used in-depth doesn’t mean it has to be. We can just use it for what we need and ignore the rest. A great example is SCORM’s page sequencing and navigation system; it’s really tricky to figure out, and requires a really complicated imsmanifest.xml file. If your course only has a few pages, or if you already have a decent navigation system worked out, don’t use SCORM’s navigation features. You can still create a SCORM-conformant course (SCO) that will work with any SCORM-conformant LMS!

Got ideas?

So how about it? I’m going to start writing down simple, easy-to-digest rules of thumb that I hope someone will find useful. I intend to provide examples and/or links with every concept. Will you help me? Maybe together we can get this thing turned around.

New: SCORM API wrapper for ActionScript 3.0

I just converted my AS2 SCORM class to AS3.

Read documentation and download file(s) here. Note this class requires the pipwerks SCORM API wrapper for JavaScript.

Not being much of an AS3 guy (so far!), it was easier than I expected; I guess since I had already used strong typing in AS2 it met most of the AS3 requirements for strong typing. The only other changes between the AS2 and AS3 classes are pretty simple:

  • Added the AS3-required ‘package’ wrapper. I used the package name “pipwerks”; if you use this class, you’ll need to either place the class in a subfolder named pipwerks, or rename the package. It’s not a requirement, but I’d appreciate it if you left the pipwerks in there. 🙂
  • Converted all “Number” variables to “int”
  • Changed all “Void” function return types to “void”

I think that’s it…

As always, please give me feedback! Let me know if it does or doesn’t work for you, if you find any bugs, or if you have any suggestions for improvements.

New: SCORM API wrapper for ActionScript 2.0

I just finished an ActionScript 2.0 class file meant to be a companion to my JavaScript SCORM API wrapper.

Update: AS3 version now available, too.

Simplified syntax

The idea was simple: give me (and others) a way to make SCORM calls using ExternalInterface without having to constantly type ExternalInterface!

So now instead of typing the tedious

var student_name:String = String(ExternalInterface.call("SCORM.data.get", "cmi.core.student_name"));

we can just type

var student_name:String = scorm.get("cmi.core.student_name");

To initialize a course, you can just do the following:

var scorm:SCORM = new SCORM();

Usable return values and automatic ExternalInterface error-checking

The class includes type checking, type conversion, and error-checking to help avoid running into the same annoying issues over and over again. Let the class worry about that stuff, so we can just request our data! 🙂

You can use the boolean return types to ensure your course works as expected. For instance, you could do something like:

var scorm:SCORM = new SCORM();

var isConnected:Boolean = scorm.connect();


   var lesson_status:String = scorm.get("cmi.core.lesson_status");

   if(lesson_status == "completed" || lesson_status == "passed"){


   } else {

      var success:Boolean = scorm.set("cmi.core.lesson_status", "completed");





The class has been successfully tested in the ADL SCORM 1.2 test suite (1.2.7), but is designed to be version-neutral, working exactly the same with both SCORM 1.2 and 2004 — just make sure you have the required JavaScript wrapper.

The JavaScript wrapper determines your SCORM mode (1.2 or 2004) when it finds the API; you never have to state which version of SCORM you’re using in your JavaScript OR your ActionScript! If you use this class for SCORM 1.2 and decide to transition to SCORM 2004, you won’t have to change the class file or the JavaScript wrapper.

If you’re keeping the same course functionality and not adding new features, you’ll just need to change some of the variable names in your own course ActionScript, such as going from “cmi.core.lesson_location” to “cmi.location”.

If you want to add SCORM 2004 features, the wrapper is already set up for it, just use the appropriate syntax, such as var progress:String = scorm.get("cmi.progress_measure");.

(In case you’re wondering how the scripts know which version of SCORM is being used, the SCORM version is declared by the imsmanifest file and the course settings when importing the course into the LMS.)

Get the class file

You can get the class file and read the (meager) documentation at http://pipwerks.com/lab/scorm/wrapper/flash/.

PLEASE give me feedback!

Please try it out and let me know what you think! I’m still testing it out and would appreciate any feedback or suggestions you might have. Thanks in advance!

A revised SCORM API wrapper

I’ve been a longtime user of the ADL wrapper (with code from the late Claude Ostyn), and to be honest, it’s pretty much met my needs. But I was never completely comfortable with the wrapper for two reasons: 1) The code is hard to read with confusing and overly complicated looking variable names, and 2) the code made heavy use of global variables, which in this Web 2.0 world is a big no-no. Global variables can easily cause conflicts with other scripts and script libraries, and should be avoided as much as possible.

This past week I decided to roll up my sleeves and make a new SCORM API wrapper that takes care of these issues. [ Download wrapper | Documentation ]

Examples of the wrapper in action

I have successfully tested the wrapper with the ADL test suites for SCORM 1.2 and SCORM 2004 rev 3.

Update April 23, 2008: all downloads and demonstration files have been relocated. See the SCORM page for more info.


Now, mind you, I’m not saying the wrapper is perfect — there are still some changes I’m considering — but I think it’s a step in the right direction. I’d love to hear your thoughts on the revised wrapper, especially if you’ve had a chance to test-drive it.

What’s a wrapper?

A “SCORM API wrapper” is a buffer (aka ‘proxy’ or ‘middleman’) that prevents your SCORM course from making direct calls to the SCORM Run-Time Environment (RTE) located on your learning management system.

(For those less familiar with the concept of APIs: API stands for “application programming interface.” An API allows 3rd party developers to tap into specific features of a program or service. For instance, Flickr has become famous for allowing independent developers to create web-based applications that tap into Flickr’s photo hosting services using the Flickr API.)

Why use a wrapper?

There are two really good reasons to use a SCORM API wrapper: 1) advanced error-checking, and 2) ease of maintenance.


If you try to make a call to the SCORM RTE before the course has been initialized (turned on), your call will fail. This means if you try to request the course status or student’s name, your request will not work, and you will most likely NOT receive any error messages telling you what happened.

//This will fail silently if you don't use error-checking
var myvalue = api.GetValue("cmi.suspend_data");

By using a wrapper, you can build ‘checks’ into your code that ensure certain criteria are met before performing a specified action. For instance, the wrapper can ensure your course is properly connected to the SCORM RTE before asking the RTE to give you data.

if (connectionIsActive){
   var myvalue = api.GetValue("cmi.suspend_data");

You can also add debugging alerts and statements to help you figure out what has happened when something goes wrong:

if (connectionIsActive){
   var myvalue = api.GetValue("cmi.suspend_data");
} else {
   alert("api.GetValue() failed because the API connection is inactive.");


Another great reason to use a wrapper is ease of maintenance. The SCORM RTE has been steadily evolving over the years; for the last few years, the dominant version has been 1.2. However, version 1.3 (later renamed “2004”) has been gaining ground, thanks largely to mandates by the US military that require all e-learning courses used in military training be SCORM 2004-conformant. That’s a LOT of courses, and those big-money contracts are increasing the pace of SCORM 2004 support in both courseware and learning management systems.

What if you hard-coded your SCORM 1.2 calls into your course? SCORM 1.2’s nomenclature is very different from SCORM 2004. This means you’d have to dig into all of your courses and replace every single SCORM 1.2-specific reference to the newer SCORM 2004 nomenclature. Yuck.

What would be easier is using a wrapper to control the SCORM nomenclature for you. Consider this SCORM 1.2 call wrapped in a custom function:

function saveData(){

When you change your course from SCORM 1.2 to SCORM 2004, all you’d need to do is change the call in the function from api.LMSCommit("") to api.Commit(""). The code used in your course would be the same (saveData("")), and you’d only need to update your code in one place. This makes upgrading much less painful.

OK, I’m sold on the value of wrappers. Where do I get one?

Chances are you’re already using a wrapper, but probably not to its potential. The ADL has some sample wrappers available on their website, and most commercial SCORM products come with wrappers.

My revision to the ADL wrapper is intended to make it even easier to use and troubleshoot. Best of all, it’s free. 🙂 Give it a whirl! All I ask is for you to give me some feedback; let me know if it works on your particular LMS, or if you have suggestions for improvements.

Update: all demonstration files have been relocated. See the SCORM page for more info.

Actionscript, JavaScript, and SCORM

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.



var myVar2 = "Send me to Flash!";

function myFunction(v){
   var swf = window.document.mySwfId;
   swf.SetVariable("myVariable", myVar2);

//watch() or setInterval() used here to detect
//when variable "myVar" has been updated.

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 to some die-hard coders.)

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:


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

function getDataFromJS(v){
      //external interface call
   } else {
      //old-school method


var canDoEI = false;

function setCanDoEI(v){
   canDoEI = v;

function sendDataToFlash(v){
      //external interface call
   } else {
      //SetVariable method

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:

Thoughts on using JavaScript in Adobe Captivate

Having just finished my Making Actionscript calls from Adobe Captivate tutorial, I’ve been looking at Captivate 2.0 a lot the last few days. Specifically, I’ve been looking for ways to use JavaScript in Captivate. I’m a bit disappointed to report that JavaScript can only be used in very limited instances.

From what I can gather, JavaScript calls can be made in the following instances:

  1. At the end of a slide
  2. At the end of the movie
  3. When a clickbox or button is clicked
  4. When a text input field is used

“That sounds like plenty of ways to use JavaScript,” you say? Well, the major shortcoming is this: if you choose to execute JavaScript in any of those cases, you’re giving up the ability to use the other ‘Navigation’ options, such as ‘go to next slide,’ ‘go to previous slide,’ ‘jump to slide,’ ‘open URL or file,’ and ‘open other project.’

Navigation options in Captivate

As you can see in the image above, Captivate only allows you to choose ONE ‘navigation’ option. You can’t execute JavaScript and jump to a slide.

In some cases this may be fine, but what if your Captivate movie is a scenario with branching? A button click or other interaction must occur to tell the movie to jump to the appropriate scenario slide. If you choose to execute JavaScript instead of using a ‘jump to slide’ action, your scenario is toast… you will not be able to navigate to any slide other than the next slide in the timeline.

Johnny doesn’t play well with others

The bottom line is that Captivate is being developed as a stand-alone solution, and is not really meant to integrate with any other course development tools.

A Captivate SWF can be embedded in an HTML-based course interface, but doing so will render the built-in interaction tracking system practically useless. The tracking system is designed to deliver data in a limited, pre-packaged capacity; there is no obvious way to access to the raw tracking data. For instance, if you want to get SCORM calls such as lesson_location from the Captivate SWF, there’s no clear, easy solution for doing so. And there’s no way to set up the Captivate file as a component of a SCORM course… it’s meant to be a be-all-end-all solution (for example it will do ‘LMS initialize’ calls, which is a no-no in the middle of a course).

A Captivate SWF can be loaded into a Flash-based course interface, but because there is no easy access to the Captivate SWF’s Actionscript code, it’s a huge challenge — though not impossible — to extract Actionscript variables from a Captivate SWF. This includes tasks such as controlling the Captivate SWF’s playback using your own Flash playback controls; The sheer number of Captivate ‘help’ sites dedicated to this normally simple exercise is proof enough.

Have you ever tried decompiling a Captivate-generated SWF and inspecting its Actionscript? It’s very enlightening and utterly confusing! (FYI SoThink SWF Decompiler has a limited trial version you can use if you’re curious).

And NO, asking us to export the Captivate movies as FLAs and then customizing in Flash is NOT an appropriate solution. Big chunks of functionality and settings get lost in the conversion, and you can’t send the FLA back to Captivate. It’s a path of no return. The whole point of Captivate was to make things quick and easy and avoid having to do heavy lifting in Flash.

In many ways, Captivate is a great product. It’s the best software I’ve ever used for creating software simulations, and the SWFs it creates are much smaller than video-based tools such as Camtasia.

However, until the Captivate design team starts acknowledging the needs of course developers who use Captivate as a small part of their development toolbox, we will be stuck pulling our hair out and spending hours on end searching for workarounds. And that kinda sucks, don’t you think?