@didask/scol-r 2.9.0-beta.2 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/HTMLGenerator.d.ts +0 -1
- package/lib/HTMLGenerator.js +2 -2
- package/lib/MessageHandler.d.ts +1 -12
- package/lib/MessageHandler.js +39 -44
- package/lib/SCORMAdapter.d.ts +3 -3
- package/lib/SCORMAdapter.js +5 -12
- package/lib/SCORMAdapter.test.d.ts +1 -0
- package/lib/SCORMAdapter.test.js +14 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +0 -1
- package/lib/loadContent.d.ts +1 -3
- package/lib/loadContent.js +134 -189
- package/package.json +1 -1
- package/lib/hashString.d.ts +0 -1
- package/lib/hashString.js +0 -57
package/lib/HTMLGenerator.d.ts
CHANGED
package/lib/HTMLGenerator.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HTMLGenerator = void 0;
|
|
4
4
|
function HTMLGenerator(props) {
|
|
5
|
-
var dataSource = props.dataSource, _a = props.libPath, libPath = _a === void 0 ? "lib" : _a
|
|
6
|
-
return "<!DOCTYPE html>\n <html>\n <head>\n <title>SCO local endpoint</title>\n <meta charset=\"UTF-8\"/>\n <script>var exports = {};</script>\n <script type=\"text/javascript\" src=\"".concat(libPath, "/
|
|
5
|
+
var dataSource = props.dataSource, _a = props.libPath, libPath = _a === void 0 ? "lib" : _a;
|
|
6
|
+
return "<!DOCTYPE html>\n <html>\n <head>\n <title>SCO local endpoint</title>\n <meta charset=\"UTF-8\"/>\n <script>var exports = {};</script>\n <script type=\"text/javascript\" src=\"".concat(libPath, "/SCORMAdapter.js\"></script>\n <script type=\"text/javascript\" src=\"").concat(libPath, "/MessageHandler.js\"></script>\n <script type=\"text/javascript\" src=\"").concat(libPath, "/loadContent.js\"></script>\n <style type=\"text/css\">\n html, body { margin: 0; padding:0; overflow:hidden; width: 100%; height: 100%; }\n body {\n font-size: 20px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n color: #1d1046;\n }\n #wrapper { display: flex; flex-direction: column; height: 100%; }\n .container { width: 80%; max-width: 1200px; padding: 15px; margin: auto; }\n #wrapper .header {\n padding-top: 20px; padding-bottom: 20px;\n background-color: #f3f4f5;\n }\n #wrapper .messages { flex-grow: 1; padding-top: 20px; padding-bottom: 20px; }\n #wrapper .messages p { color: red; }\n #title-error-messages { color: #1d1046; }\n #wrapper .footer {\n background-color: #1d1046; color: white;\n padding-top: 10px; padding-bottom: 10px;\n }\n #wrapper .footer a { color: white; }\n\n iframe { overflow: hidden; height: 100%; width: 100%; }\n iframe + #wrapper { display: none; }\n #runtime-error {\n position: fixed;\n left: 20px; bottom: 20px; padding: 15px;\n background-color: #f44a3d; color: white;\n font-size: 16px;\n }\n #runtime-error h6, #runtime-error p { margin: 0 0 10px;}\n #runtime-error p:last-child { margin: 0;}\n #runtime-error:empty { display: none; }\n </style>\n </head>\n <!-- Set the body's data-source attribute to the SCO's remote endpoint. -->\n <body onload=\"loadContent();\" data-source=\"").concat(dataSource, "\">\n <div id=\"wrapper\">\n <div class=\"header\"><div class=\"container\">\n <h1 id=\"title\">Your content is loading...</h1>\n <p id=\"subtitle\">Please wait, or if your content doesn't appear, try closing and opening this window again.</p>\n </div></div>\n <div class=\"messages container\">\n <h2 id=\"title-error-messages\">If the initialization fails, error messages will appear below:</h2>\n </div>\n <div class=\"footer\"><div class=\"container\" id=\"footer-content\">\n This content is loaded via <a href=\"https://github.com/Didask/scol-r\" target=\"_blank\">SCOL-R</a>, a cross-domain SCORM connector created by <a href=\"https://www.didask.com\" target=\"_blank\">Didask</a>.\n </div></div>\n </div>\n <div id=\"runtime-error\"></div>\n </body>\n </html>");
|
|
7
7
|
}
|
|
8
8
|
exports.HTMLGenerator = HTMLGenerator;
|
package/lib/MessageHandler.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
private readonly adapter;
|
|
3
|
-
constructor(win: Window, sourceOrigin: string, adapter: any);
|
|
4
|
-
commit(): void;
|
|
5
|
-
setTitle(title: string): void;
|
|
6
|
-
setScore(score: string): void;
|
|
7
|
-
setStudent(studentId: string, studentName: string): void;
|
|
8
|
-
setLessonStatus(lessonStatus: string): void;
|
|
9
|
-
setObjectives(objectivesIds: string[]): void;
|
|
10
|
-
setObjectiveScore(objectiveId: string, score: number): void;
|
|
11
|
-
setObjectiveStatus(objectiveId: string, status: string): void;
|
|
12
|
-
}
|
|
1
|
+
export declare function MessageReceiver(win: Window, sourceOrigin: string, adapter: any): void;
|
|
13
2
|
export declare class MessageEmitter {
|
|
14
3
|
private currentWindow;
|
|
15
4
|
private lmsOrigin;
|
package/lib/MessageHandler.js
CHANGED
|
@@ -1,63 +1,58 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageEmitter = exports.MessageReceiver = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
this[functionName].apply(this, functionArgs);
|
|
19
|
-
if (timeoutId) {
|
|
20
|
-
clearTimeout(timeoutId);
|
|
21
|
-
}
|
|
22
|
-
timeoutId = setTimeout(function () {
|
|
23
|
-
_this.commit();
|
|
24
|
-
timeoutId = null;
|
|
25
|
-
}, 500);
|
|
4
|
+
function MessageReceiver(win, sourceOrigin, adapter) {
|
|
5
|
+
this.timeoutId = null;
|
|
6
|
+
win.addEventListener("message", function (e) {
|
|
7
|
+
var _this = this;
|
|
8
|
+
if (e.origin !== sourceOrigin)
|
|
9
|
+
return;
|
|
10
|
+
var functionName = e.data["function"];
|
|
11
|
+
var functionArgs = e.data["arguments"];
|
|
12
|
+
if (functionName &&
|
|
13
|
+
functionArgs &&
|
|
14
|
+
typeof this[functionName] === "function") {
|
|
15
|
+
this[functionName].apply(this, functionArgs);
|
|
16
|
+
if (this.timeoutId) {
|
|
17
|
+
clearTimeout(this.timeoutId);
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
this.timeoutId = setTimeout(function () {
|
|
20
|
+
_this.commit();
|
|
21
|
+
_this.timeoutId = null;
|
|
22
|
+
}, 500);
|
|
23
|
+
}
|
|
24
|
+
}.bind(this));
|
|
25
|
+
this.commit = function () {
|
|
26
|
+
adapter.LMSCommit();
|
|
31
27
|
};
|
|
32
|
-
|
|
28
|
+
this.setTitle = function (title) {
|
|
33
29
|
document.title = title;
|
|
34
30
|
};
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
this.setScore = function (score) {
|
|
32
|
+
adapter.setScore(score);
|
|
37
33
|
};
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
this.setStudent = function (studentId, studentName) {
|
|
35
|
+
adapter.setStudent(studentId, studentName);
|
|
40
36
|
};
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
this.setLessonStatus = function (lessonStatus) {
|
|
38
|
+
adapter.setLessonStatus(lessonStatus);
|
|
43
39
|
};
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
40
|
+
this.setObjectives = function (objectivesIds) {
|
|
41
|
+
if (adapter.objectivesAreAvailable) {
|
|
42
|
+
adapter.setObjectives(objectivesIds);
|
|
47
43
|
}
|
|
48
44
|
};
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
45
|
+
this.setObjectiveScore = function (objectiveId, score) {
|
|
46
|
+
if (adapter.objectivesAreAvailable) {
|
|
47
|
+
adapter.setObjectiveScore(objectiveId, score);
|
|
52
48
|
}
|
|
53
49
|
};
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
50
|
+
this.setObjectiveStatus = function (objectiveId, status) {
|
|
51
|
+
if (adapter.objectivesAreAvailable) {
|
|
52
|
+
adapter.setObjectiveStatus(objectiveId, status);
|
|
57
53
|
}
|
|
58
54
|
};
|
|
59
|
-
|
|
60
|
-
}());
|
|
55
|
+
}
|
|
61
56
|
exports.MessageReceiver = MessageReceiver;
|
|
62
57
|
var MessageEmitter = /** @class */ (function () {
|
|
63
58
|
function MessageEmitter(lmsOrigin) {
|
package/lib/SCORMAdapter.d.ts
CHANGED
|
@@ -17,14 +17,14 @@ export declare class SCORMAdapter {
|
|
|
17
17
|
LMSTerminate(): true | void;
|
|
18
18
|
LMSGetValue(name: string): any;
|
|
19
19
|
LMSSetValue(name: string, value: string | number): true | void;
|
|
20
|
-
LMSCommit():
|
|
20
|
+
LMSCommit(): boolean;
|
|
21
21
|
LMSGetLastError(): number;
|
|
22
22
|
LMSGetErrorString(errorCode: number): any;
|
|
23
23
|
LMSGetDiagnostic(errorCode: number): any;
|
|
24
24
|
get lastRequest(): {
|
|
25
|
-
method
|
|
25
|
+
method: "get" | "set";
|
|
26
26
|
key: string;
|
|
27
|
-
}
|
|
27
|
+
};
|
|
28
28
|
getDataFromLMS(): any;
|
|
29
29
|
getLearnerId(): any;
|
|
30
30
|
getLearnerName(): any;
|
package/lib/SCORMAdapter.js
CHANGED
|
@@ -15,7 +15,7 @@ var SCORMAdapter = /** @class */ (function () {
|
|
|
15
15
|
code: 401,
|
|
16
16
|
getShouldBeIgnored: function () {
|
|
17
17
|
return !_this._isSCORM2004 &&
|
|
18
|
-
|
|
18
|
+
_this._lastRequest &&
|
|
19
19
|
_this._lastRequest.method === "get" &&
|
|
20
20
|
_this._lastRequest.key === "cmi.objectives._children";
|
|
21
21
|
},
|
|
@@ -24,7 +24,7 @@ var SCORMAdapter = /** @class */ (function () {
|
|
|
24
24
|
code: 402,
|
|
25
25
|
getShouldBeIgnored: function () {
|
|
26
26
|
return _this._isSCORM2004 &&
|
|
27
|
-
|
|
27
|
+
_this._lastRequest &&
|
|
28
28
|
_this._lastRequest.method === "get" &&
|
|
29
29
|
_this._lastRequest.key === "cmi.objectives._children";
|
|
30
30
|
},
|
|
@@ -32,16 +32,11 @@ var SCORMAdapter = /** @class */ (function () {
|
|
|
32
32
|
{
|
|
33
33
|
code: 351,
|
|
34
34
|
getShouldBeIgnored: function () {
|
|
35
|
-
|
|
36
|
-
return ((_a = _this._lastRequest) === null || _a === void 0 ? void 0 : _a.method) === "set" &&
|
|
35
|
+
return _this._lastRequest.method === "set" &&
|
|
37
36
|
new RegExp("^cmi.objectives.\\d+.id$").test(_this._lastRequest.key) &&
|
|
38
37
|
!!_this.LMSGetValue(_this._lastRequest.key);
|
|
39
38
|
},
|
|
40
39
|
},
|
|
41
|
-
{
|
|
42
|
-
code: 113,
|
|
43
|
-
getShouldBeIgnored: function () { var _a; return ((_a = _this._lastRequest) === null || _a === void 0 ? void 0 : _a.key) === "Terminate"; },
|
|
44
|
-
},
|
|
45
40
|
];
|
|
46
41
|
this._API = null;
|
|
47
42
|
this._isSCORM2004 = false;
|
|
@@ -128,9 +123,8 @@ var SCORMAdapter = /** @class */ (function () {
|
|
|
128
123
|
else if (!this._isSCORM2004 && !(fun.indexOf("LMS") == 0)) {
|
|
129
124
|
fun = "LMS" + fun;
|
|
130
125
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return result;
|
|
126
|
+
console.info("[SCOL-R] Calling a scorm api function", { fun: fun, args: args });
|
|
127
|
+
return this._API[fun].apply(this._API, args);
|
|
134
128
|
};
|
|
135
129
|
SCORMAdapter.prototype._handleError = function (functionName) {
|
|
136
130
|
var lastErrorCode = this.LMSGetLastError();
|
|
@@ -173,7 +167,6 @@ var SCORMAdapter = /** @class */ (function () {
|
|
|
173
167
|
return success || this._handleError(functionName);
|
|
174
168
|
};
|
|
175
169
|
SCORMAdapter.prototype.LMSTerminate = function () {
|
|
176
|
-
this._lastRequest = { key: "Terminate" };
|
|
177
170
|
var functionName = this._isSCORM2004 ? "Terminate" : "Finish";
|
|
178
171
|
var result = this._callAPIFunction(functionName);
|
|
179
172
|
var success = this.validateResult(result);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var bun_test_1 = require("bun:test");
|
|
4
|
+
var SCORMAdapter_1 = require("./SCORMAdapter");
|
|
5
|
+
bun_test_1.test('convertMsToCMITimespan ("0000:00:00.00")', function () {
|
|
6
|
+
var milliseconds = (36 * 60 * 60 * 1000) + (6 * 60 * 1000) + (2 * 1000) + (23 * 10);
|
|
7
|
+
var CMITimespan = SCORMAdapter_1.convertMsToCMITimespan(milliseconds);
|
|
8
|
+
bun_test_1.expect(CMITimespan).toBe('0036:06:02.23');
|
|
9
|
+
});
|
|
10
|
+
bun_test_1.test('convertToTimeInterval', function () {
|
|
11
|
+
var milliseconds = (36 * 60 * 60 * 1000) + (6 * 60 * 1000) + (2 * 1000) + (23 * 10);
|
|
12
|
+
var timeInterval = SCORMAdapter_1.convertToTimeInterval(milliseconds);
|
|
13
|
+
bun_test_1.expect(timeInterval).toBe('P1DT12H6M2');
|
|
14
|
+
});
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./ManifestGenerator";
|
|
|
2
2
|
export * from "./SCORMAdapter";
|
|
3
3
|
export * from "./HTMLGenerator";
|
|
4
4
|
export { MessageEmitter } from "./MessageHandler";
|
|
5
|
-
export declare const libFiles: readonly ["loadContent.js", "MessageHandler.js", "SCORMAdapter.js"
|
|
5
|
+
export declare const libFiles: readonly ["loadContent.js", "MessageHandler.js", "SCORMAdapter.js"];
|
|
6
6
|
export declare const scormVersions: readonly ["1.2", "2004 3rd Edition", "2004 4th Edition"];
|
|
7
7
|
export declare enum LessonStatus {
|
|
8
8
|
Passed = "passed",
|
package/lib/index.js
CHANGED
package/lib/loadContent.d.ts
CHANGED
package/lib/loadContent.js
CHANGED
|
@@ -1,195 +1,140 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.loadContent = void 0;
|
|
40
|
-
function loadContent(
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
sourceOrigin = sourceUrlParser.protocol + "//" + host;
|
|
175
|
-
new MessageReceiver(window, sourceOrigin, ADAPTER);
|
|
176
|
-
sessionStart = new Date().getTime();
|
|
177
|
-
/*
|
|
178
|
-
* In case the beforeunload event is not triggered, we still want to send the session time to the LMS.
|
|
179
|
-
* This is why we send the session time every 10 seconds.
|
|
180
|
-
*/
|
|
181
|
-
setInterval(function () {
|
|
182
|
-
var now = new Date().getTime();
|
|
183
|
-
ADAPTER.setSessionTime(now - sessionStart);
|
|
184
|
-
}, 10000);
|
|
185
|
-
window.addEventListener("beforeunload", function (e) {
|
|
186
|
-
var sessionEnd = new Date().getTime();
|
|
187
|
-
ADAPTER.setSessionTime(sessionEnd - sessionStart);
|
|
188
|
-
ADAPTER.LMSTerminate();
|
|
189
|
-
});
|
|
190
|
-
return [2 /*return*/];
|
|
191
|
-
}
|
|
192
|
-
});
|
|
4
|
+
function loadContent() {
|
|
5
|
+
var messages = {
|
|
6
|
+
en: {
|
|
7
|
+
pageTitle: "Your content is loading...",
|
|
8
|
+
pageSubtitle: "Please wait, or if your content doesn't appear, try closing and opening this window again.",
|
|
9
|
+
pageErrorMessagesTitle: "If the initialization fails, error messages will appear below:",
|
|
10
|
+
pageFooter: 'This content is loaded via <a href="https://github.com/Didask/scol-r" target="_blank">SCOL-R</a>, a cross-domain SCORM connector created by <a href="https://www.didask.com" target="_blank">Didask</a>.',
|
|
11
|
+
apiNotFound: "<p>We were not able to contact your LMS: please close this window and try again later.</p>",
|
|
12
|
+
couldNotInitialize: "<p>We were not able to initialize the connection with your LMS: please close this window and try again later.</p>",
|
|
13
|
+
learnerIdMissing: "<p>We could not get your learner ID from the LMS: please close this window and try again later.</p>",
|
|
14
|
+
sourceUrlMissing: "<p>We could find the address of the remote resource: it looks like this module is invalid, please contact your LMS administrator.</p>",
|
|
15
|
+
runtimeErrorTitle: "An error occurred:",
|
|
16
|
+
commitFailed: "The intermediate recording could not succeed. Please close the window and try again later, or contact your administrator if the problem keeps occurring.",
|
|
17
|
+
},
|
|
18
|
+
fr: {
|
|
19
|
+
pageTitle: "Votre contenu est en cours de chargement...",
|
|
20
|
+
pageSubtitle: "Merci de patienter ; si votre contenu ne se charge pas, veuillez essayer de fermer et d'ouvrir cette fenêtre à nouveau.",
|
|
21
|
+
pageErrorMessagesTitle: "Si l'initialisation échoue, les messages d'erreur apparaîtront ci-dessous :",
|
|
22
|
+
pageFooter: 'Ce contenu est chargé via <a href="https://github.com/Didask/scol-r" target="_blank">SCOL-R</a>, un connecteur SCORM cross-domaine créé par <a href="https://www.didask.com" target="_blank">Didask</a>.',
|
|
23
|
+
apiNotFound: "<p>Nous n'avons pas pu contacter votre LMS : veuillez fermer cette fenêtre et réessayer plus tard.</p>",
|
|
24
|
+
couldNotInitialize: "<p>Nous n'avons pas pu initialiser la connection avec votre LMS : veuillez fermer cette fenêtre et réessayer plus tard.</p>",
|
|
25
|
+
learnerIdMissing: "<p>Nous n'avons pas pu obtenir votre identifiant depuis le LMS : veuillez fermer cette fenêtre et réessayer plus tard.</p>",
|
|
26
|
+
sourceUrlMissing: "<p>Nous n'avons pas pu trouver l'adresse de la ressource distante : il semble que ce module est invalide, veuillez contacter l'administrateur de votre LMS.</p>",
|
|
27
|
+
runtimeErrorTitle: "Une erreur s'est produite :",
|
|
28
|
+
commitFailed: "La sauvegarde automatique intermédiaire n’a pu aboutir. Si cette erreur se produit fréquemment veuillez fermer votre contenu et retenter plus tard ou contacter votre administrateur.",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
var localizeMessage = function (message) {
|
|
32
|
+
var locale = navigator.language || navigator.userLanguage;
|
|
33
|
+
if (locale)
|
|
34
|
+
locale = locale.split(/[_-]/)[0];
|
|
35
|
+
if (!messages.hasOwnProperty(locale))
|
|
36
|
+
locale = "en";
|
|
37
|
+
var localizedMessages = messages[locale];
|
|
38
|
+
return localizedMessages.hasOwnProperty(message)
|
|
39
|
+
? localizedMessages[message]
|
|
40
|
+
: message;
|
|
41
|
+
};
|
|
42
|
+
document.getElementById("title").innerHTML = localizeMessage("pageTitle");
|
|
43
|
+
document.getElementById("subtitle").innerHTML =
|
|
44
|
+
localizeMessage("pageSubtitle");
|
|
45
|
+
document.getElementById("footer-content").innerHTML =
|
|
46
|
+
localizeMessage("pageFooter");
|
|
47
|
+
document.getElementById("title-error-messages").innerHTML = localizeMessage("pageErrorMessagesTitle");
|
|
48
|
+
var displayInitError = function (message) {
|
|
49
|
+
var messagesContainer = document.getElementsByClassName("messages");
|
|
50
|
+
var newMessage = document.createElement("p");
|
|
51
|
+
var localizedMessage = localizeMessage(message);
|
|
52
|
+
newMessage.innerHTML = localizedMessage;
|
|
53
|
+
messagesContainer.length && messagesContainer[0].appendChild(newMessage);
|
|
54
|
+
console.error(localizedMessage);
|
|
55
|
+
};
|
|
56
|
+
var displayRuntimeError = function () {
|
|
57
|
+
var errorContainer = document.getElementById("runtime-error");
|
|
58
|
+
if (!(arguments && arguments.length)) {
|
|
59
|
+
errorContainer.innerHTML = "";
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
errorContainer.innerHTML =
|
|
63
|
+
"<h6>" + localizeMessage("runtimeErrorTitle") + "</h6>";
|
|
64
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
65
|
+
if (!arguments[i])
|
|
66
|
+
continue;
|
|
67
|
+
var thisError = document.createElement("p");
|
|
68
|
+
thisError.innerHTML = localizeMessage(arguments[i]);
|
|
69
|
+
errorContainer.appendChild(thisError);
|
|
70
|
+
}
|
|
71
|
+
// Remove the messages after 6 seconds
|
|
72
|
+
setTimeout(function () {
|
|
73
|
+
errorContainer.innerHTML = "";
|
|
74
|
+
}, 6000);
|
|
75
|
+
};
|
|
76
|
+
var ADAPTER = new SCORMAdapter(displayRuntimeError);
|
|
77
|
+
if (!ADAPTER.foundAPI) {
|
|
78
|
+
displayInitError("apiNotFound");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!ADAPTER.LMSInitialize()) {
|
|
82
|
+
displayInitError("couldNotInitialize");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
var lessonStatus = ADAPTER.getLessonStatus();
|
|
86
|
+
if (lessonStatus === "not attempted") {
|
|
87
|
+
ADAPTER.setLessonStatus("incomplete");
|
|
88
|
+
}
|
|
89
|
+
var sourceUrl = document.body.getAttribute("data-source");
|
|
90
|
+
if (!sourceUrl) {
|
|
91
|
+
displayInitError("sourceUrlMissing");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
var sourceUrlParser = document.createElement("a");
|
|
95
|
+
sourceUrlParser.href = sourceUrl;
|
|
96
|
+
var learnerId = ADAPTER.getLearnerId();
|
|
97
|
+
var learnerName = ADAPTER.getLearnerName();
|
|
98
|
+
if (learnerId == null) {
|
|
99
|
+
displayInitError("learnerIdMissing");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
sourceUrlParser.search +=
|
|
103
|
+
(sourceUrlParser.search.startsWith("?") ? "&" : "?") +
|
|
104
|
+
"scorm" +
|
|
105
|
+
"&learner_id=".concat(learnerId) +
|
|
106
|
+
"&learner_name=".concat(learnerName) +
|
|
107
|
+
"&lms_origin=".concat(encodeURIComponent(location.origin)) +
|
|
108
|
+
"&data_from_lms=".concat(ADAPTER.getDataFromLMS());
|
|
109
|
+
var iframe = document.createElement("iframe");
|
|
110
|
+
iframe.setAttribute("src", sourceUrlParser.href);
|
|
111
|
+
iframe.setAttribute("frameborder", "0");
|
|
112
|
+
iframe.setAttribute("height", "100%");
|
|
113
|
+
iframe.setAttribute("width", "100%");
|
|
114
|
+
document.body.insertBefore(iframe, document.getElementById("wrapper"));
|
|
115
|
+
var sessionStart = new Date();
|
|
116
|
+
var host = sourceUrlParser.host;
|
|
117
|
+
// The `host` variable may or may not contain the port number depending on the browser.
|
|
118
|
+
// We remove it if it wasnt' explicitly set.
|
|
119
|
+
if (host.indexOf(":") > -1 &&
|
|
120
|
+
sourceUrl.indexOf(host) !== sourceUrlParser.protocol.length + 2) {
|
|
121
|
+
host = host.slice(0, host.indexOf(":"));
|
|
122
|
+
}
|
|
123
|
+
var sourceOrigin = sourceUrlParser.protocol + "//" + host;
|
|
124
|
+
new MessageReceiver(window, sourceOrigin, ADAPTER);
|
|
125
|
+
var sessionStart = new Date().getTime();
|
|
126
|
+
/*
|
|
127
|
+
* In case the beforeunload event is not triggered, we still want to send the session time to the LMS.
|
|
128
|
+
* This is why we send the session time every 10 seconds.
|
|
129
|
+
*/
|
|
130
|
+
setInterval(function () {
|
|
131
|
+
var now = new Date().getTime();
|
|
132
|
+
ADAPTER.setSessionTime(now - sessionStart);
|
|
133
|
+
}, 10000);
|
|
134
|
+
window.addEventListener("beforeunload", function (e) {
|
|
135
|
+
var sessionEnd = new Date().getTime();
|
|
136
|
+
ADAPTER.setSessionTime(sessionEnd - sessionStart);
|
|
137
|
+
ADAPTER.LMSTerminate();
|
|
193
138
|
});
|
|
194
139
|
}
|
|
195
140
|
exports.loadContent = loadContent;
|
package/package.json
CHANGED
package/lib/hashString.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function hashString(string: string): Promise<string>;
|
package/lib/hashString.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.hashString = void 0;
|
|
40
|
-
function hashString(string) {
|
|
41
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
42
|
-
var utf8, hashBuffer;
|
|
43
|
-
return __generator(this, function (_a) {
|
|
44
|
-
switch (_a.label) {
|
|
45
|
-
case 0:
|
|
46
|
-
utf8 = new TextEncoder().encode(string);
|
|
47
|
-
return [4 /*yield*/, crypto.subtle.digest("SHA-256", utf8)];
|
|
48
|
-
case 1:
|
|
49
|
-
hashBuffer = _a.sent();
|
|
50
|
-
return [2 /*return*/, Array.from(new Uint8Array(hashBuffer))
|
|
51
|
-
.map(function (bytes) { return bytes.toString(16).padStart(2, "0"); })
|
|
52
|
-
.join("")];
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
exports.hashString = hashString;
|