diff --git a/README.md b/README.md index 487d87d..7c889c9 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,6 @@ This javascript file is typically used in SCORM 2004 courses. If the ADL-provid Note: The updated APIWrapper.js file does not stand-alone and MUST be used with the SCORMToXAPIFunctions.js file. ## SCORM1.2/APIWrapper.js -NOTE - THIS VERSION IS CURRENTLY OUT OF DATE. PLEASE SEE THE 2004 WRAPPER UNTIL THIS ISSUE IS ADDRESSED. - Javascript SCORM 1.2 API wrapper with new xAPI object (Implemented in SCORMToXAPIFunctions.js). This javascript file is typically used in SCORM 1.2 courses. If the ADL-provided ADLWrapper.js file is used in your SCORM courses, it can be replaced with this file. @@ -57,15 +55,18 @@ var activity = ; Finally, several configuration values must be set in the updated APIWrapper.js file (init method). Instructions are also included in the header at the top of the JavaScript file. Near the top of the file, configure the following lines of code: ```JavaScript - var config = { - lrs:{ - endpoint:"https://lrs.adlnet.gov/xapi/", - user:"", - password:"" - }, - courseId:"", - lmsHomePage:"" - }; + var config = { + lrs: { + endpoint: "https://lrs.adlnet.gov/xapi/", + user: "", + password: "" + }, + courseId: "", + lmsHomePage: "", + isScorm2004: true, + activityId: "", + groupingContextActivity: {} + }; ``` ### Limitations diff --git a/SCORM1.2/APIWrapper.js b/SCORM1.2/APIWrapper.js index 1d835aa..11a7361 100755 --- a/SCORM1.2/APIWrapper.js +++ b/SCORM1.2/APIWrapper.js @@ -125,7 +125,7 @@ retrieveDataValue = doLMSGetValue; ** false if the initialization failed. ** ** Description: -** Initialize communication with LMS by calling the LMSInitialize +** Initialize communication with LMS by calling the doLMSInitialize ** function which will be implemented by the LMS. ** *******************************************************************************/ @@ -136,33 +136,23 @@ function doLMSInitialize() var api = getAPIHandle(); if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSInitialize was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSInitialize was not successful."); return "false"; } - var result = api.LMSInitialize(""); + var result = api.doLMSInitialize(""); + if (result.toString() != "true") { var err = ErrorHandler(); - message("LMSInitialize failed with error code: " + err.code); + message("doLMSInitialize failed with error code: " + err.code); } else { - initialized = true; - - // xAPI Extensions - var config = { - lrs:{ - endpoint:"", - user:"", - password:"" - }, - courseId:"", - lmsHomePage:"", - isScorm2004:false - }; // isSCORM2004:true above - to convert SCORM 2004 courses - xapi.setConfig(config); - xapi.initializeAttempt(); + initialized = true; + + //xAPI Extension + xapi.initializeAttempt(); } @@ -177,7 +167,7 @@ function doLMSInitialize() ** false if failed. ** ** Description: -** Close communication with LMS by calling the LMSFinish +** Close communication with LMS by calling the doLMSFinish ** function which will be implemented by the LMS ** *******************************************************************************/ @@ -188,7 +178,7 @@ function doLMSFinish() var api = getAPIHandle(); if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSFinish was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSFinish was not successful."); return "false"; } else @@ -196,12 +186,12 @@ function doLMSFinish() // xAPI Extension xapi.terminateAttempt(); - // call the LMSFinish function that should be implemented by the API - var result = api.LMSFinish(""); + // call the doLMSFinish function that should be implemented by the API + var result = api.doLMSFinish(""); if (result.toString() != "true") { var err = ErrorHandler(); - message("LMSFinish failed with error code: " + err.code); + message("doLMSFinish failed with error code: " + err.code); } } @@ -220,31 +210,32 @@ function doLMSFinish() ** input value. ** ** Description: -** Wraps the call to the LMS LMSGetValue method +** Wraps the call to the LMS doLMSGetValue method ** *******************************************************************************/ function doLMSGetValue(name) { + var api = getAPIHandle(); var result = ""; if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSGetValue was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSGetValue was not successful."); } else if (! initialized && ! doLMSInitialize()) { var err = ErrorHandler(); // get why doLMSInitialize() returned false - message("LMSGetValue failed - Could not initialize communication with the LMS - error code: " + err.code); + message("doLMSGetValue failed - Could not initialize communication with the LMS - error code: " + err.code); } else { - result = api.LMSGetValue(name); + result = api.doLMSGetValue(name); var error = ErrorHandler(); if (error.code != _NoError.code) { // an error was encountered so display the error description - message("LMSGetValue("+name+") failed. \n"+ error.code + ": " + error.string); + message("doLMSGetValue("+name+") failed. \n"+ error.code + ": " + error.string); result = ""; } } @@ -260,7 +251,7 @@ function doLMSGetValue(name) ** false if failed. ** ** Description: -** Wraps the call to the LMS LMSSetValue function +** Wraps the call to the LMS doLMSSetValue function ** *******************************************************************************/ function doLMSSetValue(name, value) @@ -269,23 +260,23 @@ function doLMSSetValue(name, value) var result = "false"; if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSSetValue was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSSetValue was not successful."); } - else if (! initialized && ! doLMSInitialize()) + else if (!initialized && !doLMSInitialize()) { var err = ErrorHandler(); // get why doLMSInitialize() returned false - message("LMSSetValue failed - Could not initialize communication with the LMS - error code: " + err.code); + message("doLMSSetValue failed - Could not initialize communication with the LMS - error code: " + err.code); } else { // xAPI Extension xapi.saveDataValue(name, value); - result = api.LMSSetValue(name, value); + result = api.doLMSSetValue(name, value); if (result.toString() != "true") { var err = ErrorHandler(); - message("LMSSetValue("+name+", "+value+") failed. \n"+ err.code + ": " + err.string); + message("doLMSSetValue("+name+", "+value+") failed. \n"+ err.code + ": " + err.string); } } @@ -309,20 +300,20 @@ function doLMSCommit() var result = "false"; if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSCommit was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSCommit was not successful."); } - else if (! initialized && ! doLMSInitialize()) + else if (!initialized && ! doLMSInitialize()) { var err = ErrorHandler(); // get why doLMSInitialize() returned false - message("LMSCommit failed - Could not initialize communication with the LMS - error code: " + err.code); + message("doLMSCommit failed - Could not initialize communication with the LMS - error code: " + err.code); } else { - result = api.LMSCommit(""); + result = api.doLMSCommit(""); if (result != "true") { var err = ErrorHandler(); - message("LMSCommit failed - error code: " + err.code); + message("doLMSCommit failed - error code: " + err.code); } } @@ -336,7 +327,7 @@ function doLMSCommit() ** Return: The error code that was set by the last LMS function call ** ** Description: -** Call the LMSGetLastError function +** Call the doLMSGetLastError function ** *******************************************************************************/ function doLMSGetLastError() @@ -344,12 +335,12 @@ function doLMSGetLastError() var api = getAPIHandle(); if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSGetLastError was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSGetLastError was not successful."); //since we can't get the error code from the LMS, return a general error return _GeneralException.code; //General Exception } - return api.LMSGetLastError().toString(); + return api.doLMSGetLastError().toString(); } /******************************************************************************* @@ -359,7 +350,7 @@ function doLMSGetLastError() ** Return: The textual description that corresponds to the input error code ** ** Description: -** Call the LMSGetErrorString function +** Call the doLMSGetErrorString function ** ********************************************************************************/ function doLMSGetErrorString(errorCode) @@ -367,11 +358,11 @@ function doLMSGetErrorString(errorCode) var api = getAPIHandle(); if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSGetErrorString was not successful."); + message("Unable to locate the LMS's API Implementation.\ndoLMSGetErrorString was not successful."); return _GeneralException.string; } - return api.LMSGetErrorString(errorCode).toString(); + return api.doLMSGetErrorString(errorCode).toString(); } /******************************************************************************* @@ -382,7 +373,7 @@ function doLMSGetErrorString(errorCode) ** input error code ** ** Description: -** Call the LMSGetDiagnostic function +** Call the doLMSGetDiagnostic function ** *******************************************************************************/ function doLMSGetDiagnostic(errorCode) @@ -390,11 +381,11 @@ function doLMSGetDiagnostic(errorCode) var api = getAPIHandle(); if (api == null) { - message("Unable to locate the LMS's API Implementation.\nLMSGetDiagnostic was not successful."); - return "Unable to locate the LMS's API Implementation. LMSGetDiagnostic was not successful."; + message("Unable to locate the LMS's API Implementation.\ndoLMSGetDiagnostic was not successful."); + return "Unable to locate the LMS's API Implementation. doLMSGetDiagnostic was not successful."; } - return api.LMSGetDiagnostic(errorCode).toString(); + return api.doLMSGetDiagnostic(errorCode).toString(); } /******************************************************************************* @@ -430,12 +421,12 @@ function ErrorHandler() } // check for errors caused by or from the LMS - error.code = api.LMSGetLastError().toString(); + error.code = api.doLMSGetLastError().toString(); if (error.code != _NoError.code) { // an error was encountered so display the error description - error.string = api.LMSGetErrorString(error.code); - error.diagnostic = api.LMSGetDiagnostic(""); + error.string = api.doLMSGetErrorString(error.code); + error.diagnostic = api.doLMSGetDiagnostic(""); } return error; @@ -475,7 +466,7 @@ function getAPIHandle() *******************************************************************************/ function findAPI(win) { - var findAPITries = 0; + var findAPITries = 0; while ((win.API == null) && (win.parent != null) && (win.parent != win)) { findAPITries++; @@ -537,4 +528,4 @@ function message(str) { output.log(str); } -} +} \ No newline at end of file diff --git a/SCORM2004/APIWrapper.js b/SCORM2004/APIWrapper.js index f9ed1d0..e0fc2ae 100644 --- a/SCORM2004/APIWrapper.js +++ b/SCORM2004/APIWrapper.js @@ -149,20 +149,17 @@ function doInitialize() } else { - // todo remove - message("Initialize succeeded"); - initialized = true; - // xAPI Extension + // xAPI Extension xapi.initializeAttempt(); + doSetValue("cmi.progress_measure", 0.0); } return result.toString(); } - /******************************************************************************* ** ** Function doTerminate() @@ -189,7 +186,8 @@ function doTerminate() { // xAPI Extension xapi.terminateAttempt(); - + doSetValue("cmi.progress_measure", 0.99); + xapi.measureProgress(); // call the Terminate function that should be implemented by the API var result = api.Terminate(""); if (result.toString() != "true") @@ -204,6 +202,9 @@ function doTerminate() return result.toString(); } + + + /******************************************************************************* ** ** Function doGetValue(name) @@ -232,7 +233,6 @@ function doGetValue(name) } else { - result = api.GetValue(name); var error = ErrorHandler(); diff --git a/SCORMToXAPIFunctions.js b/SCORMToXAPIFunctions.js index 9582ce3..834d67a 100644 --- a/SCORMToXAPIFunctions.js +++ b/SCORMToXAPIFunctions.js @@ -73,18 +73,8 @@ xapi = function () { ** *******************************************************************************/ var getBaseStatement = function () { - if (window.localStorage.learnerId == null) { - window.localStorage.learnerId = retrieveDataValue(scormVersionConfig.learnerIdElement); - } - return { - actor: { - objectType: "Agent", - account: { - homePage: config.lmsHomePage, - name: window.localStorage.learnerId - } - }, + actor: getAgent(), verb: {}, object: { id: config.activityId, @@ -129,18 +119,8 @@ xapi = function () { ** *******************************************************************************/ var getInteractionsBaseStatement = function () { - if (window.localStorage.learnerId == null) { - window.localStorage.learnerId = retrieveDataValue(scormVersionConfig.learnerIdElement); - } - return { - actor: { - objectType: "Agent", - account: { - homePage: config.lmsHomePage, - name: window.localStorage.learnerId - } - }, + actor: getAgent(), verb: ADL.verbs.responded, object: { objectType: "Activity", @@ -199,18 +179,8 @@ xapi = function () { ** *******************************************************************************/ var getVoidedBaseStatement = function () { - if (window.localStorage.learnerId == null) { - window.localStorage.learnerId = retrieveDataValue(scormVersionConfig.learnerIdElement); - } - return { - actor: { - objectType: "Agent", - account: { - homePage: config.lmsHomePage, - name: window.localStorage.learnerId - } - }, + actor: getAgent(), verb: {}, object: { objectType: "StatementRef", @@ -235,7 +205,8 @@ xapi = function () { account: { homePage: config.lmsHomePage, name: window.localStorage.learnerId - } + }, + objectType: "Agent" }; return agent; @@ -347,7 +318,7 @@ xapi = function () { // window.localStorage[activity] uses activity id to return the most recent // attempt stmt.context.contextActivities.grouping[0].id = window.localStorage[config.activityId]; - + // set the context activity from the manifest/launch_data to group together // for an event stmt.context.contextActivities.grouping.push(config.groupingContextActivity); @@ -373,7 +344,7 @@ xapi = function () { // window.localStorage[activity] uses activity id to return the most recent // attempt stmt.context.contextActivities.grouping[0].id = window.localStorage[config.activityId]; - + // set the context activity from the manifest/launch_data to group together // for an event stmt.context.contextActivities.grouping.push(config.groupingContextActivity); @@ -396,6 +367,7 @@ xapi = function () { var scoreRaw = retrieveDataValue(scormVersionConfig.scoreRawElement); var scoreMin = retrieveDataValue(scormVersionConfig.scoreMinElement); var scoreMax = retrieveDataValue(scormVersionConfig.scoreMaxElement); + var sessionTime = retrieveDataValue(scormVersionConfig.sessionTimeElement); var resultSet = false; var resultJson = {}; @@ -455,6 +427,12 @@ xapi = function () { scoreJson.max = parseFloat(scoreMax); } + // include sessionTime if set by sco + if (sessionTime != undefined && sessionTime != ""){ + resultSet = true; + resultJson.duration = sessionTime; + } + // set the score object in with the rest of the result object if (scoreSet) { resultJson.score = scoreJson; @@ -476,11 +454,6 @@ xapi = function () { ** *******************************************************************************/ var setAgentProfile = function () { - - if (window.localStorage.learnerId == null) { - window.localStorage.learnerId = retrieveDataValue(scormVersionConfig.learnerIdElement); - } - var lang = retrieveDataValue(scormVersionConfig.languageElement); var audioLevel = retrieveDataValue(scormVersionConfig.audioLevelElement); var deliverySpeed = retrieveDataValue(scormVersionConfig.deliverySpeedElement); @@ -493,12 +466,8 @@ xapi = function () { audio_captioning: audioCaptioning }; - ADL.XAPIWrapper.sendAgentProfile({ - account: { - homePage: config.lmsHomePage, - name: window.localStorage.learnerId - } - }, + ADL.XAPIWrapper.sendAgentProfile( + getAgent(), config.activityId, profile, null, @@ -518,12 +487,11 @@ xapi = function () { var ap = ADL.XAPIWrapper.getActivityProfile(config.activityId, constants.activityProfileIri); if (ap == null) { - // get comments from lms (if any) - //var cmi_num_comments_from_lms_count = retrieveDataValue("cmi.comments_from_lms._count"); - // todo: get the comments, if any and add to array - - // get completion threshold (if supplied in manifest) - var cmi_completion_threshold = retrieveDataValue(scormVersionConfig.completionThresholdElement); + // get completion threshold (if supplied in manifest, only valid in SCORM2004) + var cmi_completion_threshold = ""; + if (config.isScorm2004){ + cmi_completion_threshold = retrieveDataValue(scormVersionConfig.completionThresholdElement); + } var cmi_launch_data = retrieveDataValue(scormVersionConfig.launchDataElement); var cmi_max_time_allowed = retrieveDataValue(scormVersionConfig.maxTimeAllowedElement); var cmi_scaled_passing_score = retrieveDataValue(scormVersionConfig.scaledPassingScoreElement); @@ -603,7 +571,7 @@ xapi = function () { // location, preferences object, credit, lesson_mode, suspend_data, // total_time, adl_data var cmi_location = retrieveDataValue(scormVersionConfig.locationElement); - + var cmi_language = retrieveDataValue(scormVersionConfig.languageElement); var cmi_audio_level = retrieveDataValue(scormVersionConfig.audioLevelElement); var cmi_delivery_speed = retrieveDataValue(scormVersionConfig.deliverySpeedElement); @@ -842,6 +810,10 @@ xapi = function () { var setScore = function (value) { // For scorm 1.2, must divide raw by 100 var score = (config.isScorm2004) ? parseFloat(value) : parseFloat(value) / 100; + // Can't send statement if score is not a proper float + if (isNaN(score)){ + return; + } var stmt = getBaseStatement(); stmt.verb = ADL.verbs.scored; @@ -851,7 +823,6 @@ xapi = function () { // for an event stmt.context.contextActivities.grouping.push(config.groupingContextActivity); - // todo: add error handling if value is not a valid scaled score stmt.result = { score: { scaled: score @@ -872,6 +843,34 @@ xapi = function () { } } + + /******************************************************************************* + ** + ** This function is used to measure progress in an activity + ** + *******************************************************************************/ + var measureProgress = function () { + if (config.isScorm2004) { + var stmt = getBaseStatement(); + stmt.verb = ADL.verbs.progressed; + stmt.context.contextActivities.grouping[0].id = window.localStorage[config.activityId]; + var progressMeasure = parseFloat(retrieveDataValue(scormVersionConfig.progressMeasureElement)); + if (!isNaN(progressMeasure)){ + stmt.result = { + score: { + scaled: progressMeasure + } + }; + } + + // set the context activity from the manifest/launch_data to group together + // for an event + stmt.context.contextActivities.grouping.push(config.groupingContextActivity); + var response = ADL.XAPIWrapper.sendStatement(stmt); + } + } + + /******************************************************************************* ** ** This function is used to set pass/failed on an activity @@ -973,7 +972,14 @@ xapi = function () { creditElement: (config.isScorm2004) ? "cmi.credit" : "cmi.core.credit", modeElement: (config.isScorm2004) ? "cmi.mode" : "cmi.core.lesson_mode", suspendDataElement: "cmi.suspend_data", - totalTimeElement: (config.isScorm2004) ? "cmi.total_time" : "cmi.core.total_time" + totalTimeElement: (config.isScorm2004) ? "cmi.total_time" : "cmi.core.total_time", + //new stuff here + sessionTimeElement: (config.isScorm2004) ? "cmi.session_time" : "cmi.core.session_time", + progressMeasureElement: (config.isScorm2004) ? "cmi.progress_measure" : "", + interactionsElement: "cmi.interactions", + objectivesElement: "cmi.objectives", + learnerCommentsElement: (config.isScorm2004) ? "cmi.comments_from_learner" : "cmi.comments", + LMSCommentsElement: "cmi.comments_from_lms", } } @@ -1070,7 +1076,8 @@ xapi = function () { setScore: setScore, setComplete: setComplete, setSuccess: setSuccess, - configureLRS: configureLRS + configureLRS: configureLRS, + measureProgress:measureProgress } //