Cleaning up Adobe Captivate’s SCORM Publishing Template, Part 2: HTML

In part one of this series, we published a simple Captivate course and examined its file structure. In this part, we’ll take an in-depth look at the HTML generated by Captivate (using the SCORM 2004 publishing template) and clean it up as much as we can.

Here’s the default HTML published by Captivate.

I’ll take the high road and avoid the ever-so-easy snarky comments about this code. Suffice to say it needs some serious cleanup; it’s obvious that multiple people with multiple coding styles have worked on this document, and no quality assurance team has run through it to ensure it’s clean and concise. For example, there is an entire block of code commented out at line 141 (commenting it out means it never gets used, and therefore is useless bloat).

There’s also an aborted attempt at using SWFObject from lines 214 to 242 — the object is declared, but never invoked. Never. Did you know this code has been shipping with Captivate for years? I’m amazed no one has bothered to clean it up (and yes, I have reported it to Adobe, but they chose not to act).

As irritated as I get looking at the code, this blog post is not meant to be a rant, so let’s be constructive and get to work cleaning this mess.

Cleanup task #1: Externalize the JavaScript

This document is incredibly hard to read due to all of the <script> elements and JavaScript code. Let’s start by removing the JavaScript in the document’s <head> by cutting it out and pasting it into an external JavaScript file.

View the results of task #1:
The new captivate.js file
The slightly cleaner sample.htm file

This single step makes the HTML file much easier to read.

Cleanup task #2: Fix the doctype

Stepping through the HTML, the very first lines of code (lines 3-4) contain a conflict: the doctype says this is an HTML 4 (transitional) document, but the head element contains an XHTML lang declaration.

We’re in an HTML5 world now, so let’s use the HTML5 doctype. It’s 100% compatible with all browsers (even Internet Explorer 6), and all the cool kids use it. We can retain the lang declaration, too, with a few modifications. While we’re at it, let’s update the charset meta tag to the accepted HTML5 syntax.

View the result of task #2

Cleanup task #3: End the crazy <script> abuse!

There are six <script> blocks in our HTML file, and they are all inconsistent. For example, some have a “type” attribute, some have a “language” attribute, some have both, and some have neither. This is a sure sign of multiple authors working on the document over a long period of time.

Going through the <script> block, we can clean them up as follows:

  • Line 8: Since we’re using the HTML5 doctype, we can simplify it to remove the “type” attribute.
  • Line 9: Leave as-is.
  • Line 10: Remove the “type” and “language” attributes.
  • Lines 17-25: This entire block is never invoked and is completely useless. Delete it.
  • Lines 37-73: The contents of this block need cleanup, but we’ll handle that later one. For now, just remove the “type” and “language” attributes.
  • Lines 74-77: There is no need for a separate <script> block here; merge the contents with the previous <script> block.

View the result of task #3

Cleanup task #4: Remove inline scripts and styles

The <body> element contains two inline attributes: a style attribute, and an onunload handler. It’s an accepted best practice to leave your markup as clean as possible by removing inline styles and scripts when possible, so let’s create a new <style> element to hold the CSS, and move the onunload handler to our captivate.js file (just paste window.onunload = Finish; at the bottom of captivate.js).

View the result of task #4

If you’re not sleeping yet, you’re probably wondering why creating a <style> block is better than leaving the style attribute in the <body> tag. For this project, I know I will be adding more CSS declarations to the <style> block, so we may as well set it up now.

Cleanup task #5: Cure <center>itis

There are two sets of <center> elements on the page that can be replaced by adding one line of CSS to the top of the page.

Delete lines 16, 47, 66 and 72. Add text-align: center; to the body selector in the <style> block.

View the result of task #5

Cleanup task #6: Edit the <noscript> block

For accessibility and usability purposes, it’s usually a good idea to include a <noscript> block; this enables you to present a message or fallback content to visitors who have JavaScript disabled in their browsers.

Captivate uses SWFObject — a JavaScript utility — to embed the Captivate SWF. To hedge their bets, Adobe also attempts to embed the SWF in the <noscript> block using a method that doesn’t require JavaScript. Normally this is a good idea. However, SCORM courses require JavaScript; if JavaScript is disabled, the course won’t be able to communicate with the LMS. Period. End of story.

