Skip to content

Instantly share code, notes, and snippets.

@pipwerks
Created January 18, 2012 07:22
Show Gist options
  • Save pipwerks/1631774 to your computer and use it in GitHub Desktop.
Save pipwerks/1631774 to your computer and use it in GitHub Desktop.
Captivate SCORM 2004 Output, fixed RightClick functionality when using SWFObject 2.2
<!DOCTYPE HTML>
<!-- saved from url=(0014)about:internet -->
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@MOVIETITLE</title>
<script>
// set document.domain property here, if it works for your environment/SCORM implementation
// document.domain="";
var CONFIG = {
TITLE: "@MOVIETITLE",
FILEPATH: "@MOVIENAME",
BGCOLOR: "@SKINCOLOR",
FPVERSION: "@FlashPlayerVersion",
WIDTH: "@MOVIEWIDTH",
HEIGHT: "@MOVIEHEIGHT",
WMODE: "@WMODEVALUE",
RIGHTCLICKENABLED: '@IsRightClickFunctionalityRequired',
TARGET: "Captivate",
NOSCORM: "Sorry, but the course is not available at this time (SCORM API not found). Please try again. If you continue to encounter problems, please contact the course administrator."
},
flashvars = {},
params = { bgcolor: CONFIG.BGCOLOR, menu: "false", wmode: CONFIG.WMODE },
attributes = { name: "Captivate" };
</script>
<script src="https://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script src="standard.js"></script>
<script src="SCORM_support/scorm_support.js"></script>
<style>
* { margin: 0; padding: 0; } /* remove all padding and margins on page */
body { text-align: center; background: @SKINCOLOR }
</style>
</head>
<body>
<div id="Captivate">
<noscript>
This course requires JavaScript to be enabled in your browser. Please enable JavaScript, then relaunch the course.
</noscript>
</div>
</body>
</html>
var SCORM_API = null,
unloaded = false,
isInitialized = false,
isTerminated = false,
courseStatus,
value_store = [],
lastCommand,
setValueWasSuccessful = true,
CaptivateSWF; //Cache the reference to the SWF to avoid future lookups
/*
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");
}
}
};
//Used by SWFObject
var callbackFn = function (e){
//e.ref is the <object> aka SWF file. No need for getElementById
if(e.success && e.ref){
CaptivateSWF = e.ref;
CaptivateSWF.tabIndex = -1; //Set tabIndex to enable focus on non-form elements
CaptivateSWF.focus();
//Enable RightClick functionality if needed.
if(CONFIG.RIGHTCLICKENABLED !== ""){
RightClick.init();
}
//Initialze the SCORM API, don't wait for the SWF to do it.
initializeSCORM();
}
};
//Kind of cheating; not as reusable as I'd prefer.
var createWrapper = function (targetID, wrapperID){
var target = document.getElementById(targetID);
if(target){
//Turn the original div into the wrapper div
target.setAttribute("id", wrapperID);
//Create new child element
var new_target = document.createElement("div");
new_target.setAttribute("id", targetID);
//Place original element inside new element.
target.appendChild(new_target);
}
}
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();
//Only embed SWF if SCORM API is found
if(SCORM_API){
//Check to see if right-click functionality
//is required before embedding SWF
if(CONFIG.RIGHTCLICKENABLED !== ""){
//Create wrapper around original target element
swfobject.addDomLoadEvent(function(){
createWrapper("Captivate", "CaptivateContent");
});
}
swfobject.embedSWF(CONFIG.FILEPATH + "?SCORM_API=1.0&SCORM_TYPE=0", CONFIG.TARGET, CONFIG.WIDTH, CONFIG.HEIGHT, CONFIG.FPVERSION, false, flashvars, params, attributes, callbackFn);
} else {
//Provide a useful error message for the learner. Will only show up if SCORM API is not found!
swfobject.addDomLoadEvent(function(){
document.getElementById(CONFIG.TARGET).innerHTML = CONFIG.NOSCORM;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment