Note: This post covers Captivate 2 & 3; Captivate 4 introduced new problems for JavaScript interaction. You can avoid the headache of writing your own code by using the free CaptivateController utility, which works with all versions of Captivate.

JavaScript can control the playback of Captivate-generated SWFs. I posted some examples about a year ago (example one, example two), but someone recently reminded me I haven’t posted any instructions or explanations for my examples. Here’s a quickie explanation of how you can control a Captivate-generated SWF using JavaScript.

What can be controlled using JavaScript?

According to the official Adobe docs, Captivate provides the following controls:

  • go previous slide
  • go to next slide
  • pause
  • resume (play/un-pause)
  • rewind to beginning and stop
  • rewind to beginning and play
  • go to a specific frame
  • exit
  • display the information window

I’ve determined there are additional unpublished parameters that can be accessed. A complete list (including the variable name) is located here.

Build a simple example

Step 1: Create the HTML file and embed the Captivate SWF

For this example, we’ll use bare-bones HTML, with SWFObject handling the embed:

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Control a Captivate SWF with JavaScript</title> <script type="text/javascript" src="swfobject.js"></script> <script type="text/javascript"> //Embed the SWF in the HTML swfobject.embedSWF("captivate.swf", "captivateSample", "450", "300", "7"); </script> </head> <body> <div id="captivateSample"></div> </body> </html>
Code language: HTML, XML (xml)

Make sure the SWF you’re embedding is a SWF created using Adobe Captivate, and was published without the “border” property in the Skin settings. My example SWF is named “captivate.swf”; you should replace “captivate.swf” with your Captivate SWF’s filename.

