On Converting Flash to HTML

I received a question from Bob (no, really), who wrote:

I have a question about the newest version of Flash and its HTML publishing option using CreateJS. What do you think of that approach going forward?

I started to write an email response but figured I should probably post it here.

I haven’t been paying much attention to Flash, so I don’t know what the ‘HTML export’ is capable of these days. In general, I’m very wary of converting Flash-based projects to HTML. When Adobe Captivate first released a “publish to HTML5” feature, all it did was convert the SWF animation to a video file, losing all interactivity along the way.

The limitations of the browsers and the HTML5 spec mean you can’t expect a fully 1:1 conversion from Flash to HTML, regardless of libraries like CreateJS. Some of the features found in Flash are still not quite supported in browsers, or might not work quite the way you’d expect. For example, CSS transitions, CSS gradients, and SVG/Canvas support vary widely from browser to browser (though it’s getting better, and there are workarounds aka “polyfills”). Streaming video, which is a breeze in Flash, is not part of the HTML5 Video spec (yet) and is unsupported in browsers. Video and audio codec support is inconsistent. In some cases, devices add new limitations — last time I checked, iOS devices wouldn’t autoplay audio or video in Safari. ‘Play’ couldn’t be scripted, it required the user to press a button.

Publishing to HTML (with the aid of JavaScript libraries like CreateJS) is definitely the way of the future, but I would flip the workflow: use a tool that’s “HTML first”. For my workflow, I always start in HTML then only fall back to Flash if I absolutely have to. I hand-code, but if you want to stick to a WYSIWYG editor, maybe try some of the Adobe Edge products, or go with a third-party product such as Tumult Hype.

If you continue to use Flash as an HTML development tool, temper expectations and test widely, as some things might not work the way you expect when converted to HTML.

And regardless of whether you publish to Flash or HTML, always test the accessibility of your project. Just because it’s HTML doesn’t mean it’s accessible; HTML by nature is more accessible than Flash, but libraries like CreateJS add a lot of complexity to the page, which can easily impact accessibility.

Flash support is increasingly a minefield

Back in 2011, I mentioned that Microsoft was about to halt development of the Silverlight plugin, that Flash mobile was being discontinued, and that Adobe recommended HTML5 for enterprise RIA development instead of Flex, which was being open-sourced. My post was a little long-winded, but the short version was: whoa, the times-are-a-changin’, it’s getting dangerous to rely on browser plugins.

Over the last year, the situation has evolved in an interesting way — browser support for plugins (especially Flash Player) has been considerably restricted by browser vendors due to repeated security vulnerabilities in Flash Player and Java.

Automatically disabling Flash Player

In May 2012, Apple’s Safari browser began automatically disabling outdated versions of Flash Player: “Out-of-date versions of Adobe Flash Player do not include the latest security updates and will be disabled to help keep your Mac secure.” If a webpage contains a SWF but the installed edition of Flash Player is deemed out of date, Safari will display a “blocked plugin” message and inform the user they need to download the latest edition of Flash Player at adobe.com. This change came with Adobe’s blessing.

In January 2013, Mozilla introduced a global “click to play” mechanism that disables ALL plugins in Firefox by default, except the latest edition of Flash Player:  “Our plan is to enable Click to Play for all versions of all plugins except the current version of Flash.”

To Adobe’s credit, Flash Player updates are being released at a fast clip to address known security vulnerabilities. Unfortunately, this has a nasty side effect: you’re very likely to have an outdated edition of Flash Player when you try to view Flash content on a website. (By my unofficial count, there have been at least 13 updates over the past calendar year, averaging about once a month.)

At a recent job, I managed a small network of Macs in classrooms. The Macs were set up to use Adobe’s ‘automatic updates’ feature for Flash Player, but they never seemed to update fast enough — we received numerous complaints from classroom users who couldn’t view Flash content because Safari blocked it.

Internet Explorer’s on-again, off-again relationship with Flash Player

I previously mentioned that Microsoft’s Windows 8 ‘Metro’ mode disabled all plugins, including Flash Player; Microsoft said Internet Explorer in Windows 8 Metro mode “provides an add-on–free experience, so browser plugins don’t load and dependent content isn’t displayed“.

