UNPKG

@didask/scol-r

Version:

Shareable Cross-Origin Learning Resources

425 lines (424 loc) 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertMsToCMITimespan = exports.convertToTimeInterval = exports.SCORMAdapter = void 0; var SCORMAdapter = /** @class */ (function () { function SCORMAdapter(errorCallback) { if (errorCallback === void 0) { errorCallback = function () { }; } var _this = this; this._ignorableErrorCodes = [ { code: 0, getShouldBeIgnored: function () { return true; } }, { code: 403, getShouldBeIgnored: function () { return _this._isSCORM2004; }, }, { code: 401, getShouldBeIgnored: function () { return !_this._isSCORM2004 && !!_this._lastRequest && _this._lastRequest.method === "get" && _this._lastRequest.key === "cmi.objectives._children"; }, }, { code: 402, getShouldBeIgnored: function () { return _this._isSCORM2004 && !!_this._lastRequest && _this._lastRequest.method === "get" && _this._lastRequest.key === "cmi.objectives._children"; }, }, { code: 351, getShouldBeIgnored: function () { var _a; return ((_a = _this._lastRequest) === null || _a === void 0 ? void 0 : _a.method) === "set" && new RegExp("^cmi.objectives.\\d+.id$").test(_this._lastRequest.key) && !!_this.LMSGetValue(_this._lastRequest.key); }, }, { code: 113, getShouldBeIgnored: function () { var _a; return ((_a = _this._lastRequest) === null || _a === void 0 ? void 0 : _a.key) === "Terminate"; }, }, ]; this._API = null; this._isSCORM2004 = false; this._errorCallback = errorCallback; this._lastRequest = null; this._findAndSetAPI(); } Object.defineProperty(SCORMAdapter.prototype, "foundAPI", { get: function () { return !!this._API; }, enumerable: false, configurable: true }); SCORMAdapter.prototype._initialize = function () { if (this._isSCORM2004) { this.LMSSetValue("cmi.score.min", 0); this.LMSSetValue("cmi.score.max", 100); } else { this.LMSSetValue("cmi.core.score.min", 0); this.LMSSetValue("cmi.core.score.max", 100); } }; SCORMAdapter.prototype._findAndSetAPI = function () { if (typeof window === "undefined") { console.error("Unable to find an API adapter"); } else { var theAPI = this._findAPIInWindow(window); if (theAPI == null && window.opener != null && typeof window.opener != "undefined") { theAPI = this._findAPIInWindow(window.opener); } if (theAPI == null) { console.error("Unable to find an API adapter"); } else { this._API = theAPI["API"]; this._isSCORM2004 = theAPI["isSCORM2004"]; } if (this._API == null) { console.error("Couldn't find the API!"); } } }; SCORMAdapter.prototype._findAPIInWindow = function (win) { var findAPITries = 0; while (win.API == null && win.API_1484_11 == null && win.parent != null && win.parent != win) { findAPITries++; if (findAPITries > 7) { console.error("Error finding API -- too deeply nested."); return null; } win = win.parent; } if (win.API) { return { API: win.API, isSCORM2004: false, }; } else if (win.API_1484_11) { return { API: win.API_1484_11, isSCORM2004: true, }; } return null; }; SCORMAdapter.prototype._callAPIFunction = function (fun, args) { if (args === void 0) { args = [""]; } if (this._API == null) { this._warnNOAPI(); return; } if (this._isSCORM2004 && fun.indexOf("LMS") == 0) { fun = fun.substr(3); } else if (!this._isSCORM2004 && !(fun.indexOf("LMS") == 0)) { fun = "LMS" + fun; } var result = this._API[fun].apply(this._API, args); console.info("[SCOL-R] ".concat(fun, "(").concat(args.join(", "), ") = ").concat(JSON.stringify(result))); return result; }; SCORMAdapter.prototype._handleError = function (functionName) { var lastErrorCode = this.LMSGetLastError(); var lastErrorString = this.LMSGetErrorString(lastErrorCode); var lastErrorDiagnostic = this.LMSGetDiagnostic(lastErrorCode); if (!this._ignorableErrorCodes.some(function (_a) { var code = _a.code, getShouldBeIgnored = _a.getShouldBeIgnored; return code === lastErrorCode && getShouldBeIgnored(); })) { console.warn(functionName, "An error occured on the SCORM API: code ".concat(lastErrorCode, ", message: ").concat(lastErrorString), lastErrorDiagnostic); this._errorCallback(lastErrorString, lastErrorDiagnostic && lastErrorDiagnostic != lastErrorCode ? lastErrorDiagnostic : null); } }; SCORMAdapter.prototype._warnNOAPI = function () { console.warn("Cannot execute this function because the SCORM API is not available."); this._errorCallback("apiNotFound"); }; SCORMAdapter.prototype.validateResult = function (result) { if (typeof result === "string") { return result === "true"; } else if (typeof result === "boolean") { return result; } return false; }; SCORMAdapter.prototype.LMSInitialize = function () { var functionName = "Initialize"; var result = this._callAPIFunction(functionName); var lastErrorCode = this.LMSGetLastError(); var success = this.validateResult(result) || (this._isSCORM2004 ? lastErrorCode === 103 // 103 in 2004.* = already initialized : lastErrorCode === 101); // 101 in 1.2 = already initialized if (success) { this._initialize(); } return success || this._handleError(functionName); }; SCORMAdapter.prototype.LMSTerminate = function () { this._lastRequest = { key: "Terminate" }; var functionName = this._isSCORM2004 ? "Terminate" : "Finish"; var result = this._callAPIFunction(functionName); var success = this.validateResult(result); return success || this._handleError(functionName); }; SCORMAdapter.prototype.LMSGetValue = function (name) { this._lastRequest = { method: "get", key: name }; var functionName = "GetValue"; var value = this._callAPIFunction(functionName, [name]); var success = this.LMSGetLastError() === 0; return success ? value : this._handleError("".concat(functionName, ": ").concat(name)); }; SCORMAdapter.prototype.LMSSetValue = function (name, value) { this._lastRequest = { method: "set", key: name }; var functionName = "SetValue"; var result = this._callAPIFunction(functionName, [name, value]); var success = this.validateResult(result); return success || this._handleError("".concat(functionName, ": {").concat(name, ": ").concat(value, "}")); }; SCORMAdapter.prototype.LMSCommit = function () { var _this = this; var result = this._callAPIFunction("Commit"); if (this.validateResult(result)) { return true; } else if (typeof result === "object" && "then" in result && typeof result.then === "function") { result.then(function (success) { if (!_this.validateResult(success)) { _this._errorCallback("commitFailed"); } }); return true; } this._errorCallback("commitFailed"); }; SCORMAdapter.prototype.LMSGetLastError = function () { return parseInt(this._callAPIFunction("GetLastError")); }; SCORMAdapter.prototype.LMSGetErrorString = function (errorCode) { return this._callAPIFunction("GetErrorString", [errorCode]); }; SCORMAdapter.prototype.LMSGetDiagnostic = function (errorCode) { return this._callAPIFunction("GetDiagnostic", [errorCode]); }; Object.defineProperty(SCORMAdapter.prototype, "lastRequest", { get: function () { return this._lastRequest; }, enumerable: false, configurable: true }); SCORMAdapter.prototype.getDataFromLMS = function () { return this.LMSGetValue("cmi.launch_data"); }; SCORMAdapter.prototype.getLearnerId = function () { var CMIVariableName = this._isSCORM2004 ? "cmi.learner_id" : "cmi.core.student_id"; return this.LMSGetValue(CMIVariableName); }; SCORMAdapter.prototype.getLearnerName = function () { var CMIVariableName = this._isSCORM2004 ? "cmi.learner_name" : "cmi.core.student_name"; return this.LMSGetValue(CMIVariableName); }; SCORMAdapter.prototype.setStudent = function (studentId, studentName) { if (this._isSCORM2004) { this.LMSSetValue("cmi.learner_id", studentId); this.LMSSetValue("cmi.learner_name", studentName); } else { this.LMSSetValue("cmi.core.student_id", studentId); this.LMSSetValue("cmi.core.student_name", studentName); } }; SCORMAdapter.prototype.setScore = function (score) { if (this._isSCORM2004) { this.LMSSetValue("cmi.score.raw", score); this.LMSSetValue("cmi.score.scaled", score / 100); } else { this.LMSSetValue("cmi.core.score.raw", score); } }; SCORMAdapter.prototype.getScore = function () { var CMIVariableName = this._isSCORM2004 ? "cmi.score.raw" : "cmi.core.score.raw"; var score = this.LMSGetValue(CMIVariableName); return score; }; SCORMAdapter.prototype.getLessonStatus = function () { var CMIVariableName = this._isSCORM2004 ? "cmi.completion_status" : "cmi.core.lesson_status"; return this.LMSGetValue(CMIVariableName); }; SCORMAdapter.prototype.setLessonStatus = function (lessonStatus) { if (this._isSCORM2004) { var successStatus = "unknown"; if (lessonStatus === "passed" || lessonStatus === "failed") successStatus = lessonStatus; this.LMSSetValue("cmi.success_status", successStatus); var completionStatus = "unknown"; if (lessonStatus === "passed" || lessonStatus === "completed") { completionStatus = "completed"; } else if (lessonStatus === "incomplete") { completionStatus = "incomplete"; } else if (lessonStatus === "not attempted" || lessonStatus === "browsed") { completionStatus = "not attempted"; } this.LMSSetValue("cmi.completion_status", completionStatus); } else { this.LMSSetValue("cmi.core.lesson_status", lessonStatus); } }; SCORMAdapter.prototype.setSessionTime = function (msSessionTime) { if (this._isSCORM2004) { var duration = (0, exports.convertToTimeInterval)(msSessionTime); this.LMSSetValue("cmi.session_time", duration); } else { var duration = (0, exports.convertMsToCMITimespan)(msSessionTime); this.LMSSetValue("cmi.core.session_time", duration); } }; Object.defineProperty(SCORMAdapter.prototype, "objectivesAreAvailable", { get: function () { var objectivesFields = !!this.LMSGetValue("cmi.objectives._children"); return objectivesFields && this.LMSGetLastError() === 0; }, enumerable: false, configurable: true }); SCORMAdapter.prototype.setObjectives = function (objectivesIds) { var _this = this; objectivesIds.forEach(function (objectiveId, index) { _this.LMSSetValue("cmi.objectives.".concat(index, ".id"), objectiveId); }); }; Object.defineProperty(SCORMAdapter.prototype, "objectives", { get: function () { var objectives = []; var objectivesNbr = this.LMSGetValue("cmi.objectives._count"); for (var index = 0; index < objectivesNbr; index++) { objectives.push(this.LMSGetValue("cmi.objectives.".concat(index, ".id"))); } return objectives; }, enumerable: false, configurable: true }); SCORMAdapter.prototype.setObjectiveScore = function (objectiveId, score) { var objectivesNbr = this.LMSGetValue("cmi.objectives._count"); for (var index = 0; index < objectivesNbr; index++) { var storedObjectiveId = this.LMSGetValue("cmi.objectives.".concat(index, ".id")); if (objectiveId === storedObjectiveId) { this.LMSSetValue("cmi.objectives.".concat(index, ".score.raw"), score); return; } } }; SCORMAdapter.prototype.setObjectiveStatus = function (objectiveId, status) { var objectivesNbr = this.LMSGetValue("cmi.objectives._count"); for (var index = 0; index < objectivesNbr; index++) { var storedObjectiveId = this.LMSGetValue("cmi.objectives.".concat(index, ".id")); if (objectiveId === storedObjectiveId) { if (this._isSCORM2004) { this.LMSSetValue("cmi.objectives.".concat(index, ".success_status"), status === "completed" ? "passed" : "unknown"); this.LMSSetValue("cmi.objectives.".concat(index, ".completion_status"), status === "completed" ? "completed" : "incomplete"); } else { this.LMSSetValue("cmi.objectives.".concat(index, ".status"), status === "completed" ? "passed" : "incomplete"); } return; } } }; SCORMAdapter.prototype.getObjectiveScore = function (objectiveId) { var objectivesNbr = this.LMSGetValue("cmi.objectives._count"); for (var index = 0; index < objectivesNbr; index++) { var storedObjectiveId = this.LMSGetValue("cmi.objectives.".concat(index, ".id")); if (objectiveId === storedObjectiveId) { return this.LMSGetValue("cmi.objectives.".concat(index, ".score.raw")); } } }; SCORMAdapter.prototype.setSuspendData = function (data) { this.LMSSetValue("cmi.suspend_data", data); }; Object.defineProperty(SCORMAdapter.prototype, "suspendData", { get: function () { return this.LMSGetValue("cmi.suspend_data"); }, enumerable: false, configurable: true }); return SCORMAdapter; }()); exports.SCORMAdapter = SCORMAdapter; var convertToTimeInterval = function (milliseconds) { // timeinterval (second,10,2), var data = getDurationData(milliseconds); var days = data.days; var hours = data.hours % 24; var minutes = data.minutes % 60; var seconds = data.seconds % 60; var cents = data.cents % 100; var daysString = days ? days + "D" : ""; var hoursString = hours ? hours + "H" : ""; var minutesString = minutes ? minutes + "M" : ""; var secondsString = (seconds || "0" + (cents ? "." + cents : "")) + "S"; var hms = [hoursString, minutesString, secondsString].join(""); return "P" + daysString + "T" + hms; }; exports.convertToTimeInterval = convertToTimeInterval; var convertMsToCMITimespan = function (milliseconds) { // CMITimespan "0000:00:00.00" var _a = getDurationData(milliseconds), seconds = _a.seconds, minutes = _a.minutes, hours = _a.hours, cents = _a.cents; var h = pad(hours, 4); var m = pad(minutes % 60, 2); var s = pad(seconds % 60, 2); var c = pad(cents % 100, 2); return "".concat(h, ":").concat(m, ":").concat(s, ".").concat(c); }; exports.convertMsToCMITimespan = convertMsToCMITimespan; var getDurationData = function (milliseconds) { var cents = Math.floor(milliseconds / 10); var seconds = Math.floor(milliseconds / 1000); var minutes = Math.floor(seconds / 60); var hours = Math.floor(minutes / 60); var days = Math.floor(hours / 24); return { days: days, hours: hours, minutes: minutes, seconds: seconds, cents: cents }; }; var pad = function (value, targetLength) { var text = value.toString(); var padLength = targetLength - text.length; if (padLength <= 0) return text; return "0".repeat(padLength) + text; };