For this Captivate template, it’s probably best to remove the SWF from the <noscript> block and leave a message for the learner informing them that they can’t take the course unless JavaScript is enabled. Chances are they can’t get to the popup window containing the course anyway!

View the result of task #6

Cleanup task #7: Get rid of the <table> markup

The JavaScript on lines 39-41 and 54-56 generate a <table> whose sole purpose is to make the SWF vertically centered on the page. For our purposes, this is unnecessary because most courses launch in a popup window that has been sized to fit the course.

Ironically, the <table> that is meant to make the embedded SWF look nice on the page actually causes a significant problem — the table has cellpadding and cellspacing set to 7, which means the SWF will never extend to the edge of the window. When you’re trying to make a perfectly-sized popup window for your course, this cellpadding and cellspacing will cause scrollbars to appear, driving you bonkers!

Also, it’s widely accepted that tables shouldn’t be used for layout purposes, anyway, so it’s best to get rid of the <table>.

View the result of task #7

Our HTML file is starting to look pretty sweet!

Cleanup task #8: Externalize more JavaScript where possible

We externalized JavaScript in steps 1 and 4, let’s try and get the rest of this JavaScript externalized. The only remaining inline JavaScript is contained in lines 22 through 51. Our first task is to determine whether it needs to be inline; will moving it break anything?

  • Lines 23 through 36 appear to be safe to move into the document’s <head>, which means it’s safe to move to our captivate.js file. Just cut and paste — place the script at the very bottom of captivate.js.
  • Lines 38 through 47 use SWFObject 1.5 to embed the SWF. We can move this code, but it will need to be wrapped in an onload event or else it will break the page. In a later step, we will upgrade SWFObject to 2.2, which helps us optimize the Captivate template even further.
  • Lines 49 and 50 can be moved, but will also need to be wrapped in an onload event.

