SCORM and Flash: Getting
started
This is the JavaScript
for the the alms_sco.js file. This is part of the full tutorial available
from Alpha LMS' Briefings page.
//these
four variables, along with the two functions ScanForAPI and
var nFindAPITries =
0;
var API = null;
var maxTries = 500;
var APIVersion = "";
//some
string variables to avoid repeat typing of text in the code
var STR_SETTING = "setting
";
var STR_SCORERAW = "cmi.core.score.raw";
var STR_SCOREMAX = "cmi.core.score.max";
var STR_LESSONSTATUS= "cmi.core.lesson_status";
var STR_EXIT = "cmi.core.exit";
var STR_WITHVALUE = " with value ";
//GetAPI
are given in then SCORM documentation as the recommended
//way of locating the API in either an opener or parent window
function ScanForAPI(win)
{
while ((win.API ==
null)
&& (win.parent != null)
&& (win.parent != win)) {
nFindAPITries++;
if (nFindAPITries > maxTries) {
alert("Error
in finding API instance -- too deeply nested.");
return null;
}
win = win.parent;
}
return win.API;
}
function GetAPI() {
if ((window.parent
!= null) && (window.parent != window)) {
API = ScanForAPI(window.parent);
}
if ((API == null) && (window.opener != null)) {
API = ScanForAPI(window.opener);
}
}
//Here
are two utilities: one to handle error-checking and one to
//find whether the LMS supports a particular data field. This
//function should be called after every call to the API
function scormCheckError(context)
{
var errorCode = API.LMSGetLastError();
if (errorCode != 0) {
alert("Error
" + context + ": " + API.LMSGetErrorString(errorCode));
}
}
//scormFindChild
is a utility which checks to see whether the value
//child exists within the comma-separated list of children. Some data
//fields do not have to be supported by an LMS. This is the way of
//checking whether a feature is supported before using it.
//See scormClose() for the use of this function.
function scormFindChild(childElement, child) {
var isFound = false;
var children = API.LMSGetValue(childElement);
var childArray = new Array();
childArray = children.split(",");
scormCheckError("getting children for " + children);
for (var i=0; (i<childArray.length); i++) {
if (childArray[i]
== child) {
isFound = true;
break;
}
}
return isFound;
}
//here is code to support our assessment model.
If an API object is
//found, LMSInitialize must be called first and LMSFinish last. You
//will normally call LMSCommit before LMSFinish to ensure that all
//values are persisted. In between these, we may call LMSSetValue,
//to pass data back to the LMS, LMSGetValue to read data from the
//LMSGetLastError and LMSGetErrorString if things go wrong. We will
//use three functions: ScormInitialize to get things going, ScormCommand
to
//deal with the fscommand events occurring in the Flash animation, and
//ScormClose to tidy up at the end.
//ScormClose
might be called in one of two ways: (a) when the Flash
//movie finishes and issues an fscommand("finish", "");
or if the student
//closes the browser window before finishing. To avoid calling ScormClose
//twice, we need to track whether our scorm session is active.
var scormActive = false;
//these
variables will keep track of the student's progress through the SCO
var marksTotal; //will be set in the SCO's html
var marksDone = 0;
var marksScored = 0;
var scormStatus = "not attempted";
var marksReturned = false;
//scormStart()
will get called whenever our html page loads
function scormStart() {
GetAPI();
if (API != null) {
API.LMSInitialize("");
scormCheckError("initializing API");
scormActive = true;
//we might load bookmarking information here,
but we'll leave that for
//next time
}
}
//scormClose
will get called at the end, either when the movie finishes or
//when the student closes the window without finishing the movie. We will
//return some minimum information: score, status, exit and marksDone.
These
//fields
are all mandatory fields for the LMS, except for core.score.max,
//Before returning core.score.max we need to find
whether this is supported
//by the LMS
function scormClose() {
if (scormActive) {
//prevent closing
twice
scormActive = false;
//return normalized score
if (marksTotal > 0) {
//under
SCORM 1.2, raw score is always returned as a
//normalized percentage
alert("Setting scoreRaw: marksScored = " + marksScored
+ "; marksTotal = " + marksTotal);
var scoreRaw = (marksScored / marksTotal) * 100;
alert("ScoreRaw = " + scoreRaw);
API.LMSSetValue(STR_SCORERAW, scoreRaw);
scormCheckError(STR_SETTING + STR_SCORERAW + STR_WITHVALUE + scoreRaw);
}
//return max score (what the student could have
scored if he got all
//questions presented right
if ((marksTotal > 0) && (scormFindChild("cmi.core.score._children",
"max"))) {
var maxScore =
(marksScored / marksTotal) * 100;
alert("maxScore = " + maxScore);
API.LMSSetValue(STR_SCOREMAX, maxScore);
scormCheckError(STR_SETTING + STR_SCOREMAX + STR_WITHVALUE + maxScore);
}
//set lesson_status
if (marksReturned) {
if (marksDone
= marksTotal) {
scormStatus
= "completed";
} else {
scormStatus
= "incomplete";
}
} else {
scormStatus =
"browsed";
}
API.LMSSetValue(STR_LESSONSTATUS, scormStatus);
scormCheckError(STR_SETTING + STR_LESSONSTATUS + STR_WITHVALUE + scormStatus);
//set normal exit
API.LMSSetValue("cmi.core.exit", "");
scormCheckError(STR_SETTING + STR_EXIT + STR_WITHVALUE);
//commit and finish
API.LMSCommit("");
scormCheckError("committing to API");
API.LMSFinish("");
scormCheckError("finishing SCORM session");
}
}
//scormCommand
will deal with the fscommand messages from the movie
//we will not pass this data to the LMS, but just keep tote of the score
//in local JavaScript variables until the time comes to finish the unit
function scormCommand(command,
params) {
if (command == "mark")
{
marksReturned = true;
var paramArray = new Array();
paramArray = params.split(",");
if (paramArray.length != 3) {
alert("Error:
mark command must have three parameters");
} else {
if (paramArray[1]
> paramArray[2]) {
alert("Error:
cannot score more than total marks available");
} else {
//we
will ignore question numbers for the time being
var newMarksDone = marksDone + eval(paramArray[2]);
if (newMarksDone > marksTotal) {
alert("Error:
marks done cannot be more than total marks");
} else {
marksDone
= newMarksDone;
marksScored += eval(paramArray[1]);
}
}
}
} else {
if (command == "finish")
{
scormClose();
}
}
}
|