Created
January 14, 2012 07:57
-
-
Save pipwerks/1610662 to your computer and use it in GitHub Desktop.
Captivate SCORM 2004 Output, preventing redundant GetLastError calls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global CaptivateSWF */ | |
var SCORM_API = null, | |
unloaded = false, | |
isInitialized = false, | |
isTerminated = false, | |
courseStatus, | |
value_store = [], | |
lastCommand, | |
setValueWasSuccessful = true; | |
/* | |
cmiCache(property, value) | |
Caches CMI value to help prevent sending duplicate data to LMS | |
Parameters: property (CMI property name), value (CMI value, normally a string) | |
Returns: property value if cached version found, false if not cached. | |
*/ | |
var cmiCache = function(property, value){ | |
//Ensure we have a valid property to work with | |
if(typeof property === "undefined"){ return false; } | |
//Replace all periods in CMI property names so we don't run into JS errors | |
property = property.replace(/\./g,'_'); | |
//If cached value exists, return it | |
if(typeof value_store[property] !== "undefined"){ | |
return value_store[property]; | |
} | |
//Otherwise add to cache | |
if(typeof value !== "undefined"){ | |
value_store[property] = value; | |
} | |
return false; | |
}; | |
/* | |
findAPI(window) | |
Adapted from pipwerks SCORM wrapper | |
https://github.com/pipwerks/scorm-api-wrapper | |
Looks for an object named API in parent and opener windows | |
Parameters: window (the browser window object). | |
Returns: Object if API is found, null if no API found | |
*/ | |
var findAPI = function(win){ | |
var API, | |
findAttempts = 0, | |
findAttemptLimit = 500; | |
while (!win.API_1484_11 && win.parent && win.parent != win && findAttempts <= findAttemptLimit){ | |
findAttempts++; | |
win = win.parent; | |
} | |
API = win.API_1484_11 || null; | |
/* | |
if(!API){ | |
alert("Error finding API. \nFind attempts: " +findAttempts +". \nFind attempt limit: " +findAttemptLimit); | |
} | |
*/ | |
return API; | |
}; | |
/* | |
getAPI() | |
Adapted from pipwerks SCORM wrapper | |
https://github.com/pipwerks/scorm-api-wrapper | |
Looks for an object named API_1484_11, first in the current window's frame | |
hierarchy and then, if necessary, in the current window's opener window | |
hierarchy (if there is an opener window). | |
Parameters: None. | |
Returns: Object if API found, null if no API found | |
*/ | |
var getAPI = function(){ | |
var API = null, | |
win = window; | |
//Look in parent windows first | |
if(win.parent && win.parent != win){ | |
API = findAPI(win.parent); | |
} | |
//Look in opener windows next | |
if(!API && win.top.opener){ | |
API = findAPI(win.top.opener); | |
} | |
//Plateau LMS needs special hand-holding | |
if(!API && win.top.opener && win.top.opener.document) { | |
API = findAPI(win.top.opener.document); | |
} | |
//if(!API){ alert("getAPI failed: Can't find the API!"); } | |
return API; | |
}; | |
var Captivate_DoExternalInterface = function (command, parameter, value, variable) { | |
console.log("Captivate_DoExternalInterface: " +command +", " +parameter +", " +value); | |
var strErr = "true", | |
intercept = false; | |
//Ensure SCORM API was initialized | |
if(!isInitialized){ return; } | |
if(command === "Initialize"){ | |
//We already initialized, just nod politely | |
//and tell the SWF everything is okay! | |
} else if(command === "SetValue"){ | |
if(parameter === "completion_status"){ courseStatus = value; } | |
//Check to see if value is already cached | |
var cached_value = cmiCache(parameter, value); | |
//Only send value to LMS if it hasn't already been sent; | |
//If value is cached and matches what is about to be sent | |
//to the LMS, prevent value from being sent a second time. | |
if(!cached_value || cached_value !== value){ | |
console.log(parameter +"(" +value +") is not cached. Sending to LMS."); | |
strErr = SCORM_API.SetValue(parameter, value); | |
setValueWasSuccessful = (strErr === "true"); | |
} else { | |
console.log(parameter +"(" +value +") has already been sent. Preventing redundant LMS communication."); | |
//Fakin' it for Captivate's sake. | |
setValueWasSuccessful = true; | |
} | |
} else if(command === "Terminate"){ | |
strErr = SCORM_API.Terminate(""); | |
isTerminated = (strErr === "true"); | |
} else if(command === "Commit"){ | |
strErr = SCORM_API.Commit(""); | |
} else if(command === "GetLastError"){ | |
if(lastCommand === "SetValue" && setValueWasSuccessful){ | |
strErr = ""; | |
console.log("Last Get/Set was successful. Preventing pointless GetLastError invocation."); | |
} else { | |
strErr = SCORM_API.GetLastError(); | |
} | |
} else if(value && value.length > 0){ | |
strErr = SCORM_API[command](parameter); | |
} | |
CaptivateSWF.SetScormVariable(variable, strErr); | |
lastCommand = command; | |
return strErr; | |
}; | |
var initializeSCORM = function (){ | |
isInitialized = SCORM_API.Initialize(""); | |
if(isInitialized){ | |
console.log("SCORM initialized. Ready to go!"); | |
courseStatus = SCORM_API.GetValue("cmi.completion_status"); | |
if(courseStatus === "not attempted"){ | |
SCORM_API.SetValue("cmi.completion_status", "incomplete"); | |
} | |
} | |
}; | |
var unloadHandler = function (){ | |
if(!unloaded && isInitialized && !isTerminated){ | |
var exit_status = (courseStatus === "incomplete") ? "suspend" : "normal"; | |
SCORM_API.SetValue("cmi.exit", exit_status); //Set exit to whatever is needed | |
SCORM_API.Commit(""); //Ensure that LMS saves all data | |
isTerminated = (SCORM_API.Terminate("") === "true"); //close the SCORM API connection properly | |
unloaded = true; //Ensure we don't invoke unloadHandler more than once. | |
} | |
}; | |
window.onbeforeunload = unloadHandler; | |
window.onunload = unloadHandler; | |
//Initialize SCORM API | |
SCORM_API = getAPI(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment