@didask/scol-r 3.0.0-beta.1 → 3.0.0-beta.2

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.
@@ -0,0 +1,5 @@
1
+ export interface HTMLGeneratorProps {
2
+ dataSource: string;
3
+ libPath?: string;
4
+ }
5
+ export declare function HTMLGenerator(props: HTMLGeneratorProps): string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HTMLGenerator = void 0;
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=\"" + libPath + "/SCORMAdapter.js\"></script>\n <script type=\"text/javascript\" src=\"" + libPath + "/MessageHandler.js\"></script>\n <script type=\"text/javascript\" src=\"" + 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=\"" + 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
+ }
8
+ exports.HTMLGenerator = HTMLGenerator;
@@ -0,0 +1,20 @@
1
+ import { scormVersions } from ".";
2
+ export declare class Sco {
3
+ scoID: string;
4
+ scoTitle: string;
5
+ author: string;
6
+ learningTime: number;
7
+ resources: string[];
8
+ constructor(scoID: string, scoTitle: string, author: string, learningTime: number, resources?: string[]);
9
+ }
10
+ export interface ManifestGeneratorProps {
11
+ courseId: string;
12
+ courseTitle: string;
13
+ courseAuthor: string;
14
+ scoList?: Sco[];
15
+ sharedResources?: string[];
16
+ totalLearningTime?: number;
17
+ dataFromLms?: string;
18
+ scormVersion?: typeof scormVersions[number];
19
+ }
20
+ export declare function ManifestGenerator({ courseId, scoList, sharedResources, totalLearningTime, dataFromLms, scormVersion, ...props }: ManifestGeneratorProps): string;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.ManifestGenerator = exports.Sco = void 0;
26
+ var Sco = /** @class */ (function () {
27
+ function Sco(scoID, scoTitle, author, learningTime, resources) {
28
+ this.scoID = scoID;
29
+ this.scoTitle = scoTitle;
30
+ this.author = author;
31
+ this.learningTime = learningTime;
32
+ this.resources = resources || [];
33
+ }
34
+ return Sco;
35
+ }());
36
+ exports.Sco = Sco;
37
+ var formatLearningTime = function (learningTime) {
38
+ var intHours = Math.floor(learningTime / 60);
39
+ var hours = intHours > 10 ? intHours : "0" + intHours;
40
+ var intMinutes = intHours > 0 ? learningTime - intHours * 60 : learningTime;
41
+ var minutes = intMinutes > 10 ? intMinutes : "0" + intMinutes;
42
+ return hours + ":" + minutes + ":00";
43
+ };
44
+ var removeSpecialChars = function (obj) {
45
+ return Object.entries(obj).reduce(function (acc, _a) {
46
+ var _b;
47
+ var key = _a[0], value = _a[1];
48
+ return (__assign(__assign({}, acc), (_b = {}, _b[key] = value.replace(/&/g, "-"), _b)));
49
+ }, {});
50
+ };
51
+ function ManifestGenerator(_a) {
52
+ var courseId = _a.courseId, _b = _a.scoList, scoList = _b === void 0 ? [] : _b, _c = _a.sharedResources, sharedResources = _c === void 0 ? [] : _c, _d = _a.totalLearningTime, totalLearningTime = _d === void 0 ? 0 : _d, dataFromLms = _a.dataFromLms, _e = _a.scormVersion, scormVersion = _e === void 0 ? "1.2" : _e, props = __rest(_a, ["courseId", "scoList", "sharedResources", "totalLearningTime", "dataFromLms", "scormVersion"]);
53
+ var _f = removeSpecialChars(props), courseTitle = _f.courseTitle, courseAuthor = _f.courseAuthor;
54
+ var courseGlobalLearningTime = scoList.length
55
+ ? scoList.reduce(function (acc, sco) { return acc + sco.learningTime; }, 0)
56
+ : totalLearningTime;
57
+ return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n <manifest xmlns=\"http://www.imsproject.org/xsd/imscp_rootv1p1p2\" identifier=\"" + courseId + "\" version=\"1.0\" xmlns:imsmd=\"http://www.imsglobal.org/xsd/imsmd_rootv1p2p1\" xmlns:adlcp=\"http://www.adlnet.org/xsd/adlcp_rootv1p2\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd\">\n <metadata>\n <schema>ADL SCORM</schema>\n <schemaversion>" + scormVersion + "</schemaversion>\n <imsmd:lom xmlns=\"http://ltsc.ieee.org/xsd/LOM\">\n <imsmd:general>\n <imsmd:identifier>" + courseId + "</imsmd:identifier>\n </imsmd:general>\n <imsmd:lifecycle>\n <imsmd:contribute>\n <imsmd:role>\n <imsmd:source>\n <imsmd:langstring xml:lang=\"fr\">LOMv1.0</imsmd:langstring>\n </imsmd:source>\n <imsmd:value>\n <imsmd:langstring xml:lang=\"fr\">Author</imsmd:langstring>\n </imsmd:value>\n </imsmd:role>\n <imsmd:centity>\n <imsmd:vcard>\n begin:vcard\n fn:" + courseAuthor + "\n end:vcard\n </imsmd:vcard>\n </imsmd:centity>\n </imsmd:contribute>\n </imsmd:lifecycle>\n <imsmd:educational>\n <imsmd:typicallearningtime>\n <imsmd:datetime>" + formatLearningTime(courseGlobalLearningTime) + "</imsmd:datetime>\n </imsmd:typicallearningtime>\n </imsmd:educational>\n </imsmd:lom>\n </metadata>\n <organizations default=\"Org1\">\n <organization identifier=\"Org1\">\n <title>" + courseTitle + "</title>\n " + scoList
58
+ .map(function (_a) {
59
+ var scoID = _a.scoID, learningTime = _a.learningTime, resources = _a.resources, props = __rest(_a, ["scoID", "learningTime", "resources"]);
60
+ var _b = removeSpecialChars(props), scoTitle = _b.scoTitle, author = _b.author;
61
+ return "<item identifier=\"" + scoTitle + "\" identifierref=\"resource_" + scoID + "\" isvisible=\"true\">\n <title>" + scoTitle + "</title>\n <adlcp:dataFromLMS>" + (dataFromLms !== null && dataFromLms !== void 0 ? dataFromLms : courseId + ":" + scoID) + "</adlcp:dataFromLMS>\n <metadata>\n <imsmd:lom xmlns=\"http://ltsc.ieee.org/xsd/LOM\">\n <imsmd:general>\n <imsmd:identifier>" + scoID + "</imsmd:identifier>\n </imsmd:general>\n <imsmd:lifecycle>\n <imsmd:contribute>\n <imsmd:role>\n <imsmd:source>\n <imsmd:langstring xml:lang=\"fr\">LOMv1.0</imsmd:langstring>\n </imsmd:source>\n <imsmd:value>\n <imsmd:langstring xml:lang=\"fr\">Author</imsmd:langstring>\n </imsmd:value>\n </imsmd:role>\n <imsmd:centity>\n <imsmd:vcard>\n begin:vcard\n fn:" + author + "\n end:vcard\n </imsmd:vcard>\n </imsmd:centity>\n </imsmd:contribute>\n </imsmd:lifecycle>\n <imsmd:educational>\n <imsmd:typicallearningtime>\n <imsmd:datetime>" + formatLearningTime(learningTime) + "</imsmd:datetime>\n </imsmd:typicallearningtime>\n </imsmd:educational>\n </imsmd:lom>\n </metadata>\n </item>";
62
+ })
63
+ .join("\n") + "\n </organization>\n </organizations>\n <resources>\n " + ((sharedResources === null || sharedResources === void 0 ? void 0 : sharedResources.length)
64
+ ? "<resource adlcp:scormtype=\"asset\" type=\"webcontent\" identifier=\"shared_resources\">\n " + sharedResources
65
+ .map(function (resource) {
66
+ return "<file href=\"" + resource + "\"/>";
67
+ })
68
+ .join("\n") + "\n </resource>"
69
+ : "") + "\n " + scoList
70
+ .map(function (sco) {
71
+ return "<resource adlcp:scormtype=\"sco\" type=\"webcontent\" identifier=\"resource_" + sco.scoID + "\" href=\"./" + sco.scoID + "/index.html\">\n " + ((sharedResources === null || sharedResources === void 0 ? void 0 : sharedResources.length)
72
+ ? '<dependency identifierref="shared_resources"/>'
73
+ : "") + "\n " + sco.resources
74
+ .map(function (resource) {
75
+ return "<file href=\"" + resource + "\"/>";
76
+ })
77
+ .join("\n") + "\n </resource>";
78
+ })
79
+ .join("\n") + "\n </resources>\n </manifest>";
80
+ }
81
+ exports.ManifestGenerator = ManifestGenerator;
@@ -0,0 +1,12 @@
1
+ export declare function MessageReceiver(win: Window, sourceOrigin: string, adapter: any): void;
2
+ export declare class MessageEmitter {
3
+ private currentWindow;
4
+ private lmsOrigin;
5
+ constructor(lmsOrigin: string);
6
+ private sendMessage;
7
+ setLessonStatus(status: string): void;
8
+ setScore(score: number): void;
9
+ setObjectives(objectives: string[]): void;
10
+ setObjectiveScore(objectiveId: string, score: number): void;
11
+ setObjectiveStatus(objectiveId: string, status: "completed" | "incomplete"): void;
12
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MessageEmitter = exports.MessageReceiver = void 0;
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);
18
+ }
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();
27
+ };
28
+ this.setTitle = function (title) {
29
+ document.title = title;
30
+ };
31
+ this.setScore = function (score) {
32
+ adapter.setScore(score);
33
+ };
34
+ this.setLessonStatus = function (lessonStatus) {
35
+ adapter.setLessonStatus(lessonStatus);
36
+ };
37
+ this.setObjectives = function (objectivesIds) {
38
+ if (adapter.objectivesAreAvailable) {
39
+ adapter.setObjectives(objectivesIds);
40
+ }
41
+ };
42
+ this.setObjectiveScore = function (objectiveId, score) {
43
+ if (adapter.objectivesAreAvailable) {
44
+ adapter.setObjectiveScore(objectiveId, score);
45
+ }
46
+ };
47
+ this.setObjectiveStatus = function (objectiveId, status) {
48
+ if (adapter.objectivesAreAvailable) {
49
+ adapter.setObjectiveStatus(objectiveId, status);
50
+ }
51
+ };
52
+ }
53
+ exports.MessageReceiver = MessageReceiver;
54
+ var MessageEmitter = /** @class */ (function () {
55
+ function MessageEmitter(lmsOrigin) {
56
+ this.currentWindow = window.parent || window.opener;
57
+ this.lmsOrigin = lmsOrigin;
58
+ }
59
+ MessageEmitter.prototype.sendMessage = function (name, values) {
60
+ this.currentWindow.postMessage({
61
+ function: name,
62
+ arguments: values,
63
+ }, this.lmsOrigin);
64
+ };
65
+ MessageEmitter.prototype.setLessonStatus = function (status) {
66
+ this.sendMessage("setLessonStatus", [status]);
67
+ };
68
+ MessageEmitter.prototype.setScore = function (score) {
69
+ this.sendMessage("setScore", [score]);
70
+ };
71
+ MessageEmitter.prototype.setObjectives = function (objectives) {
72
+ this.sendMessage("setObjectives", [objectives]);
73
+ };
74
+ MessageEmitter.prototype.setObjectiveScore = function (objectiveId, score) {
75
+ this.sendMessage("setObjectiveScore", [objectiveId, score]);
76
+ };
77
+ MessageEmitter.prototype.setObjectiveStatus = function (objectiveId, status) {
78
+ this.sendMessage("setObjectiveStatus", [objectiveId, status]);
79
+ };
80
+ return MessageEmitter;
81
+ }());
82
+ exports.MessageEmitter = MessageEmitter;
@@ -0,0 +1,37 @@
1
+ export declare class SCORMAdapter {
2
+ private _API;
3
+ private _isSCORM2004;
4
+ private _errorCallback;
5
+ private _ignorableErrorCodes;
6
+ constructor(errorCallback?: Function);
7
+ get foundAPI(): boolean;
8
+ private _initialize;
9
+ private _findAndSetAPI;
10
+ private _findAPIInWindow;
11
+ private _callAPIFunction;
12
+ private _handleError;
13
+ private _warnNOAPI;
14
+ LMSInitialize(): any;
15
+ LMSTerminate(): any;
16
+ LMSGetValue(name: string): any;
17
+ LMSSetValue(name: string, value: string | number): any;
18
+ LMSCommit(): any;
19
+ LMSGetLastError(): number;
20
+ LMSGetErrorString(errorCode: number): any;
21
+ LMSGetDiagnostic(errorCode: number): any;
22
+ getDataFromLMS(): any;
23
+ getLearnerId(): any;
24
+ setScore(score: number): void;
25
+ getScore(): any;
26
+ getLessonStatus(): any;
27
+ setLessonStatus(lessonStatus: string): void;
28
+ setSessionTime(msSessionTime: number): void;
29
+ get objectivesAreAvailable(): boolean;
30
+ setObjectives(objectivesIds: string[]): void;
31
+ get objectives(): any[];
32
+ setObjectiveScore(objectiveId: string, score: number): void;
33
+ setObjectiveStatus(objectiveId: string, status: "completed" | "incomplete"): void;
34
+ getObjectiveScore(objectiveId: string): any;
35
+ setSuspendData(data: string): void;
36
+ get suspendData(): any;
37
+ }
@@ -0,0 +1,314 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SCORMAdapter = void 0;
4
+ var SCORMAdapter = /** @class */ (function () {
5
+ function SCORMAdapter(errorCallback) {
6
+ if (errorCallback === void 0) { errorCallback = function () { }; }
7
+ this._ignorableErrorCodes = [
8
+ { code: 0 },
9
+ { code: 403, scope: "2004" },
10
+ ];
11
+ this._API = null;
12
+ this._isSCORM2004 = false;
13
+ this._errorCallback = errorCallback;
14
+ this._findAndSetAPI();
15
+ }
16
+ Object.defineProperty(SCORMAdapter.prototype, "foundAPI", {
17
+ get: function () {
18
+ return !!this._API;
19
+ },
20
+ enumerable: false,
21
+ configurable: true
22
+ });
23
+ SCORMAdapter.prototype._initialize = function () {
24
+ if (this._isSCORM2004) {
25
+ this.LMSSetValue("cmi.score.min", 0);
26
+ this.LMSSetValue("cmi.score.max", 100);
27
+ }
28
+ else {
29
+ this.LMSSetValue("cmi.core.score.min", 0);
30
+ this.LMSSetValue("cmi.core.score.max", 100);
31
+ }
32
+ };
33
+ SCORMAdapter.prototype._findAndSetAPI = function () {
34
+ var _this = this;
35
+ if (typeof window === "undefined") {
36
+ console.error("Unable to find an API adapter");
37
+ }
38
+ else {
39
+ var theAPI = this._findAPIInWindow(window);
40
+ if (theAPI == null &&
41
+ window.opener != null &&
42
+ typeof window.opener != "undefined") {
43
+ theAPI = this._findAPIInWindow(window.opener);
44
+ }
45
+ if (theAPI == null) {
46
+ console.error("Unable to find an API adapter");
47
+ }
48
+ else {
49
+ this._API = theAPI["API"];
50
+ this._isSCORM2004 = theAPI["isSCORM2004"];
51
+ this._ignorableErrorCodes = this._ignorableErrorCodes.filter(function (_a) {
52
+ var scope = _a.scope;
53
+ return !scope || (_this._isSCORM2004 ? scope === "2004" : scope === "1.2");
54
+ });
55
+ }
56
+ if (this._API == null) {
57
+ console.error("Couldn't find the API!");
58
+ }
59
+ }
60
+ };
61
+ SCORMAdapter.prototype._findAPIInWindow = function (win) {
62
+ var findAPITries = 0;
63
+ while (win.API == null &&
64
+ win.API_1484_11 == null &&
65
+ win.parent != null &&
66
+ win.parent != win) {
67
+ findAPITries++;
68
+ if (findAPITries > 7) {
69
+ console.error("Error finding API -- too deeply nested.");
70
+ return null;
71
+ }
72
+ win = win.parent;
73
+ }
74
+ if (win.API) {
75
+ return {
76
+ API: win.API,
77
+ isSCORM2004: false,
78
+ };
79
+ }
80
+ else if (win.API_1484_11) {
81
+ return {
82
+ API: win.API_1484_11,
83
+ isSCORM2004: true,
84
+ };
85
+ }
86
+ return null;
87
+ };
88
+ SCORMAdapter.prototype._callAPIFunction = function (fun, args) {
89
+ if (args === void 0) { args = [""]; }
90
+ if (this._API == null) {
91
+ this._warnNOAPI();
92
+ return;
93
+ }
94
+ if (this._isSCORM2004 && fun.indexOf("LMS") == 0) {
95
+ fun = fun.substr(3);
96
+ }
97
+ else if (!this._isSCORM2004 && !(fun.indexOf("LMS") == 0)) {
98
+ fun = "LMS" + fun;
99
+ }
100
+ console.info("[SCOL-R] Calling a scorm api function", { fun: fun, args: args });
101
+ return this._API[fun].apply(this._API, args);
102
+ };
103
+ SCORMAdapter.prototype._handleError = function (functionName) {
104
+ var lastErrorCode = this.LMSGetLastError();
105
+ var lastErrorString = this.LMSGetErrorString(lastErrorCode);
106
+ var lastErrorDiagnostic = this.LMSGetDiagnostic(lastErrorCode);
107
+ if (!this._ignorableErrorCodes.some(function (_a) {
108
+ var code = _a.code;
109
+ return code === lastErrorCode;
110
+ })) {
111
+ console.warn(functionName, "An error occured on the SCORM API: code " + lastErrorCode + ", message: " + lastErrorString, lastErrorDiagnostic);
112
+ this._errorCallback(lastErrorString, lastErrorDiagnostic && lastErrorDiagnostic != lastErrorCode
113
+ ? lastErrorDiagnostic
114
+ : null);
115
+ }
116
+ };
117
+ SCORMAdapter.prototype._warnNOAPI = function () {
118
+ console.warn("Cannot execute this function because the SCORM API is not available.");
119
+ this._errorCallback("apiNotFound");
120
+ };
121
+ SCORMAdapter.prototype.LMSInitialize = function () {
122
+ var functionName = "Initialize";
123
+ var result = this._callAPIFunction(functionName);
124
+ var lastErrorCode = this.LMSGetLastError();
125
+ var success = eval(result.toString()) ||
126
+ (this._isSCORM2004
127
+ ? lastErrorCode === 103 // 103 in 2004.* = already initialized
128
+ : lastErrorCode === 101); // 101 in 1.2 = already initialized
129
+ if (success) {
130
+ this._initialize();
131
+ }
132
+ return success || this._handleError(functionName);
133
+ };
134
+ SCORMAdapter.prototype.LMSTerminate = function () {
135
+ var functionName = this._isSCORM2004 ? "Terminate" : "Finish";
136
+ var result = this._callAPIFunction(functionName);
137
+ var success = eval(result.toString());
138
+ return success || this._handleError(functionName);
139
+ };
140
+ SCORMAdapter.prototype.LMSGetValue = function (name) {
141
+ var functionName = "GetValue";
142
+ var value = this._callAPIFunction(functionName, [name]);
143
+ var success = this.LMSGetLastError() === 0;
144
+ return success ? value : this._handleError(functionName + ": " + name);
145
+ };
146
+ SCORMAdapter.prototype.LMSSetValue = function (name, value) {
147
+ var functionName = "SetValue";
148
+ var result = this._callAPIFunction(functionName, [name, value]);
149
+ var success = eval(result.toString());
150
+ return success || this._handleError(functionName + ": {" + name + ": " + value + "}");
151
+ };
152
+ SCORMAdapter.prototype.LMSCommit = function () {
153
+ var result = this._callAPIFunction("Commit");
154
+ var success = eval(result.toString());
155
+ return success || this._errorCallback("commitFailed");
156
+ };
157
+ SCORMAdapter.prototype.LMSGetLastError = function () {
158
+ return parseInt(this._callAPIFunction("GetLastError"));
159
+ };
160
+ SCORMAdapter.prototype.LMSGetErrorString = function (errorCode) {
161
+ return this._callAPIFunction("GetErrorString", [errorCode]);
162
+ };
163
+ SCORMAdapter.prototype.LMSGetDiagnostic = function (errorCode) {
164
+ return this._callAPIFunction("GetDiagnostic", [errorCode]);
165
+ };
166
+ SCORMAdapter.prototype.getDataFromLMS = function () {
167
+ return this.LMSGetValue("cmi.launch_data");
168
+ };
169
+ SCORMAdapter.prototype.getLearnerId = function () {
170
+ var CMIVariableName = this._isSCORM2004
171
+ ? "cmi.learner_id"
172
+ : "cmi.core.student_id";
173
+ return this.LMSGetValue(CMIVariableName);
174
+ };
175
+ SCORMAdapter.prototype.setScore = function (score) {
176
+ if (this._isSCORM2004) {
177
+ this.LMSSetValue("cmi.score.raw", score);
178
+ this.LMSSetValue("cmi.score.scaled", score / 100);
179
+ }
180
+ else {
181
+ this.LMSSetValue("cmi.core.score.raw", score);
182
+ }
183
+ };
184
+ SCORMAdapter.prototype.getScore = function () {
185
+ var CMIVariableName = this._isSCORM2004
186
+ ? "cmi.score.raw"
187
+ : "cmi.core.score.raw";
188
+ var score = this.LMSGetValue(CMIVariableName);
189
+ return score;
190
+ };
191
+ SCORMAdapter.prototype.getLessonStatus = function () {
192
+ var CMIVariableName = this._isSCORM2004
193
+ ? "cmi.completion_status"
194
+ : "cmi.core.lesson_status";
195
+ return this.LMSGetValue(CMIVariableName);
196
+ };
197
+ SCORMAdapter.prototype.setLessonStatus = function (lessonStatus) {
198
+ if (this._isSCORM2004) {
199
+ var successStatus = "unknown";
200
+ if (lessonStatus === "passed" || lessonStatus === "failed")
201
+ successStatus = lessonStatus;
202
+ this.LMSSetValue("cmi.success_status", successStatus);
203
+ var completionStatus = "unknown";
204
+ if (lessonStatus === "passed" || lessonStatus === "completed") {
205
+ completionStatus = "completed";
206
+ }
207
+ else if (lessonStatus === "incomplete") {
208
+ completionStatus = "incomplete";
209
+ }
210
+ else if (lessonStatus === "not attempted" ||
211
+ lessonStatus === "browsed") {
212
+ completionStatus = "not attempted";
213
+ }
214
+ this.LMSSetValue("cmi.completion_status", completionStatus);
215
+ }
216
+ else {
217
+ this.LMSSetValue("cmi.core.lesson_status", lessonStatus);
218
+ }
219
+ };
220
+ SCORMAdapter.prototype.setSessionTime = function (msSessionTime) {
221
+ var CMIVariableName = this._isSCORM2004
222
+ ? "cmi.session_time"
223
+ : "cmi.core.session_time";
224
+ var duration;
225
+ if (this._isSCORM2004) {
226
+ duration = Math.round(msSessionTime / 1000);
227
+ }
228
+ else {
229
+ var hours = Math.floor(msSessionTime / 1000 / 60 / 60);
230
+ msSessionTime -= hours * 1000 * 60 * 60;
231
+ var minutes = Math.floor(msSessionTime / 1000 / 60);
232
+ msSessionTime -= minutes * 1000 * 60;
233
+ var seconds = Math.floor(msSessionTime / 1000);
234
+ var formattedSeconds = seconds < 10 ? "0" + seconds : seconds;
235
+ var formattedMinutes = minutes < 10 ? "0" + minutes : minutes;
236
+ var formattedHours = hours < 10 ? "0" + hours : hours;
237
+ duration =
238
+ formattedHours + ":" + formattedMinutes + ":" + formattedSeconds;
239
+ }
240
+ this.LMSSetValue(CMIVariableName, duration);
241
+ };
242
+ Object.defineProperty(SCORMAdapter.prototype, "objectivesAreAvailable", {
243
+ get: function () {
244
+ return this.LMSGetValue("cmi.objectives._children") !== null;
245
+ },
246
+ enumerable: false,
247
+ configurable: true
248
+ });
249
+ SCORMAdapter.prototype.setObjectives = function (objectivesIds) {
250
+ var _this = this;
251
+ objectivesIds.forEach(function (objectiveId, index) {
252
+ _this.LMSSetValue("cmi.objectives." + index + ".id", objectiveId);
253
+ });
254
+ };
255
+ Object.defineProperty(SCORMAdapter.prototype, "objectives", {
256
+ get: function () {
257
+ var objectives = [];
258
+ var objectivesNbr = this.LMSGetValue("cmi.objectives._count");
259
+ for (var index = 0; index < objectivesNbr; index++) {
260
+ objectives.push(this.LMSGetValue("cmi.objectives." + index + ".id"));
261
+ }
262
+ return objectives;
263
+ },
264
+ enumerable: false,
265
+ configurable: true
266
+ });
267
+ SCORMAdapter.prototype.setObjectiveScore = function (objectiveId, score) {
268
+ var objectivesNbr = this.LMSGetValue("cmi.objectives._count");
269
+ for (var index = 0; index < objectivesNbr; index++) {
270
+ var storedObjectiveId = this.LMSGetValue("cmi.objectives." + index + ".id");
271
+ if (objectiveId === storedObjectiveId) {
272
+ this.LMSSetValue("cmi.objectives." + index + ".score.raw", score);
273
+ return;
274
+ }
275
+ }
276
+ };
277
+ SCORMAdapter.prototype.setObjectiveStatus = function (objectiveId, status) {
278
+ var objectivesNbr = this.LMSGetValue("cmi.objectives._count");
279
+ for (var index = 0; index < objectivesNbr; index++) {
280
+ var storedObjectiveId = this.LMSGetValue("cmi.objectives." + index + ".id");
281
+ if (objectiveId === storedObjectiveId) {
282
+ if (this._isSCORM2004) {
283
+ this.LMSSetValue("cmi.objectives." + index + ".success_status", status === "completed" ? "passed" : "unknown");
284
+ this.LMSSetValue("cmi.objectives." + index + ".completion_status", status === "completed" ? "completed" : "incomplete");
285
+ }
286
+ else {
287
+ this.LMSSetValue("cmi.objectives." + index + ".status", status === "completed" ? "passed" : "incomplete");
288
+ }
289
+ return;
290
+ }
291
+ }
292
+ };
293
+ SCORMAdapter.prototype.getObjectiveScore = function (objectiveId) {
294
+ var objectivesNbr = this.LMSGetValue("cmi.objectives._count");
295
+ for (var index = 0; index < objectivesNbr; index++) {
296
+ var storedObjectiveId = this.LMSGetValue("cmi.objectives." + index + ".id");
297
+ if (objectiveId === storedObjectiveId) {
298
+ return this.LMSGetValue("cmi.objectives." + index + ".score.raw");
299
+ }
300
+ }
301
+ };
302
+ SCORMAdapter.prototype.setSuspendData = function (data) {
303
+ this.LMSSetValue("cmi.suspend_data", data);
304
+ };
305
+ Object.defineProperty(SCORMAdapter.prototype, "suspendData", {
306
+ get: function () {
307
+ return this.LMSGetValue("cmi.suspend_data");
308
+ },
309
+ enumerable: false,
310
+ configurable: true
311
+ });
312
+ return SCORMAdapter;
313
+ }());
314
+ exports.SCORMAdapter = SCORMAdapter;
package/lib/index.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export * from "./ManifestGenerator";
2
+ export * from "./SCORMAdapter";
3
+ export * from "./HTMLGenerator";
4
+ export { MessageEmitter } from "./MessageHandler";
5
+ export declare const libFiles: readonly ["loadContent.js", "MessageHandler.js", "SCORMAdapter.js"];
6
+ export declare const scormVersions: readonly ["1.2", "2004 3rd Edition", "2004 4th Edition"];
7
+ export declare enum LessonStatus {
8
+ Passed = "passed",
9
+ Failed = "failed",
10
+ Completed = "completed",
11
+ Incomplete = "incomplete",
12
+ NotAttempted = "not attempted",
13
+ Browsed = "browsed"
14
+ }
package/lib/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.LessonStatus = exports.scormVersions = exports.libFiles = exports.MessageEmitter = void 0;
14
+ __exportStar(require("./ManifestGenerator"), exports);
15
+ __exportStar(require("./SCORMAdapter"), exports);
16
+ __exportStar(require("./HTMLGenerator"), exports);
17
+ var MessageHandler_1 = require("./MessageHandler");
18
+ Object.defineProperty(exports, "MessageEmitter", { enumerable: true, get: function () { return MessageHandler_1.MessageEmitter; } });
19
+ exports.libFiles = [
20
+ "loadContent.js",
21
+ "MessageHandler.js",
22
+ "SCORMAdapter.js",
23
+ ];
24
+ exports.scormVersions = [
25
+ "1.2",
26
+ "2004 3rd Edition",
27
+ "2004 4th Edition",
28
+ ];
29
+ var LessonStatus;
30
+ (function (LessonStatus) {
31
+ LessonStatus["Passed"] = "passed";
32
+ LessonStatus["Failed"] = "failed";
33
+ LessonStatus["Completed"] = "completed";
34
+ LessonStatus["Incomplete"] = "incomplete";
35
+ LessonStatus["NotAttempted"] = "not attempted";
36
+ LessonStatus["Browsed"] = "browsed";
37
+ })(LessonStatus = exports.LessonStatus || (exports.LessonStatus = {}));
@@ -0,0 +1 @@
1
+ declare function loadContent(): void;
@@ -0,0 +1,129 @@
1
+ function loadContent() {
2
+ var _this = this;
3
+ var messages = {
4
+ en: {
5
+ pageTitle: "Your content is loading...",
6
+ pageSubtitle: "Please wait, or if your content doesn't appear, try closing and opening this window again.",
7
+ pageErrorMessagesTitle: "If the initialization fails, error messages will appear below:",
8
+ 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>.',
9
+ apiNotFound: "<p>We were not able to contact your LMS: please close this window and try again later.</p>",
10
+ couldNotInitialize: "<p>We were not able to initialize the connection with your LMS: please close this window and try again later.</p>",
11
+ learnerIdMissing: "<p>We could not get your learner ID from the LMS: please close this window and try again later.</p>",
12
+ sourceUrlMissing: "<p>We could find the address of the remote resource: it looks like this module is invalid, please contact your LMS administrator.</p>",
13
+ runtimeErrorTitle: "An error occurred:",
14
+ commitFailed: "The intermediate recording could not succeed. Please close the window and try again later, or contact your administrator if the problem keeps occurring.",
15
+ },
16
+ fr: {
17
+ pageTitle: "Votre contenu est en cours de chargement...",
18
+ pageSubtitle: "Merci de patienter&nbsp;; si votre contenu ne se charge pas, veuillez essayer de fermer et d'ouvrir cette fenêtre à nouveau.",
19
+ pageErrorMessagesTitle: "Si l'initialisation échoue, les messages d'erreur apparaîtront ci-dessous&nbsp;:",
20
+ 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>.',
21
+ apiNotFound: "<p>Nous n'avons pas pu contacter votre LMS&nbsp;: veuillez fermer cette fenêtre et réessayer plus tard.</p>",
22
+ 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>",
23
+ 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>",
24
+ 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>",
25
+ runtimeErrorTitle: "Une erreur s'est produite&nbsp;:",
26
+ 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.",
27
+ },
28
+ };
29
+ var localizeMessage = function (message) {
30
+ var locale = navigator.language || navigator.userLanguage;
31
+ if (locale)
32
+ locale = locale.split(/[_-]/)[0];
33
+ if (!messages.hasOwnProperty(locale))
34
+ locale = "en";
35
+ var localizedMessages = messages[locale];
36
+ return localizedMessages.hasOwnProperty(message)
37
+ ? localizedMessages[message]
38
+ : message;
39
+ };
40
+ document.getElementById("title").innerHTML = localizeMessage("pageTitle");
41
+ document.getElementById("subtitle").innerHTML =
42
+ localizeMessage("pageSubtitle");
43
+ document.getElementById("footer-content").innerHTML =
44
+ localizeMessage("pageFooter");
45
+ document.getElementById("title-error-messages").innerHTML = localizeMessage("pageErrorMessagesTitle");
46
+ var displayInitError = function (message) {
47
+ var messagesContainer = document.getElementsByClassName("messages");
48
+ var newMessage = document.createElement("p");
49
+ newMessage.innerHTML = localizeMessage(message);
50
+ messagesContainer.length && messagesContainer[0].appendChild(newMessage);
51
+ };
52
+ var displayRuntimeError = function () {
53
+ var errorContainer = document.getElementById("runtime-error");
54
+ if (!(arguments && arguments.length)) {
55
+ errorContainer.innerHTML = "";
56
+ return;
57
+ }
58
+ errorContainer.innerHTML =
59
+ "<h6>" + localizeMessage("runtimeErrorTitle") + "</h6>";
60
+ for (var i = 0; i < arguments.length; i++) {
61
+ if (!arguments[i])
62
+ continue;
63
+ var thisError = document.createElement("p");
64
+ thisError.innerHTML = localizeMessage(arguments[i]);
65
+ errorContainer.appendChild(thisError);
66
+ }
67
+ // Remove the messages after 6 seconds
68
+ setTimeout(function () {
69
+ errorContainer.innerHTML = "";
70
+ }, 6000);
71
+ };
72
+ // var ADAPTER = new SCORMAdapter(displayRuntimeError);
73
+ // if (!ADAPTER.foundAPI) {
74
+ // displayInitError("apiNotFound");
75
+ // return;
76
+ // }
77
+ // if (!ADAPTER.LMSInitialize()) {
78
+ // displayInitError("couldNotInitialize");
79
+ // return;
80
+ // }
81
+ // var lessonStatus = ADAPTER.getLessonStatus();
82
+ // if (lessonStatus === "not attempted") {
83
+ // ADAPTER.setLessonStatus("incomplete");
84
+ // }
85
+ // var sourceUrl = document.body.getAttribute("data-source");
86
+ // if (!sourceUrl) {
87
+ // displayInitError("sourceUrlMissing");
88
+ // return;
89
+ // }
90
+ // var learnerId = ADAPTER.getLearnerId();
91
+ // if (learnerId == null) {
92
+ // displayInitError("learnerIdMissing");
93
+ // return;
94
+ // }
95
+ var url = new URL(sourceUrl);
96
+ url.searchParams.append("scorm", true);
97
+ url.searchParams.append("learner_id", learnerId);
98
+ url.searchParams.append("lms_origin", encodeURIComponent(location.origin));
99
+ // url.searchParams.append("data_from_lms", ADAPTER.getDataFromLMS());
100
+ var iframe = document.createElement("iframe");
101
+ iframe.setAttribute("frameborder", "0");
102
+ iframe.setAttribute("height", "100%");
103
+ iframe.setAttribute("width", "100%");
104
+ var wrapper = document.getElementById("wrapper");
105
+ var xhr = new XMLHttpRequest();
106
+ xhr.open("GET", url.toString());
107
+ xhr.onreadystatechange = function () {
108
+ if (_this.readyState === _this.DONE && _this.status === 200) {
109
+ iframe.setAttribute("src", url.toString());
110
+ document.body.insertBefore(iframe, wrapper);
111
+ }
112
+ };
113
+ xhr.responseType = "blob";
114
+ xhr.setRequestHeader("Authorization", "Bearer " + token);
115
+ xhr.send();
116
+ var sessionStart = new Date();
117
+ var host = url.host;
118
+ // The `host` variable may or may not contain the port number depending on the browser.
119
+ // We remove it if it wasnt' explicitly set.
120
+ if (host.indexOf(":") > -1 &&
121
+ sourceUrl.indexOf(host) !== url.protocol.length + 2) {
122
+ host = host.slice(0, host.indexOf(":"));
123
+ }
124
+ var sourceOrigin = url.protocol + "//" + host;
125
+ // new MessageReceiver(window, sourceOrigin, ADAPTER);
126
+ // window.addEventListener("beforeunload", function (e) {
127
+ // ADAPTER.LMSTerminate();
128
+ // });
129
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@didask/scol-r",
3
- "version": "3.0.0-beta.1",
3
+ "version": "3.0.0-beta.2",
4
4
  "description": "Shareable Cross-Origin Learning Resources",
5
5
  "main": "index.html",
6
6
  "types": "lib/index.d.ts",