Now place a link in the document; this link will invoke the JavaScript command. For this example, we’ll just be using Captivate’s “rewind and play” command (rdcmndRewindAndPlay), so give the link the text “Click here to rewind and play.” Since this is a fake link, the href value should just contain a hash (#).

<body> <p><a href="#">Click here to rewind and play</a></p> <div id="captivateSample"></div> </body>
Code language: HTML, XML (xml)

Step 2: Add the JavaScript

Now that the HTML is in place, all we need to do is add a touch of JavaScript. Add the following JavaScript function to the <head>:

//Embed the SWF in the HTML swfobject.embedSWF("captivate.swf", "captivateSample", "450", "300", "7"); function rewindAndPlay(){ var swf = document.getElementById('captivateSample'); swf.SetVariable('rdcmndRewindAndPlay', 1); }
Code language: JavaScript (javascript)

Add a corresponding onclick event to the link in the <body>:

<body> <p><a href="#" onclick="rewindAndPlay(); return false;">Click here to rewind and play</a></p> <div id="captivateSample"></div> </body>
Code language: HTML, XML (xml)

Save and test your page; the link should control the Captivate SWF.

How it works

The function

The JavaScript function you just created has two elements.

var swf = document.getElementById('captivateSample');
Code language: JavaScript (javascript)

When we embedded the SWF, we assigned it an ID of “captivateSample”. This means we can use document.getElementById('captivateSample') to ‘grab’ the SWF in the browser DOM and make the SWF an object available to JavaScript. In our case, we return the object as the variable swf. As a JavaScript object, you can now invoke any methods and get/set any properties that are available within that object.

Note: You may find old documentation warning you not to use document.getElementById to get a SWF; in my testing, document.getElementById works fine in all major browsers, including Firefox 2 & 3 (Mac & PC), Internet Explorer 6 & 7, Safari 2, Safari 3 (Mac & PC), and Opera 9.5 (Mac). Also note that I used SWFObject to embed the SWFs in all of my tests, which could have an impact on test results.

swf.SetVariable('rdcmndRewindAndPlay', 1);
Code language: JavaScript (javascript)

Captivate SWFs can be controlled by setting the value of specific ActionScript variables contained inside the Captivate SWF. We can set the value of these ActionScript variables using Flash’s SetVariable method (SetVariable allows JavaScript to set the value of an ActionScript variable without using ExternalInterface).

In this example, we’re setting the value of the Captivate variable rdcmndRewindAndPlay to 1 (boolean, meaning true).

The onclick event

If you’re not familiar with onclick events, all that’s happening is the function rewindAndPlay(); is being invoked when the link gets clicked. The extra code return false; simply instructs the browser to ignore whatever is contained in the href attribute, effectively preventing the browser from following the link. Remember to include the semicolons!

<p><a href="#" onclick="rewindAndPlay(); return false;">Click here to rewind and play</a></p>
Code language: HTML, XML (xml)

Border blues

When a Captivate file is published with the border option enabled, Captivate is actually publishing two SWFs: a skin SWF and the Captivate SWF itself. The skin SWF loads the Captivate SWF into a movieclip named cpSkinLoader_mc. This means we need to dig one level deeper to get to the Captivate SWF. This can be accomplished by appending the prefix cpSkinLoader_mc to the variable name. Here’s an example:

document.getElementById('captivateSample').SetVariable('cpSkinLoader_mc.rdcmndRewindAndPlay', 1);
Code language: JavaScript (javascript)

Expanding the functionality

My older examples (example one, example two) used a custom function that was designed to make controlling Captivate easier. This demonstrated how the developer could create shortcuts that prevented writing the same code over and over, while also providing a way to use simpler syntax, such as ‘pause’ instead of ‘rdcmndPause’. Here’s a really quick overview of my example function:

//Handle the Captivate commands function control(swfID, command, usesSkin){ //Get SWF as an object so we can use SetVariable var swf = document.getElementById(swfID); //Error-checking is good. if(!swf){ return false; } //Declare our prefix variable in case we need it. Leave as empty string for now. var prefix = ""; //If the Captivate SWF uses a skin, change prefix to include the skin's movieclip name if(usesSkin){ prefix = "cpSkinLoader_mc."; } //Which command is being invoked? switch (command) { case "pause": command = "rdcmndPause"; break; case "resume": command = "rdcmndResume"; break; case "rewindStop": command = "rdcmndRewindAndStop"; break; case "rewindPlay": command = "rdcmndRewindAndPlay"; break; case "next": command = "rdcmndNextSlide"; break; case "prev": command = "rdcmndPrevious"; break; case "info": command = "rdcmndInfo"; break; case "exit": command = "rdcmndExit"; break; } swf.SetVariable(prefix + command, 1); return false; }
Code language: JavaScript (javascript)

This function accepts three parameters: swfName (the ID of the Captivate SWF, which is assigned when embedding the SWF), command (what we’re telling the SWF to do), and usesSkin (boolean indicating whether or not this Captivate file uses a skin).

If the SWF doesn’t use a skin:

<a href="#" onclick="return control('captivateSample', 'pause');">Pause</a>
Code language: HTML, XML (xml)

If the SWF does use a skin:

<a href="#" onclick="return control('captivateSample', 'pause', true);">Pause</a>
Code language: HTML, XML (xml)

As I just mentioned, this function allows us to use simpler command names. A switch statement is used to match the simpler command name with the official command name. SetVariable does its thing, then the function returns false, which prevents the browser from following the link in the href attribute.

Everything but the kitchen sink

I’ve written a new Captivate controller utility that expands on the function shown above. It includes every known Captivate control that has been tested to work with JavaScript (there are a couple that appear to only work via ActionScript), and even combines a few existing controls to create new ones, such as combining ‘mute’ with ‘enable captions’ to automatically turn on captioning when muting the movie. I’ll be posting another entry about this new Captivate utility in the next day or two. Stay tuned!

Similar Posts

5 Comments

  1. hi, i like this code alot but cant figure it out in captivate 4. Actually i want to force the captivate swf file to goto last slide through javascript in html file… but cant find a way for captivate 4 swf file…
    any help 🙁

  2. Again I love this code , but is there a way to make this work without your Captivate Controller? I have tried the code above but cannot make it work on a captivate 4 swf file. I have uploaded the code to the server to test and still nothing works. Appreciate the help.

  3. Larry is right. This code would be great if he works with Captivate 4. Also appreciate the help.

  4. If you’re not interested in using the CaptivateController (which works great with Captivate 4), you can take a peek at its source code to see how to write your own.

    Captivate 4 can publish to AS3, which doesn’t work with SetVariable and requires ExternalInterface instead. If you want the code in this post to work with Captivate 4, publish to AS2.

    The point of the CaptivateController is to make it easy for people like yourself to not have to write tons of code and learn the idiosyncrasies of Captivate’s JavaScript support.

Comments are closed.