In May 2012 Microsoft changed their minds and enabled Flash in Metro mode. BUT… Microsoft will ship Flash Player as a component of IE 10 (much like Google Chrome does), and will restrict which sites are allowed to run Flash! “While any site can play Flash content in IE10 on the Windows desktop, only sites that are on the Compatibility View (CV) list can play Flash content within Metro style IE.”

In other words, if you don’t have Microsoft’s blessing, your Flash site will not work when viewed in Metro mode.

Update: @chris_sage pointed me to a post by Microsoft written just three days ago where they apparently changed their minds again — almost a year after saying they’d require a whitelist, they now say they support Flash Player by default in Metro mode without requiring sites to be whitelisted.

What it boils down to…

If you develop Flash-based content, it will be more and more of a challenge to provide a smooth, problem-free user experience. For e-learning developers, one of the original lures of Flash was the ubiquity of Flash Player; Flash made it easy to provide the same e-learning experience across browsers and platforms. Due to fragmentation in Flash support, this no longer appears possible.

  • Adobe says: No Flash Player for mobile devices.
  • Microsoft says: No Flash Player on Surface tablets (or other Windows 8/RT tablets) unless the user switches to desktop mode OR gets on our whitelist for Metro mode. We love us some Flash! But we’ll manage the security updates ourselves, thank-you.
  • Mozilla says: Only the latest edition of Flash Player for Firefox.
  • Apple says: No Flash Player on Apple iOS devices, and only the latest edition of Flash Player for desktop Safari.
  • Opera says: Flash Player on desktop editions of Opera? No problem. Flash Player in Opera Mobile? Don’t get mad at us, Adobe stopped providing Flash Player for mobile devices!
  • Google says: We control Flash Player for Chrome (desktop) ourselves. No worries. Flash Player in Chrome on mobile devices? Don’t get mad at us, Adobe stopped providing Flash Player for mobile devices!

The browser vendors are enforcing their will. You don’t have to be a Flash-hater to see that building Flash-dependent sites is a minefield.

For those of you in e-learning who depend almost completely on Flash-based courseware, it’s a good idea to start looking for alternatives.

 

 

Introducing SWFRightClick

Adobe Captivate currently ships with a 3rd-party JavaScript utility named RightClick.js, which enables the Captivate SWF to detect when a user right-clicks the SWF. While upgrading the Captivate publishing templates, I realized RightClick.js wasn’t built to work with SWFObject 2.x and suffered from a few shortcomings. I modified the Captivate template’s SWFObject code to get around the issue, but marked it down as something to revisit when I have the time.

Now, I’m happy to report I’ve created a replacement for the RightClick.js utility, creatively named SWFRightClick. It uses the same approach to handling right-clicks, but does it with a completely new codebase and a few extra goodies. SWFRightClick is compatible with every edition of SWFObject, and is free to use (MIT license).

Check it out on GitHub. I plan to fold it in to my Captivate publishing templates very soon.

HTML5, Flash, Silverlight, and your courseware

What a busy week.

Flash is dead. Sort of, but not really.

In case you haven’t heard, Adobe formally announced the discontinuation of Flash Player for mobile devices (“Flash to Focus on PC Browsing and Mobile Apps; Adobe to More Aggressively Contribute to HTML5“). Adobe employees struggled to come to grips with what has undoubtedly been a tough week for them — aside from the product news, they were also informed of massive layoffs (around Adobe 750 employees). Regardless of your feelings about Flash, your heart must go out to the families affected by a sudden job loss.

Flash critics were quick to declare Flash dead. But in the immortal words of Monty Python’s Eric Idle, “I’m not quite dead yet.”

Yes, Adobe is scaling back on Flash to focus more energy on so-called HTML5 technologies (“so-called” because many of the technologies involved are not actually part of the HTML5 spec.) However, their public announcement was that mobile Flash is dead, and Flash on the desktop will continue to thrive.

Flex is being abandoned

Then the “Official Flex Team Blog” dropped a bombshell: Adobe Flex is going open-source:

