@didask/scol-r
Version:
Shareable Cross-Origin Learning Resources
425 lines (424 loc) • 17.5 kB
JavaScript
;
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;
};