Over the last few weeks, I received a few reports that scores were not being saved in the LMS when using my template. Turned out to be a simple oversight on my part, which I have just fixed. Please download the latest version of scorm_support.js (v1.20120328) from GitHub.

Cause and effect

If you’re curious what happened, here’s a quick rundown:

When a SCORM course launches for the first time, the value of cmi.completion_status is "ab-initio". This means the course is a fresh launch with no prior completion attempts, and therefore no historical data in the LMS.

When Captivate launches, it requests a slew of information from the LMS via SCORM_API.GetValue. This includes the usual suspects, such as completion status, suspend data, location, score.raw, score.max, score.min, and score.scaled. However, if the course has never been launched before, suspend_data, location, and the score elements will all be empty (null). If the LMS follows the SCORM spec, it will throw the “element not initialized” error.

In my earlier work on the template, I decided to prevent these “element not initialized” errors by adding some logic to the template, preventing suspend_data, location, and the score elements from being checked when the course status is ab-initio. This was achieved via a regular expression:

if(entryStatus === "ab-initio" && /location|suspend_data|score/g.test(parameter)){
   //prevent action
}Code language: JavaScript (javascript)

Unfortunately, I overlooked one important detail: when the Captivate course loads, it queries the LMS to see which SCORM fields are supported. This is done by requesting the “._children” CMI elements. For example, cmi.score._children will return the string “scaled,min,max,raw” indicating that cmi.score.scaled, cmi.score.min, cmi.score.max, and cmi.score.raw are supported by the LMS.

See any problems yet?

My regular expression was too broad, and prevented cmi.score._children from being queried, making Captivate believe that cmi.score was not supported. Since Captivate thought cmi.score was not supported, it did the right thing and stopped sending cmi.score data to the LMS.

The solution was to make the regular expression a bit more explicit:

if(entryStatus === "ab-initio" && /location|suspend_data|score\.(raw|min|max|scaled)/g.test(parameter)){
   //prevent action
}Code language: JavaScript (javascript)

Instead of blocking any GetValue calls requesting “score” data when the course is ab-initio, we now only block GetValue calls that request specific CMI elements: score.raw, score.min, score.max, and score.scaled. Problem solved.

Similar Posts

10 Comments

  1. Hi Philip!

    It’s a great job! Thanks for it!
    But I have a question:
    What should we change in these codes, if we want to see the SWF in fullscreen?

    First, I tried these:
    CONFIG.swfWidth = “100%”;
    CONFIG.swfHeight = “100%”;

    –> It’s not enough, because the SWF moved to the right bottom corner, so I added to tried this:
    CONFIG.centerSWF = false;

    –>
    It’s working on Chrome,
    but the SWF is too small in IE8,
    and I can see only a blank page in Firefox 8.0.

    What’s your suggestion? What can we do?

    Thanks!
    Peter

  2. thanks for your quick feedback, and I confirm everything is right with the scores with your latest scorm_support.js.

    going further into my tests, I saw that success status was not sent back either. based on what you did, i added “success_status” to the line:

    if(entryStatus === “ab-initio” && /location|suspend_data|success_status|score\.(raw|min|max|scaled)/g.test(parameter)){
    //prevent action
    }

    now everything works fine also for success status, which was important to us, since we use it as a success indicator in our LMS.

  3. @ahsijetaisriche That modification should have no effect — success_status is not being filtered (prevented) by the template, and your modification will merely prevent Captivate from checking cmi.success_status at course launch (ab-initio). I suggest removing the modification and testing some more; if you’re not getting success_status, it’s probably due to something else.

    @peter Set the swfWidth and swfHeight to “100%”, then add some CSS to your HTML file. See this article for examples: http://learnswfobject.com/advanced-topics/100-width-and-height-in-browser/

  4. Thanks for your answer, Philip!

    I have one more question but in other topic… Where can I ask you, if I have any other question?

    I have one more problem with Captivate 5 or 5.5:
    I inserted Text Entry Box with the next parameters:
    – Validate User Input: check
    – Shortcut: Enter

    It often not work correctly when I play it in web browser. I have to press twice Enter key… I tried a lot of change (timing, arrange), but I didn’t find any solution. It appears totally randomly. Have you got any advise?

  5. Philip,

    I downloaded and applied your great work. Which has improved at least my frame of mind about our courses. But we were still seeing some of the issues we had before. So, at my wit’s end, I downloaded the captivate to HTML5 converter so I could get a look at the insides, and maybe fix the things.

    But what I saw in the conversion prompted me to write. The converted files use the Rustici scorm JS.

    It’s not as tidy as yours, but at least it looks like they have realized that the code needed looking at.

  6. @michael Good observation, Adobe has indeed started to use Rustici’s SCORM Driver in their products, which I think is a great decision. Should firm up the SCORM support quite a bit.

  7. Hey Phil,

    We were trying to get your SCORM template to work with our lms, and ran into a couple of issues:

    1. The onBeforeUnload handler was being called whenever we called any custom Javascript from within Captivate on IE only. This terminated the SCORM API prematurely. We had to modify your code to exclude IE from the unbeforeunload call.

    window.onbeforeunload = function () {
        if (!(navigator.appName === 'Microsoft Internet Explorer')) {
            unloadHandler;
        }
    }
    

    2. A few of our Captivate courses are very long, over an hour long with audio. In these courses, the customJavaScript function wasn’t being called at all. After further investigation, we found that CaptivateSWF.PercentLoaded() was returning negative numbers for these courses, never reaching 100% (I know this is a Captivate issue, not sure what we can do to fix this).

    We changed

    if(CaptivateSWF.PercentLoaded() === 100)
    

    to

    if(CaptivateSWF.PercentLoaded() === 100 || CaptivateSWF.PercentLoaded() < 0)
    

    Not the most elegant solution, but it seemed to work.

    Hope this helps someone.

  8. @linda thanks for the feedback, that’s very helpful.

    re #1, that’s odd — are you sure it’s being caused by the template? I’ve never encountered that behavior.

    BTW, onbeforeunload began its life as a proprietary Internet Explorer method, and is not really supported much outside of IE, so the conditional statement that tells all browsers *except* IE to use onbeforeunload is probably not needed, just comment out the whole thing.

    re #2, I’m looking into a different hook that may work better than PercentLoaded. No timeline for development, though… I’m pretty swamped.

    Thanks again for the feedback.

  9. Hey Phil,

    Not sure if it was our LMS or your template, and don’t have time to investigate 🙂 – maybe when things die down a bit I’ll take a look.

    Also, we ran into another issue – (haven’t been able to verify whether this is specific to your template or not – all I know is that the Captivate default template doesn’t do this). On Firefox, Captivate wasn’t registering any clicks UNLESS they first clicked somewhere besides on the swf (on the background, on a tab, on another program…) I added javascript to unfocus the captivate swf in the customJavaScript function and it seems to have worked:

    document.getElementById(‘Captivate’).blur();

Comments are closed.