Yes. We know Flex provides a unique set of benefits for enterprise application developers. We also know that the technology landscape for application development is rapidly changing and our customers want more direct control over the underlying technologies they use. Given this, we are planning to contribute the Flex SDK to an open source foundation in the same way we contributed PhoneGap to the Apache Foundation when we acquired Nitobi.

Okay. Flex is being open-sourced. To be honest, this isn’t really shocking news to me since Flex has mingled with Eclipse for a long time and has had its toes in open source for ages. The part that made my jaw drop was in the next section:

Does Adobe recommend we use Flex or HTML5 for our enterprise application development?
In the long-term, we believe HTML5 will be the best technology for enterprise application development. We also know that, currently, Flex has clear benefits for large-scale client projects typically associated with desktop application profiles.

Given our experiences innovating on Flex, we are extremely well positioned to positively contribute to the advancement of HTML5 development, starting with mobile applications. In fact, many of the engineers and product managers who worked on Flex SDK will be moving to work on our HTML efforts. We will continue making significant contributions to open web technologies like WebKit & jQuery, advance the development of PhoneGap and create new tools that solve the challenges developers face when building applications with HTML5.

In the long-term, we believe HTML5 will be the best technology for enterprise application development. For those of you unfamiliar with Flex, it’s Adobe’s ‘enterprise-level’ Flash development path. Designers use Flash Professional and the timeline, while programmers use Flex and its pure ActionScript/MXML environment. This line is basically saying “see ya, Flex, was nice knowing you. We’re putting our best guys — the ones who weren’t laid off — on the ‘HTML5’ train.”

By extension, if Adobe is wiping its hands of Flex, it means they’re seriously scaling back support for the entire Flash ecosystem.

Whoa. The anti-Flash crowd really does have reason to celebrate. But not so quick, my friends: Support for the HTML5 environment is nowhere near Flash’s level of ubiquity, it will take a couple of years to get there, and even then, I doubt it will have the full capabilities Flash offers today.

But does it matter? Let me come back to that in a minute.

Silverlight is dead. Sort of, but not really

For now, lets turn our attention to our friends in Redmond, WA. While Adobe created this week’s loudest thunder, Microsoft made a few waves itself. If you recall, about a year ago one of Microsoft’s presidents (yes, they have more than one) caused a stir when he said “HTML is the only true cross platform solution for everything, including (Apple’s) iOS platform”. Microsoft quickly issued a statement backtracking from the implication that Silverlight was on its way out, and stressed their commitment to Silverlight.

A year later, the circus is back in town. According to some industry sources, Microsoft is planning to stop development of future editions of Silverlight; version 5 may be the last hurrah, except for security updates. Stop me if this sounds familiar.

However, this time around, the rumor sounds much more feasible because of Internet Explorer 10.

Microsoft’s Internet Explorer, that grand ol’ browser, is going through a major metamorphosis. In general, Internet Explorer 10 will behave less like its ancestors and more like Firefox and Webkit (Safari/Chrome). For example, IE 10 will not support Microsoft’s long-standing conditional comments. This is a big deal for web developers, as conditional comments have become a major crutch when dealing with Internet Explorer. But the biggest news I’ve heard about IE 10 thus far is that it will not support plugins — Flash, Silverlight, Quicktime, etc. — when running in “Metro” mode. Microsoft’s Windows 8 team believes that removing plugins from IE will result in improvements across-the-board: security, reliability, privacy, battery life in mobile devices, etc.

For the web to move forward and for consumers to get the most out of touch-first browsing, the Metro style browser in Windows 8 is as HTML5-only as possible, and plug-in free. The experience that plug-ins provide today is not a good match with Metro style browsing and the modern HTML5 web.

Running Metro style IE plug-in free improves battery life as well as security, reliability, and privacy for consumers. Plug-ins were important early on in the web’s history. But the web has come a long way since then with HTML5. Providing compatibility with legacy plug-in technologies would detract from, rather than improve, the consumer experience of browsing in the Metro style UI.

Plugins will still be supported in the non-Metro environment, but it appears Microsoft’s way of the future is Metro, and Metro is HTML5-based, with no plugins allowed, just like Apple iOS. Microsoft is clearly serious about leaving plugins behind, including its own Silverlight Player.

