@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.
@@ -1,6 +1,5 @@
1
1
  export interface HTMLGeneratorProps {
2
2
  dataSource: string;
3
3
  libPath?: string;
4
- hashIdentifiers?: boolean;
5
4
  }
6
5
  export declare function HTMLGenerator(props: HTMLGeneratorProps): string;
@@ -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, _b = props.hashIdentifiers, hashIdentifiers = _b === void 0 ? false : _b;
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, "/hashString.js\"></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({hashIdentifiers: ").concat(hashIdentifiers, "});\" 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>");
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;
@@ -1,15 +1,4 @@
1
- export declare class MessageReceiver {
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;
@@ -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
- var MessageReceiver = /** @class */ (function () {
5
- function MessageReceiver(win, sourceOrigin, adapter) {
6
- this.adapter = adapter;
7
- var timeoutId = null;
8
- win.addEventListener("message", function (e) {
9
- var _this = this;
10
- if (e.origin !== sourceOrigin)
11
- return;
12
- var functionName = e.data["function"];
13
- var functionArgs = e.data["arguments"];
14
- if (functionName &&
15
- functionArgs &&
16
- typeof this[functionName] === "function") {
17
- // @ts-ignore
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
- }.bind(this));
28
- }
29
- MessageReceiver.prototype.commit = function () {
30
- this.adapter.LMSCommit();
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
- MessageReceiver.prototype.setTitle = function (title) {
28
+ this.setTitle = function (title) {
33
29
  document.title = title;
34
30
  };
35
- MessageReceiver.prototype.setScore = function (score) {
36
- this.adapter.setScore(score);
31
+ this.setScore = function (score) {
32
+ adapter.setScore(score);
37
33
  };
38
- MessageReceiver.prototype.setStudent = function (studentId, studentName) {
39
- this.adapter.setStudent(studentId, studentName);
34
+ this.setStudent = function (studentId, studentName) {
35
+ adapter.setStudent(studentId, studentName);
40
36
  };
41
- MessageReceiver.prototype.setLessonStatus = function (lessonStatus) {
42
- this.adapter.setLessonStatus(lessonStatus);
37
+ this.setLessonStatus = function (lessonStatus) {
38
+ adapter.setLessonStatus(lessonStatus);
43
39
  };
44
- MessageReceiver.prototype.setObjectives = function (objectivesIds) {
45
- if (this.adapter.objectivesAreAvailable) {
46
- this.adapter.setObjectives(objectivesIds);
40
+ this.setObjectives = function (objectivesIds) {
41
+ if (adapter.objectivesAreAvailable) {
42
+ adapter.setObjectives(objectivesIds);
47
43
  }
48
44
  };
49
- MessageReceiver.prototype.setObjectiveScore = function (objectiveId, score) {
50
- if (this.adapter.objectivesAreAvailable) {
51
- this.adapter.setObjectiveScore(objectiveId, score);
45
+ this.setObjectiveScore = function (objectiveId, score) {
46
+ if (adapter.objectivesAreAvailable) {
47
+ adapter.setObjectiveScore(objectiveId, score);
52
48
  }
53
49
  };
54
- MessageReceiver.prototype.setObjectiveStatus = function (objectiveId, status) {
55
- if (this.adapter.objectivesAreAvailable) {
56
- this.adapter.setObjectiveStatus(objectiveId, status);
50
+ this.setObjectiveStatus = function (objectiveId, status) {
51
+ if (adapter.objectivesAreAvailable) {
52
+ adapter.setObjectiveStatus(objectiveId, status);
57
53
  }
58
54
  };
59
- return MessageReceiver;
60
- }());
55
+ }
61
56
  exports.MessageReceiver = MessageReceiver;
62
57
  var MessageEmitter = /** @class */ (function () {
63
58
  function MessageEmitter(lmsOrigin) {
@@ -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(): true | undefined;
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?: "get" | "set" | undefined;
25
+ method: "get" | "set";
26
26
  key: string;
27
- } | null;
27
+ };
28
28
  getDataFromLMS(): any;
29
29
  getLearnerId(): any;
30
30
  getLearnerName(): any;
@@ -15,7 +15,7 @@ var SCORMAdapter = /** @class */ (function () {
15
15
  code: 401,
16
16
  getShouldBeIgnored: function () {
17
17
  return !_this._isSCORM2004 &&
18
- !!_this._lastRequest &&
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
- !!_this._lastRequest &&
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
- var _a;
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
- var result = this._API[fun].apply(this._API, args);
132
- console.info("[SCOL-R] ".concat(fun, "(").concat(args.join(", "), ") = ").concat(JSON.stringify(result)));
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", "hashString.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
@@ -24,7 +24,6 @@ exports.libFiles = [
24
24
  "loadContent.js",
25
25
  "MessageHandler.js",
26
26
  "SCORMAdapter.js",
27
- "hashString.js",
28
27
  ];
29
28
  exports.scormVersions = [
30
29
  "1.2",
@@ -1,3 +1 @@
1
- export function loadContent({ hashIdentifiers }?: {
2
- hashIdentifiers?: boolean | undefined;
3
- }): Promise<void>;
1
+ export function loadContent(): void;
@@ -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(_a) {
41
- var _b = _a === void 0 ? {} : _a, _c = _b.hashIdentifiers, hashIdentifiers = _c === void 0 ? false : _c;
42
- return __awaiter(this, void 0, void 0, function () {
43
- var messages, localizeMessage, displayInitError, displayRuntimeError, ADAPTER, lessonStatus, sourceUrl, sourceUrlParser, learnerId, learnerName, iframe, sessionStart, host, sourceOrigin, sessionStart;
44
- return __generator(this, function (_d) {
45
- switch (_d.label) {
46
- case 0:
47
- messages = {
48
- en: {
49
- pageTitle: "Your content is loading...",
50
- pageSubtitle: "Please wait, or if your content doesn't appear, try closing and opening this window again.",
51
- pageErrorMessagesTitle: "If the initialization fails, error messages will appear below:",
52
- 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>.',
53
- apiNotFound: "<p>We were not able to contact your LMS: please close this window and try again later.</p>",
54
- couldNotInitialize: "<p>We were not able to initialize the connection with your LMS: please close this window and try again later.</p>",
55
- learnerIdMissing: "<p>We could not get your learner ID from the LMS: please close this window and try again later.</p>",
56
- sourceUrlMissing: "<p>We could find the address of the remote resource: it looks like this module is invalid, please contact your LMS administrator.</p>",
57
- runtimeErrorTitle: "An error occurred:",
58
- commitFailed: "The intermediate recording could not succeed. Please close the window and try again later, or contact your administrator if the problem keeps occurring.",
59
- },
60
- fr: {
61
- pageTitle: "Votre contenu est en cours de chargement...",
62
- pageSubtitle: "Merci de patienter&nbsp;; si votre contenu ne se charge pas, veuillez essayer de fermer et d'ouvrir cette fenêtre à nouveau.",
63
- pageErrorMessagesTitle: "Si l'initialisation échoue, les messages d'erreur apparaîtront ci-dessous&nbsp;:",
64
- 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>.',
65
- apiNotFound: "<p>Nous n'avons pas pu contacter votre LMS&nbsp;: veuillez fermer cette fenêtre et réessayer plus tard.</p>",
66
- couldNotInitialize: "<p>Nous n'avons pas pu initialiser la connection avec votre LMS&nbsp;: veuillez fermer cette fenêtre et réessayer plus tard.</p>",
67
- learnerIdMissing: "<p>Nous n'avons pas pu obtenir votre identifiant depuis le LMS&nbsp;: veuillez fermer cette fenêtre et réessayer plus tard.</p>",
68
- sourceUrlMissing: "<p>Nous n'avons pas pu trouver l'adresse de la ressource distante&nbsp;: il semble que ce module est invalide, veuillez contacter l'administrateur de votre LMS.</p>",
69
- runtimeErrorTitle: "Une erreur s'est produite&nbsp;:",
70
- 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.",
71
- },
72
- };
73
- localizeMessage = function (message) {
74
- var locale = navigator.language || navigator.userLanguage;
75
- if (locale)
76
- locale = locale.split(/[_-]/)[0];
77
- if (!messages.hasOwnProperty(locale))
78
- locale = "en";
79
- var localizedMessages = messages[locale];
80
- return localizedMessages.hasOwnProperty(message)
81
- ? localizedMessages[message]
82
- : message;
83
- };
84
- document.getElementById("title").innerHTML = localizeMessage("pageTitle");
85
- document.getElementById("subtitle").innerHTML =
86
- localizeMessage("pageSubtitle");
87
- document.getElementById("footer-content").innerHTML =
88
- localizeMessage("pageFooter");
89
- document.getElementById("title-error-messages").innerHTML = localizeMessage("pageErrorMessagesTitle");
90
- displayInitError = function (message) {
91
- var messagesContainer = document.getElementsByClassName("messages");
92
- var newMessage = document.createElement("p");
93
- var localizedMessage = localizeMessage(message);
94
- newMessage.innerHTML = localizedMessage;
95
- messagesContainer.length && messagesContainer[0].appendChild(newMessage);
96
- console.error(localizedMessage);
97
- };
98
- displayRuntimeError = function () {
99
- var errorContainer = document.getElementById("runtime-error");
100
- if (!(arguments && arguments.length)) {
101
- errorContainer.innerHTML = "";
102
- return;
103
- }
104
- errorContainer.innerHTML =
105
- "<h6>" + localizeMessage("runtimeErrorTitle") + "</h6>";
106
- for (var i = 0; i < arguments.length; i++) {
107
- if (!arguments[i])
108
- continue;
109
- var thisError = document.createElement("p");
110
- thisError.innerHTML = localizeMessage(arguments[i]);
111
- errorContainer.appendChild(thisError);
112
- }
113
- // Remove the messages after 6 seconds
114
- setTimeout(function () {
115
- errorContainer.innerHTML = "";
116
- }, 6000);
117
- };
118
- ADAPTER = new SCORMAdapter(displayRuntimeError);
119
- if (!ADAPTER.foundAPI) {
120
- displayInitError("apiNotFound");
121
- return [2 /*return*/];
122
- }
123
- if (!ADAPTER.LMSInitialize()) {
124
- displayInitError("couldNotInitialize");
125
- return [2 /*return*/];
126
- }
127
- lessonStatus = ADAPTER.getLessonStatus();
128
- if (lessonStatus === "not attempted") {
129
- ADAPTER.setLessonStatus("incomplete");
130
- }
131
- sourceUrl = document.body.getAttribute("data-source");
132
- if (!sourceUrl) {
133
- displayInitError("sourceUrlMissing");
134
- return [2 /*return*/];
135
- }
136
- sourceUrlParser = document.createElement("a");
137
- sourceUrlParser.href = sourceUrl;
138
- learnerId = ADAPTER.getLearnerId();
139
- learnerName = ADAPTER.getLearnerName();
140
- if (learnerId == null) {
141
- displayInitError("learnerIdMissing");
142
- return [2 /*return*/];
143
- }
144
- if (!hashIdentifiers) return [3 /*break*/, 3];
145
- return [4 /*yield*/, hashString(learnerId)];
146
- case 1:
147
- learnerId = _d.sent();
148
- return [4 /*yield*/, hashString(learnerName)];
149
- case 2:
150
- learnerName = _d.sent();
151
- _d.label = 3;
152
- case 3:
153
- sourceUrlParser.search +=
154
- (sourceUrlParser.search.startsWith("?") ? "&" : "?") +
155
- "scorm" +
156
- "&learner_id=".concat(learnerId) +
157
- "&learner_name=".concat(learnerName) +
158
- "&lms_origin=".concat(encodeURIComponent(location.origin)) +
159
- "&are_identifiers_hashed=".concat(hashIdentifiers);
160
- iframe = document.createElement("iframe");
161
- iframe.setAttribute("src", sourceUrlParser.href);
162
- iframe.setAttribute("frameborder", "0");
163
- iframe.setAttribute("height", "100%");
164
- iframe.setAttribute("width", "100%");
165
- document.body.insertBefore(iframe, document.getElementById("wrapper"));
166
- sessionStart = new Date();
167
- host = sourceUrlParser.host;
168
- // The `host` variable may or may not contain the port number depending on the browser.
169
- // We remove it if it wasnt' explicitly set.
170
- if (host.indexOf(":") > -1 &&
171
- sourceUrl.indexOf(host) !== sourceUrlParser.protocol.length + 2) {
172
- host = host.slice(0, host.indexOf(":"));
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&nbsp;; 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&nbsp;:",
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&nbsp;: 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&nbsp;: 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&nbsp;: 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&nbsp;: il semble que ce module est invalide, veuillez contacter l'administrateur de votre LMS.</p>",
27
+ runtimeErrorTitle: "Une erreur s'est produite&nbsp;:",
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@didask/scol-r",
3
- "version": "2.9.0-beta.2",
3
+ "version": "2.10.0",
4
4
  "description": "Shareable Cross-Origin Learning Resources",
5
5
  "main": "index.html",
6
6
  "types": "lib/index.d.ts",
@@ -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;