While moving the SWFObject code, we can also clean it up a bit:

  • Line 39 is not necessary because quality = high is Flash Player’s default.
  • Line 41 is not necessary because SWFObject is already set to use “Captivate” (the second argument passed on line 38) as the ID for the SWF.
  • Line 42 is not necessary because wmode = window is Flash Player’s default.
  • Line 45 is not necessary because it does nothing, it’s a completely gibberish line of code. I suspect it was a placeholder put there by a developer years ago, and no one has bothered removing it. It has shipped with Captivate for years.
  • Line 46 is useless; the redirect URL is only invoked when two criteria are met: 1) the embed markup is present in the HTML, and 2) the visitor does not have the required version of Flash Player. This Captivate file is using SWFObject to write the embed code. SWFObject has its own check for Flash Player (argument #5 on line 38); if the minimum version specified is not found, SWFObject will not write the embed code into the HTML. This means requirement #1 listed above will never be met, which means the redirect URL will never be invoked.
  • Update: Upon re-reading this post, I noticed even more issues with the SWFObject code: line 40 (‘name’ is not a param, it’s an attribute) and line 43 (bgcolor param isn’t needed, the color should be specified as the 6th argument in the SWFObject declaration). I won’t update the examples because we’re replacing SWFObject 1.5 with 2.2 in the next part of this series, so the entire SWFObject code block will be replaced.

    The updated HTML:

    Nice and simple, huh? We can pare it down more later, but this is a great start.

    View the updated captivate.js file.

    We were able to reduce the sample.htm file from 278 lines of code to 23 lines. Our new captivate.js weighs in at 224 lines of code, but we’ll be taking a sledgehammer to the JavaScript code in part three of this series.

    Continue to part three.

    Advertisements

Cleaning up Adobe Captivate’s SCORM Publishing Template, Part 1: Introduction

Adobe Captivate is an enormously popular tool for e-learning developers. My assumption is that most Captivate users chose Captivate as their development tool because it enables them to publish LMS-compatible courses without requiring any programming skills — no need to know JavaScript, ActionScript, SCORM, etc.

This might explain why no one is up in arms about the astoundingly bad HTML and JavaScript output by Captivate — very few people look under the hood.

In this multi-part series, I will walk through the files Captivate outputs when publishing to SCORM 2004, pointing out the bad parts (hey Adobe: this is constructive criticism, it’s for your own good) and suggesting alternatives when needed. At the end of the series, I will provide a fully-functional SCORM 2004 publishing template you can use with Captivate 5.5.

Getting Started

The first step is to create a very simple Captivate course and publish it using the SCORM 2004 template. This will produce a set of files that we can examine and modify without breaking any templates.

  1. Go to File > New Project > Blank Project
  2. Select a small screen size since we’re just messing around. I selected 640 x 480.
  3. Add something to the stage just so we have something to look at aside from a blank white screen. You can add a text caption, image, etc. — it doesn’t have to be fancy, it just gives us something to look at.
  4. Publish to SCORM 2004
    1. File > Publish Settings
    2. Quiz > Check “Enable reporting for this project”
    3. Under Learning Management System select SCORM.
    4. Click the “Manifest” button. The Manifest dialog will appear; select 2004 from the drop-down menu.
    5. Click OK, then click OK in the Publishing Settings dialog.

Now publish your course: File > Publish. The Publish dialog appears. Nothing to change here, unless you want to select a different location for your files. Click “Publish”.

Attack of the Files

Find the folder containing your published files and take a peek at what Captivate generated for you. It’s quite intimidating, especially with all of those SCORM 2004 XSD files. I suggest sorting the files by kind.

Here’s a quick breakdown of the files:

  • All the DTD and XSD files are a required part of SCORM’s packaging system. The common, extend, unique, and vocab folders all contain SCORM-related XSD files. None of these files or folders should be edited, renamed, moved or deleted. You must keep them, but otherwise it’s best to act as if they don’t exist.
  • The imsmanifest.xml file is required for SCORM 2004. Don’t move or rename it. Some portions of the file may be edited, but you’d better know what you’re doing!
  • The SWF file (in my case sample.swf) is the Captivate course.
  • The HTM file (in my case sample.htm) is the HTML file that contains the SWF.
  • standard.js is a JavaScript file that contains some 3rd-party JavaScript utilities.
  • The SCORM_support folder contains files that Captivate uses to communicate with the LMS when using really old browsers. The files aren’t part of the SCORM standard, they’re just helper files created by Adobe.

Hopefully the files don’t seem so intimidating now that you know what’s what.  Once you ignore the XSD and DTD files, there are actually very few files left to work with.

The next post in this series will cover the HTML file produced by Captivate. Continue to Part 2.

Complete List of Variables for Adobe Captivate 5

While updating my CaptivateController script I noticed there have been some changes to the Captivate variables available to Captivate developers. I figured I should document them for future reference.

Note that some variables available in CP3 and CP4 are no longer available. The following list should be exhaustive for CP5; variables for previous versions of Captivate have been purposely left off this list. I also purposely left off some publicly accessible (but useless) movieclips and objects.

While most people seem to focus on using Captivate variables natively within a Captivate project via the Variables menu or widgets, my focus has been figuring out how accessible/usable they are via JavaScript. Thus you may find small differences between my list and other people’s lists, and differing opinions regarding the usefulness of some variables and publicly accessible movieclips. Regardless, the items below should be accessible via every method: widgets, JavaScript, and the native Variables support in Adobe Captivate.

If you know of any variables that I missed, please leave a comment. Thanks!

Update: Kurt Melander has kindly converted this list to PDF format if you’d like to download or print it. Thanks, Kurt.

Variable Type Description

CPMovieType

[number] Informational variable. Indicates whether the queried SWF is a skin SWF (0) or the main content SWF (1).
CaptivateVersion [string] Informational variable. Indicates the version of Adobe Captivate that published the SWF
DoNotRegisterRightClickBecauseOfAggregator [boolean] Internal variable, no information available
LocalConnectionInUse [boolean] Internal variable, no information available
NoOfTOCEntries [number] Informational variable. Returns the number of items contained in the project’s Table of Contents

PlaybarProperties

[string]
in Chrome

[XML] in Firefox

Internal variable, no information available.

NOTE: This item is
:XML data type in AS3. Because browsers have different support for native XML data types, values returned from this variable should not be considered cross-browser. Use at your own risk.

__loadbase [string]

Informational variable. Returns project’s root file path.

NOTE: This value can only be obtained when the project uses an external skin.

contentHeight [number] Informational variable. Returns the height of the Captivate main SWF (in pixels)
contentLeft [number] Informational variable. Returns the distance of the Captivate main SWF from the leftmost edge of the project (in pixels).
contentSWF [string]

Informational variable. Returns the file name for the project’s main SWF.

NOTE: This value can only be obtained when the project uses an external skin.

contentTop [number] Informational variable. Returns the distance of the Captivate main SWF from the topmost edge of the project (in pixels).
contentWidth [number] Informational variable. Returns the width of the Captivate main SWF (in pixels)
cpAutoPlay [boolean] Informational variable. Indicates whether the project is set to auto-play.
cpCaptivateSkinSWF [boolean]

Informational variable. Indicates whether the SWF is a skin SWF or primary project SWF.

NOTE: This value can only be obtained when the project uses an external skin.

cpCmndCC [number] Command variable. Setting to 1 will enable captioning. Setting to 0 will disable captioning.
cpCmndFastForward [number] Command variable. Setting to 1 will fast-forward the movie (play the movie at a higher framerate). Setting to 0 will return the movie to the normal playback speed.
cpCmndGotoFrameAndResume [number]

Command variable. Will cause the movie to jump to the specified frame and resume playing (frame numbering begins at 0).

Note: frames are not the same as slides.

cpCmndGotoSlide [number]

Command variable. Will cause the movie to jump to the specified slide (slide numbering starts at 0).

Note: frames are not the same as slides.

cpCmndMute [boolean] Command variable. Setting to 1 will disable (mute) the audio. Setting to 0 will restore it to normal.
cpCmndNext [number] Command variable. Setting to 1 will cause the movie to jump to the next slide. Setting to 0 will do nothing.
cpCmndPlaybarMoved [boolean] Command variable. Internal variable. According to Captivate documentation, "Set to 1 if the playbar has moved."
cpCmndShowPlaybar [number] Command variable. Setting to 1 will cause the movie’s playbar to appear. Setting to 0 will make the palybar disappear.
cpCmndVolume [number] Command variable. Setting to a number will cause the volume to change. The volume ranges from 0 (muted) to 100 (maximum volume).
cpContentLoadStart [boolean]

Informational variable. Indicates whether the main project SWF has started.

NOTE: This value can only be obtained when the project uses an external skin.

cpContentLoaded [boolean]

Informational variable. Indicates whether the main project SWF has loaded.

NOTE: This value can only be obtained when the project uses an external skin.

cpContentPositioned Internal variable. No information available.
cpContentScaled Internal variable. No information available.
cpHasSkinSWF [boolean] Informational variable. Indicates whether the Captivate project uses an external skin.
cpInfoAuthor [string] Informational variable. Returns the project author’s name, as entered in the movie’s properties before publishing.
cpInfoCompany [string] Informational variable. Returns the project company’s name, as entered in the movie’s properties before publishing.
cpInfoCopyright [number] Informational variable. Returns the project’s copyright notice, as entered in the movie’s properties before publishing.
cpInfoCourseID [number] Informational variable. Returns the project’s course ID, as entered in the movie’s properties before publishing.
cpInfoCourseName [string] Informational variable. Returns the project’s course name, as entered in the movie’s properties before publishing.
cpInfoCurrentDate [string] Informational variable. Returns the day portion of the current date.
cpInfoCurrentDateString [string] Informational variable. Returns today’s date (US English format).
cpInfoCurrentDay [string] Informational variable. Returns number indicating day of week (1 = Sunday, 2 = Monday, etc.)
cpInfoCurrentHour [string] Informational variable. Returns the current hour (24 hour clock format).
cpInfoCurrentMinutes [string] Informational variable. Returns the minutes portion of the current time.
cpInfoCurrentMonth [string] Informational variable. Returns the month portion of the current date.
cpInfoCurrentSlide [number] Informational variable. Returns the current slide number. (Uses 1-based index)
cpInfoCurrentSlideLabel [string] Informational variable. Returns the slide label for the current slide, if available.
cpInfoCurrentSlideType [string] Informational variable. Returns the slide type for the current slide.
cpInfoCurrentTime [string] Informational variable. Returns the current time, including seconds (24 hour clock format).
cpInfoCurrentYear [string] Informational variable. Returns the year portion of the current date.
cpInfoDescription [string] Informational variable. Returns the project’s description, as entered in the movie’s properties before publishing.
cpInfoElapsedTimeMS [number] Informational variable. Returns the amount of time (in milliseconds) that has elapsed since the project began playing.
cpInfoEmail [string] Informational variable. Returns the project author’s e-mail address, as entered in the movie’s properties before publishing.
cpInfoEpochMS [number] Informational variable. Returns the current time elapsed (in milliseconds) since January 01, 1970.
cpInfoHasPlaybar [number] Informational variable. Indcates whether the Captivate movie has a playbar. 1=true, 0=false
cpInfoIsStandalone [number] Informational variable. Indicates whether Captivate project is en .exe or .app file (1) or standard SWF (0).
cpInfoLastVisitedSlide [number] Informational variable. Returns the last visited slide number. (Unlike cpInfoCurrentSlide, this variable uses 0-based index)
cpInfoPercentage [number] Informational variable. Returns the current score as a percentage (if available).
cpInfoPrevSlide [number] Informational variable. Returns the number of the slide before the current slide. (Uses 1-based index)
cpInfoProjectName [string] Informational variable. Returns the project’s name, as entered in the movie’s properties before publishing.
cpInfoWebsite [string] Informational variable. Returns the project’s web addess, as entered in the movie’s properties before publishing.
cpLockTOC [number] Command variable. Setting to 1 disables user interaction on the Table of Contents. Setting to 0 re-enables (unlocks) user interaction.
cpMovieHeight [number] Informational variable. Returns the height of the Captivate project, in pixels.
cpMovieWidth [number] Informational variable. Returns the width of the Captivate project, in pixels.
cpMovieXForEmbededPlaybar [number] Informational variable. Returns the x coordinate (left position) of the Captivate project’s toolbar, if available.
cpMovieXForTOC [number] Informational variable. Returns the x coordinate (left position) of the Captivate project’s Table of Contents movieclip, if available.
cpMovieYForEmbededPlaybar [number] Informational variable. Returns the y coordinate (top position) of the Captivate project’s toolbar, if available.
cpMovieYForTOC [number] Informational variable. Returns the y coordinate (top position) of the Captivate project’s Table of Contents movieclip, if available.
cpOrgSWFPath [string]

Informational variable. Provides the file name for the project’s main SWF. Appears to duplicate functionality of cpOrgSWFPath.

NOTE: This value can only be obtained when the project uses an external skin.

cpQuizInfoAnswerChoice [string] Informational variable. Returns the chosen answer for the quiz question.
cpQuizInfoAttempts [number] Informational variable. Returns the number of times the quiz has been attempted.
cpQuizInfoLastSlidePointScored [number] Informational variable. Returns the score for the last visited quiz slide.
cpQuizInfoMaxAttemptsOnCurrentQuestion [number] Informational variable. Returns the number of attempts allowed for this quiz question.
cpQuizInfoNoQuestionsPerQuiz Informational variable. No information available. Best guess: returns the number of questions in the quiz.
cpQuizInfoPassFail [number] Informational variable. Returns the result of the quiz: pass or fail.
cpQuizInfoPointsPerQuestionSlide [number] Informational variable. Returns the number of points for this quiz question.
cpQuizInfoPointsscored [number] Informational variable. Returns the total number of points scored in the project.
cpQuizInfoQuestionSlideTiming [number] Informational variable. Returns the time limit for the current question (in seconds).
cpQuizInfoQuestionSlideType [string] Informational variable. Returns the current question’s type (multiple-choice, true-false, likert, etc.).
cpQuizInfoQuizPassPercent [number] Informational variable. Returns the passing percentage for the quiz.
cpQuizInfoQuizPassPoints [number] Informational variable. Returns the passing points for the quiz.
cpQuizInfoTotalCorrectAnswers [number] Informational variable. Returns the number of correctly answered quiz questions.
cpQuizInfoTotalProjectPoints [number] Informational variable. Returns the total number of points for the project.
cpQuizInfoTotalQuestionsPerProject [number] Informational variable. Returns the total number of questions for the project.
cpQuizInfoTotalQuizPoints [number] Informational variable. Returns the total number of quiz points for the project.
cpQuizInfoTotalUnansweredQuestions [number] Informational variable. Returns the total number of unanswered questions for the project.
endSwfAction [number] Internal variable. No information available.
expired [boolean] Internal variable. No information available. Best guess: Boolean indicating whether time limit has elapsed.
hasProjectFadeOut [boolean] Internal variable. No information available. Best guess: Boolean indicating whether last slide in project is set to fade out.
inAutoPlayState [boolean] Internal variable. No information available. Best guess: Boolean indicating whether project is set to auto-play.
isCPMovie [boolean] Informational variable. Indicates whether the SWF is a Captivate SWF.
isContiniousModeRecording [number] Internal variable. No information available. (Yes, that’s how it was spelled in the code.)
isCustomizable [boolean]

Internal variable. No information available. Best guess: Indicates whether the skin is customizable.

NOTE: This value can only be obtained when the project uses an external skin.

isForceMuteAudio [boolean] Internal variable. No information available. Best guess: Indicates whether the audio was muted by the user.
isPlayBarBtnClicked [boolean] Internal variable. No information available. Best guess: Indicates whether a specific action was performed via clicking the playbar (such as muting audio).
isPreview [number] Internal variable. No information available. Best guess: Indicates whether the SWF is a preview SWF (used when previewing projects within the Captivate authoring environment).
isPreviewForAudioDialog [boolean] Internal variable. No information available. Best guess: Indicates whether the SWF is a preview SWF (used when previewing projects within the Captivate authoring environment).
isPreviewSkin [boolean] Internal variable. No information available. Best guess: Indicates whether the project SWF’s skin is a preview SWF (used when previewing projects within the Captivate authoring environment).
lmsString [string] Internal variable. No information available. Best guess: The text displayed when Captivate initializes an LMS connection (SCORM, AICC, etc.).
loadedFromAggregator [boolean] Internal variable. No information available. Best guess: Indicates whether the Captivate SWF was loaded as part of an aggregator project.
m_quizPoolColl [object] Internal variable. No information available. Best guess: Object containing question pool questions.
movieQuality [string] Internal variable. No information available. Best guess: Indicates quality setting of SWF playback.

movieXML

[string] in Chrome

[XML] in Firefox

Internal variable, no information available.

NOTE: This item is
:XML data type in AS3. Because browsers have different support for native XML data types, values returned from this variable should not be considered cross-browser. Use at your own risk.

needToMuteAudioForAggregator [boolean]

Internal variable. No information available.

NOTE: This value can only be obtained when the project uses an external skin.

passwordPresent [boolean] Internal variable. Indicates whether a password has been supplied.
pbcBtnTips [object] Internal variable. Alias for pbcBtnTips_ENU.
pbcBtnTips_ENU [object] Internal variable (array). Returns list of tooltips used by the playbar buttons.
playbarBarAlign [number]

Internal variable. No information available.

NOTE: This value can only be obtained when the project uses an external skin.

playbarHeight [number] Informational variable. Returns height of playbar, in pixels.
playbarPosition [number]

Internal variable. No information available.

NOTE: This value can only be obtained when the project uses an external skin.

rdIsInLivePreviewMode [boolean] Internal variable. No information available. Best guess: Indicates whether the SWF is a preview SWF (used when previewing projects within the Captivate authoring environment).
rdIsPreview [boolean] Internal variable. No information available. Best guess: Deprecated variable replaced by isPreview
rdIsPreviewInBrowser [boolean] Internal variable. No information available.
rdIsStandalone [boolean] Internal variable. No information available. Best guess: Deprecated variable replaced by cpInfoIsStandalone
rdcmndCC [number] Command variable (deprecated). Alias for cpCmndCC.
rdcmndExit [number] Command variable. According to Captivate documentation, "Exit the movie. Set to 1 to exit." Has never worked for me.
rdcmndGotoFrame [number] Command variable (deprecated). Alias for cpCmndGotoFrame.
rdcmndGotoFrameAndResume [number] Command variable (deprecated). Alias for cpCmndGotoFrameAndResume.
rdcmndGotoSlide [number] Command variable (deprecated). Alias for cpCmndGotoSlide.
rdcmndMute [boolean] Command variable (deprecated). Alias for cpCmndMute.
rdcmndNext [boolean] Command variable (deprecated). Alias for cpCmndNext.
rdcmndNextSlide [number] Command variable (deprecated). Alias for cpCmndNext.
rdcmndPause [number] Command variable. Setting to 1 will cause the movie to stop playing (pause). Setting to 0 will do nothing.
rdcmndPlaybarMoved [boolean] Command variable (deprecated). Alias for cpCmndPlaybarMoved.
rdcmndPrevious [number] Command variable. Setting to 1 will cause the movie to stop playing (pause). Setting to 0 will do nothing.
rdcmndResume [number] Command variable. Setting to 1 will cause the movie to go backwards to the previous slide. Setting to 0 will do nothing.
rdinfoCurrentFrame [number] Informational variable. Returns current frame number using 0-based index.
rdinfoCurrentSlide [number] Informational variable (deprecated). Alias for cpInfoCurrentSlide.
rdinfoCurrentSlideInProject [number] Informational variable. No information available. Best guess: Alias for cpInfoCurrentSlide.
rdinfoFPS [number] Informational variable. Returns the SWF’s frame rate (in seconds).
rdinfoFrameCount [number] Informational variable. Returns the number of frames in the SWF.
rdinfoHasPlaybar [boolean] Informational variable (deprecated). Alias for cpInfoHasPlaybar.
rdinfoSlideCount [number] Informational variable. Returns the number of slides in the Captivate movie.
rdinfoSlidesInProject [number] Informational variable. No information available. Best guess: An unused/deprecated variable.
rdinfocurrFrame [number] Informational variable. No information available. Best guess: Alias for rdinfoCurrentFrame.
skinHeight [number]

Internal variable. No information available.

NOTE: This value can only be obtained when the project uses an external skin.

skinWidth [number]

Internal variable. No information available.

NOTE: This value can only be obtained when the project uses an external skin.

swfCmtAutoPlay [boolean] Internal variable. No information available. Best guess: Indicates whether the SWF will auto-play when in commenting mode.
swfCommenting [boolean] Internal variable. No information available. Best guess: Indicates whether the SWF is in commenting mode.
tocInitDone [boolean] Internal variable. Indicates when the Table of Contents has finished initializing.
waitCount [number] Internal variable. Indicates how long the SWF has been waiting (used for internal timer-related functions).

CaptivateController Updated to Support Adobe Captivate 5

By popular demand, I’ve updated my CaptivateController to work with Adobe Captivate 5 (CP5). Since this is an open-source project, there’s no upgrade fee. (What? “Adobe” and “no upgrade fee” in the same paragraph?!) I kid, I kid… I’m a kidder.

As you may have heard, Adobe Captivate 5 is a complete re-write of the Adobe Captivate application. As such, there are a few significant changes under-the-hood. For example, Adobe Captivate 5 does not support ActionScript 2, and will only publish to ActionScript 3. The Captivate developers eliminated a few of the old system variables while adding a few new ones. Showing and hiding the playbar now works very reliably (yay!). Most notably, the developers added extra ExternalInterface support via the cpEIGetValue and cpEISetValue callback functions while eliminating the cpSetValue callback, which explains why the previous version of the CaptivateController didn’t work with CP5 SWFs.

As for the updated CaptivateController, it works the same as the previous version. Most of the changes were under-the-hood, so you shouldn’t need to edit any of your code, and should be able to drop this new version on top of your old one. No system restart required!

If you encounter any bugs, please let me know by posting in the comments. I’d also be happy to hear any success stories you may have.

Adobe Captivate: What the heck is g_intAPIType?

If you spend any time using Adobe Captivate to create SCORM-conformant courses, you’re bound to have run into an issue or two that caused you to read some Captivate forum posts. Almost without fail, someone will mention that the solution to their problem was changing the value of the magical g_intAPIType JavaScript variable from 1 to 0 or from 0 to 1.

So what the heck is g_intAPIType, and why does changing it make a difference?

The short version is this: Captivate courses, when published for SCORM, typically use one of two communication methods: FSCommand or getURL. FSCommand works really well in some browsers, such as Internet Explorer, but has spotty support in others. getURL works in all browsers, but uses a more complicated communication system when sending data to your Captivate file from the LMS. It also makes a lot of clicking sounds.

Setting g_intAPIType to 0 means you’re forcing Captivate to use FSCommand in all browsers. Setting g_intAPIType to 1 means you’re forcing Captivate to use getURL in all browsers. If you don’t manually specify the value of g_intAPIType, Captivate’s SCORM template includes some browser sniffing that automatically sets g_intAPIType to 0 for Internet Explorer and 1 for all other browsers.

Want to know more about FSCommand versus getURL? Colin Moock wrote a good FSCommand tutorial that covers the basics.

Note: ExternalInterface has replaced both of these methods as the favored Flash-to-JavaScript communication method, but Captivate has not caught up yet.

Customizing SCORM Manifests in Captivate and Articulate Presenter

Someone recently asked me if it was possible to customize Captivate’s SCORM manifest to reduce the need for manual editing after publishing. In her case, the manifest needed to be edited to include SumTotal TotalLMS’s custom SCORM extensions.  The answer is yes. Here’s how.

Find the Captivate files

Captivate’s publishing files are located at:

C:\Program Files\Adobe\Adobe Captivate 4\Templates\Publish

Make your edits

Find the manifest files (manifest.xml for SCORM 1.2 and manifest2004.xml for SCORM 2004), then make your edits.

If you’re adding custom SCORM extensions such as SumTotal’s c2l_cp extensions, don’t forget to include the supporting XSD files. If you’re using SCORM 2004 you can drop the extra XSD file(s) into the “Manifest2004” folder. If you’re publishing to SCORM 1.2, you’ll need to manually add the custom XSD file to your published files.

Rinse, repeat

You’ll need to repeat the process for every computer in your office that has Captivate installed. Otherwise someone on a different computer may inadvertently publish the Captivate project using the factory publishing templates.

What about Articulate?

You can do the same thing with Articulate Presenter. Their publishing templates are located here:

C:\Program Files\Articulate\Presenter\players\

What feature is missing from your e-learning development tool?

I have some simple questions I’d love to get feedback on.

I’m curious about what people are looking for in their e-learning authoring tools, specifically:

  1. What feature is your current tool missing that you would love to see implemented? Support for team collaboration? Support for themes or custom CSS styling? Support for language localization? A beer dispenser? Etc.
  2. What feature does someone else’s tool have that you’re jealous of?

For me? I wish the most popular tools (Captivate, Articulate, Lectora, etc.) would output cleaner HTML and JavaScript. I also wish there was less reliance on Flash and PowerPoint. But if you read my blog regularly, you probably already knew that!

Please post your opinion in the comments below, and please ask others to give their 2 cents. (You can also reply via twitter if you prefer)

I’m really looking forward to your comments. Thanks!

CaptivateController updated

Bug fixes!

The CaptivateController has been updated to fix the gotoSlideAndPlay and gotoSlideAndStop bugs.

Also, gotoSlideAndPlay and gotoSlideAndStop have been edited to use standard numbering in place of zero-based numbering. This means when you want to jump to slide 4, you use mycontroller.gotoSlideAndPlay(4) instead of mycontroller.gotoSlideAndPlay(3).

I had a number of requests for adding a ‘toggle table of contents’ method, but unfortunately it won’t be added at this time. It turns out that while you can toggle the TOC using the controller, it breaks the Captivate movie’s playbar — the playbar loses awareness of whether the TOC is visible or not. This is therefore not a feature I’m prepared to add. You can still toggle the TOC yourself using KCWebPlaza’s workaround (listed in the comments).

I will continue to monitor the TOC possibilities and would be happy to hear suggestions.

View the original post, download links and (somewhat spartan) documentation here.

Thanks to everyone who contacted me about the bugs.