The analysis

Flash and Silverlight are not dead, but are being minimized by their owners. If you read the articles closely, you’ll see a pattern: both Adobe and Microsoft hope to port some of the technology from their plugins to the open web, aka the “HTML5 ecosystem”.

As it currently stands, browser technology and HTML5 ubiquity will take a number of years to catch up to the baseline capabilities of Flash and Silverlight. Even then, I doubt browsers will have some of the advanced capabilities Flash offers today.

The thing is, I don’t think most Flash developers take full advantage of Flash’s capabilities; they seem to use the same basics they’ve been using for years. The cutting-edge stuff is nowhere near as common as the mundane: video players, slideshows, and simple games.

Today’s editions of Firefox, Chrome, Safari, and even Internet Explorer 9 are massively capable browsers. JavaScript, canvas, and CSS3 can be used to replicate many of Flash’s features. The real question becomes: what are you trying to do?

Video

The vast majority of Flash usage appears to be for serving streaming video. HTML5’s video support is not quite ready to replace Flash in this regard, but it’s getting pretty close. The codec wars are the biggest stumbling block, followed by support for DRM and perhaps a handful of advanced features. If you have a simple video that doesn’t need DRM and can be served via two codecs (H264 and OGG or WebM), you can proceed directly to Go, collect $200.

Need to add some interactivity to your movie? Canvas and JavaScript can do an awful lot. Projects like WebGL and Mozilla’s popcorn.js are upping the ante. The future looks pretty bright for native online video.

Gaming

Flash-based gaming is another strong user base. My kids have been using NeoPets and similar sites for years, so I understand just how far and deep Flash gaming goes in our community. But some of these games are deceptively simple with their graphics, and I wouldn’t be surprised if Adobe’s HTML5 tools soon enable Flash game developers to port their games to the HTML5 ecosystem.

Apple’s iOS and Facebook have created big-money opportunities for game developers willing to switch gears to HTML5. We’ve already seen JavaScript/HTML ports of Nintendo games, including the best video game ever made: Super Mario Brothers. They work. They’re fun. Yes, it will take a long time to get market saturation, but HTML5 already has its foot in the door and a lot of money behind it — gaming is big business!

E-Learning

If you’re reading this blog, chances are good that you’re an e-learning developer. You probably also know that most major e-learning rapid development software outputs Flash SWFs. I can’t think of any industry aside from online gaming that is so utterly dependent on Flash at the moment. This has worried me for years — I’ve long preached that e-learning developers should be less reliant on Flash.

When Apple’s iPad was released without Flash support, the outcry from the e-learning industry was fierce. I also feel it was misplaced — it clearly showed the industry’s reliance on a plugin, and rather than focus on removing the Flash requirement barrier, many people chose to plant their feet in the ground and buy non-Apple devices as a form of protest. Some vendors, to their credit, modified their products (Raptivity, Lectora, Rapid Intake, etc.) to take steps away from plugin requirements and towards modern HTML5 experiences. (I admit I haven’t tried the HTML5 editions of these products yet, so I can’t speak to their quality.)

Don’t get me wrong, I’m not anti-Flash — anyone who follows this blog knows that I work with ActionScript and am a member of the SWFObject project team — I just think browsers plugins should be used sparingly, with decent fallbacks in place for people who don’t have Flash, such as video transcripts for people who can’t see the video.

My personal development approach has been to develop the course interface and base pages in HTML/JavaScript, and only use Flash when necessary, such as when playing a video or providing a software simulation experience. Now that native video playback is possible in modern browsers, it’s easy to go back and retrofit courses to use HTML5 video. Same goes for audio if you like to have narration in your course. Some situations, such as software simulations, are much trickier, but this is where we rely on tool vendors to improve their tools. For example, Adobe is working on enabling Captivate to output to HTML5 (it currently only outputs a non-interactive video version of the SWF).

Quizzes, fun interactions, and elegant slideshows are all possible with JavaScript today, even in lowly Internet Explorer 6. I have no idea why a simple course system like Articulate Presenter doesn’t provide an HTML5 publishing option yet… interactions can be handled via JavaScript. Narration can be handled via HTML5’s audio element. Quizzes can be handled by JavaScript (though I admit the security is not as strong when you can’t obfuscate answers via a SWF). Even Captivate should be farther along than it is, but at least they’re making progress.

Hopefully this week’s news about Adobe and Microsoft shifting gears away from plugins will help the more hard-headed among us in the e-learning industry to take a more active role in moving away from Flash and towards a true native web experience.

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.

Fear of sharing, fear of failing

Janet Clarey posted a link to a great blog post by Rajesh Setty entitled Why some smart people are reluctant to share? Setty’s insights resound with me, not because I think I’m smart — quite the opposite, actually — but because the more I learn, the more I’m aware of my limitations.

Setty tried to determine why “smart people” are often reluctant to share their knowledge with others. His conclusion was:

Smart people want to give their best and as they learn more, they learn that they need to learn a lot more before they start sharing. They learn some more and they learn they need to learn some more. What they forget is that most of the expertise that they already have is either becoming “obvious” to them or better yet, going into their “background thinking.”

I agree with the points in Setty’s post completely, except in I’d substitute the word “experienced” for “smart.”

Setty’s line “Smart people want to give their best” seems to be something of a passing thought in his post. I’d like to give it more attention, because I believe conscientious experienced folks have a fear of giving bad advice.

Zeldman had it right when he said “If your old work doesn’t shame you, you’re not growing.” Experienced people look back at their younger, inexperienced self and either chuckle at their own gumption or get rosy-cheeked from embarrassment. I’m more of the rosy-cheeked guy. My old work shames me all the time, and it often causes me to hesitate when sharing my work or giving advice to others.

This may sound funny to some of you… anyone who follows this blog probably knows I spend a lot of time doling out technical advice via places like the SWFObject and eLearning Technology and Development Google Groups.  The truth is, I question myself in almost each and every post I write. Why? Because I’m experienced enough to know that maybe I shouldn’t be so quick and cocky with an answer. Maybe there’s a different solution I haven’t heard of. To paraphrase Setty, maybe I need to learn more first.

So why do I even try to give advice if I have a fear of giving bad advice? Because I want to learn more. I often find that helping others is the best way to teach myself. I’ve learned a ton through helping others, and find it rewarding in many ways. Except when I’m wrong, and then it plain sucks.

Cheating in SCORM

I’m always surprised how little people talk about cheating in e-learning; maybe it’s a fear of revealing just how easy it can be. The fact is, SCORM — the most common communication standard in e-learning — is fairly easy to hack. It uses a public JavaScript-based API that is easy to tap into and feed false data, and because it’s a standard, you know exactly what methods and properties are available in the API. It doesn’t matter what vendor or product produced the course (Articulate, Adobe, etc.)… if it uses SCORM, it’s vulnerable.

I’ve whipped up a proof-of-concept bookmarklet that when clicked will set your SCORM course to complete with a score of 100 (works with both SCORM 1.2 and 2004).

This bookmarklet isn’t guaranteed to work with all courses… it’s just a demonstration of what’s possible, and could be made much more sophisticated by someone highly motivated to cheat.

As e-learning continues to boom, we should be looking into ways of making courses more secure and more difficult to hack. I believe higher security should be achievable with current web technologies. For instance, how about requiring any score or completion data to be accompanied by a unique encrypted security key? Then no external script could inject false data because it wouldn’t have the required security key.

I don’t think cheating is a problem at the moment, but we should be proactive and implement better security before it becomes a problem.

Update #1: For those who are curious, the bookmarklet has been successfully tested in a few LMSs and test environments, but I won’t be revealing which ones. For those interested in the tech specs, the bookmarklet is an anonymous JavaScript function with no global variables. It was error-checked in JS Lint then compressed with the ‘shrink variables’ option enabled, which means it’s pretty hard to decipher. If you’re interested in seeing the uncompressed code, post a comment below with your email and I’ll consider sending a copy.

Update #2: The bookmarklet has been taken down. I am no longer distributing the code, though you’re welcome to write your own.