This commit is contained in:
Jonathan Putney
2019-12-20 14:37:43 -05:00
13 changed files with 3446 additions and 3889 deletions

5073
dist/scorm-again.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

219
package-lock.json generated
View File

@@ -39,18 +39,18 @@
}
},
"@babel/core": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz",
"integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==",
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz",
"integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.5.5",
"@babel/generator": "^7.7.2",
"@babel/helpers": "^7.7.0",
"@babel/parser": "^7.7.2",
"@babel/template": "^7.7.0",
"@babel/traverse": "^7.7.2",
"@babel/types": "^7.7.2",
"@babel/generator": "^7.7.4",
"@babel/helpers": "^7.7.4",
"@babel/parser": "^7.7.4",
"@babel/template": "^7.7.4",
"@babel/traverse": "^7.7.4",
"@babel/types": "^7.7.4",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"json5": "^2.1.0",
@@ -60,6 +60,92 @@
"source-map": "^0.5.0"
},
"dependencies": {
"@babel/generator": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz",
"integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4",
"jsesc": "^2.5.1",
"lodash": "^4.17.13",
"source-map": "^0.5.0"
}
},
"@babel/helper-function-name": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
"integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.7.4",
"@babel/template": "^7.7.4",
"@babel/types": "^7.7.4"
}
},
"@babel/helper-get-function-arity": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
"integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
"integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4"
}
},
"@babel/parser": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz",
"integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==",
"dev": true
},
"@babel/template": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
"integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/parser": "^7.7.4",
"@babel/types": "^7.7.4"
}
},
"@babel/traverse": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
"integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.5.5",
"@babel/generator": "^7.7.4",
"@babel/helper-function-name": "^7.7.4",
"@babel/helper-split-export-declaration": "^7.7.4",
"@babel/parser": "^7.7.4",
"@babel/types": "^7.7.4",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.13"
}
},
"@babel/types": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
"integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
"dev": true,
"requires": {
"esutils": "^2.0.2",
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -306,14 +392,117 @@
}
},
"@babel/helpers": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz",
"integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==",
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz",
"integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==",
"dev": true,
"requires": {
"@babel/template": "^7.7.0",
"@babel/traverse": "^7.7.0",
"@babel/types": "^7.7.0"
"@babel/template": "^7.7.4",
"@babel/traverse": "^7.7.4",
"@babel/types": "^7.7.4"
},
"dependencies": {
"@babel/generator": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz",
"integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4",
"jsesc": "^2.5.1",
"lodash": "^4.17.13",
"source-map": "^0.5.0"
}
},
"@babel/helper-function-name": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz",
"integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.7.4",
"@babel/template": "^7.7.4",
"@babel/types": "^7.7.4"
}
},
"@babel/helper-get-function-arity": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz",
"integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz",
"integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==",
"dev": true,
"requires": {
"@babel/types": "^7.7.4"
}
},
"@babel/parser": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz",
"integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==",
"dev": true
},
"@babel/template": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz",
"integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/parser": "^7.7.4",
"@babel/types": "^7.7.4"
}
},
"@babel/traverse": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz",
"integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.5.5",
"@babel/generator": "^7.7.4",
"@babel/helper-function-name": "^7.7.4",
"@babel/helper-split-export-declaration": "^7.7.4",
"@babel/parser": "^7.7.4",
"@babel/types": "^7.7.4",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.13"
}
},
"@babel/types": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz",
"integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==",
"dev": true,
"requires": {
"esutils": "^2.0.2",
"lodash": "^4.17.13",
"to-fast-properties": "^2.0.0"
}
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"@babel/highlight": {

View File

@@ -8,7 +8,7 @@
},
"devDependencies": {
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/core": "^7.7.4",
"@babel/node": "^7.7.0",
"@babel/plugin-proposal-class-properties": "^7.7.0",
"@babel/plugin-proposal-optional-chaining": "^7.6.0",

View File

@@ -4,8 +4,8 @@ import {
CMI,
CMIEvaluationCommentsObject,
CMITriesObject,
NAV,
} from './cmi/aicc_cmi';
import {NAV} from './cmi/scorm12_cmi';
/**
* The AICC API class

View File

@@ -17,6 +17,9 @@ export default class BaseAPI {
autocommitSeconds: 60,
lmsCommitUrl: false,
dataCommitFormat: 'json', // valid formats are 'json' or 'flattened', 'params'
commitRequestDataType: 'application/json;charset=UTF-8',
autoProgress: false,
logLevel: global_constants.LOG_LEVEL_ERROR,
};
cmi;
startingData: {};
@@ -32,7 +35,6 @@ export default class BaseAPI {
throw new TypeError('Cannot construct BaseAPI instances directly');
}
this.currentState = global_constants.STATE_NOT_INITIALIZED;
this.apiLogLevel = global_constants.LOG_LEVEL_ERROR;
this.lastErrorCode = 0;
this.listenerArray = [];
@@ -40,6 +42,7 @@ export default class BaseAPI {
this.#error_codes = error_codes;
this.settings = settings;
this.apiLogLevel = this.settings.logLevel;
}
/**
@@ -103,6 +106,13 @@ export default class BaseAPI {
if (this.checkState(checkTerminated,
this.#error_codes.TERMINATION_BEFORE_INIT,
this.#error_codes.MULTIPLE_TERMINATION)) {
const result = this.storeData(true);
if (result.errorCode && result.errorCode > 0) {
this.throwSCORMError(result.errorCode);
}
returnValue = result.result ?
result.result : global_constants.SCORM_FALSE;
if (checkTerminated) this.lastErrorCode = 0;
this.currentState = global_constants.STATE_TERMINATED;
returnValue = global_constants.SCORM_TRUE;
@@ -184,8 +194,8 @@ export default class BaseAPI {
// If we didn't have any errors while setting the data, go ahead and
// schedule a commit, if autocommit is turned on
if (String(this.lastErrorCode) === '0') {
if (this.#settings.autocommit && this.#timeout === undefined) {
this.scheduleCommit(this.#settings.autocommitSeconds * 1000);
if (this.settings.autocommit && !this.#timeout) {
this.scheduleCommit(this.settings.autocommitSeconds * 1000);
}
}
@@ -341,6 +351,13 @@ export default class BaseAPI {
case global_constants.LOG_LEVEL_INFO:
console.info(logMessage);
break;
case global_constants.LOG_LEVEL_DEBUG:
if (console.debug) {
console.debug(logMessage);
} else {
console.log(logMessage);
}
break;
}
}
}
@@ -611,7 +628,7 @@ export default class BaseAPI {
}
refObject = refObject[attribute];
if (!refObject) {
if (refObject === undefined) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
break;
}
@@ -854,24 +871,32 @@ export default class BaseAPI {
* @return {object}
*/
processHttpRequest(url: String, params) {
const httpReq = new XMLHttpRequest();
httpReq.open('POST', url, false);
httpReq.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
try {
if (params instanceof Array) {
httpReq.send(params.join('&'));
} else {
httpReq.send(params);
}
} catch (e) {
return {
const genericError = {
'result': global_constants.SCORM_FALSE,
'errorCode': this.#error_codes.GENERAL,
};
const httpReq = new XMLHttpRequest();
httpReq.open('POST', url, false);
try {
if (params instanceof Array) {
httpReq.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
httpReq.send(params.join('&'));
} else {
httpReq.setRequestHeader('Content-Type',
this.settings.commitRequestDataType);
httpReq.send(JSON.stringify(params));
}
} catch (e) {
return genericError;
}
try {
return JSON.parse(httpReq.responseText);
} catch (e) {
return genericError;
}
}
/**
@@ -881,6 +906,7 @@ export default class BaseAPI {
*/
scheduleCommit(when: number) {
this.#timeout = new ScheduledCommit(this, when);
this.apiLog('scheduleCommit', '', 'scheduled', global_constants.LOG_LEVEL_DEBUG);
}
/**
@@ -890,6 +916,8 @@ export default class BaseAPI {
if (this.#timeout) {
this.#timeout.cancel();
this.#timeout = null;
this.apiLog('clearScheduledCommit', '', 'cleared',
global_constants.LOG_LEVEL_DEBUG);
}
}
}
@@ -899,7 +927,7 @@ export default class BaseAPI {
*/
class ScheduledCommit {
#API;
#cancelled: false;
#cancelled = false;
#timeout;
/**
@@ -909,7 +937,7 @@ class ScheduledCommit {
*/
constructor(API: any, when: number) {
this.#API = API;
this.#timeout = setTimeout(this.wrapper, when);
this.#timeout = setTimeout(this.wrapper.bind(this), when);
}
/**

View File

@@ -5,7 +5,7 @@ import {
CMIInteractionsCorrectResponsesObject,
CMIInteractionsObject,
CMIInteractionsObjectivesObject,
CMIObjectivesObject,
CMIObjectivesObject, NAV,
} from './cmi/scorm12_cmi';
import * as Utilities from './utilities';
import {global_constants, scorm12_constants} from './constants/api_constants';
@@ -31,6 +31,8 @@ export default class Scorm12API extends BaseAPI {
super(scorm12_error_codes, finalSettings);
this.cmi = new CMI();
this.nav = new NAV();
// Rename functions to match 1.2 Spec and expose to modules
this.LMSInitialize = this.lmsInitialize;
this.LMSFinish = this.lmsFinish;
@@ -59,7 +61,21 @@ export default class Scorm12API extends BaseAPI {
* @return {string} bool
*/
lmsFinish() {
return this.terminate('LMSFinish', false);
const result = this.terminate('LMSFinish', false);
if (result === global_constants.SCORM_TRUE) {
if (this.nav.event !== '') {
if (this.nav.event === 'continue') {
this.processListeners('SequenceNext');
} else {
this.processListeners('SequencePrevious');
}
} else if (this.settings.autoProgress) {
this.processListeners('SequenceNext');
}
}
return result;
}
/**

View File

@@ -71,7 +71,39 @@ export default class Scorm2004API extends BaseAPI {
* @return {string} bool
*/
lmsTerminate() {
return this.terminate('Terminate', true);
const result = this.terminate('Terminate', true);
if (result === global_constants.SCORM_TRUE) {
if (this.adl.nav.request !== '_none_') {
switch (this.adl.nav.request) {
case 'continue':
this.processListeners('SequenceNext');
break;
case 'previous':
this.processListeners('SequencePrevious');
break;
case 'choice':
this.processListeners('SequenceChoice');
break;
case 'exit':
this.processListeners('SequenceExit');
break;
case 'exitAll':
this.processListeners('SequenceExitAll');
break;
case 'abandon':
this.processListeners('SequenceAbandon');
break;
case 'abandonAll':
this.processListeners('SequenceAbandonAll');
break;
}
} else if (this.settings.autoProgress) {
this.processListeners('SequenceNext');
}
}
return result;
}
/**

View File

@@ -379,52 +379,3 @@ export class CMIEvaluationCommentsObject extends BaseCMI {
return result;
}
}
/**
* Class for AICC Navigation object
*/
export class NAV extends BaseCMI {
/**
* Constructor for NAV object
*/
constructor() {
super();
}
#event = '';
/**
* Getter for #event
* @return {string}
*/
get event() {
return (!this.jsonString) ? throwWriteOnlyError() : this.#event;
}
/**
* Setter for #event
* @param {string} event
*/
set event(event) {
if (check12ValidFormat(event, regex.NAVEvent)) {
this.#event = event;
}
}
/**
* toJSON for nav object
* @return {
* {
* event: string
* }
* }
*/
toJSON() {
this.jsonString = true;
const result = {
'event': this.event,
};
delete this.jsonString;
return result;
}
}

View File

@@ -1205,3 +1205,52 @@ export class CMIInteractionsCorrectResponsesObject extends BaseCMI {
return result;
}
}
/**
* Class for AICC Navigation object
*/
export class NAV extends BaseCMI {
/**
* Constructor for NAV object
*/
constructor() {
super();
}
#event = '';
/**
* Getter for #event
* @return {string}
*/
get event() {
return (!this.jsonString) ? throwWriteOnlyError() : this.#event;
}
/**
* Setter for #event
* @param {string} event
*/
set event(event) {
if (check12ValidFormat(event, regex.NAVEvent)) {
this.#event = event;
}
}
/**
* toJSON for nav object
* @return {
* {
* event: string
* }
* }
*/
toJSON() {
this.jsonString = true;
const result = {
'event': this.event,
};
delete this.jsonString;
return result;
}
}

View File

@@ -428,7 +428,7 @@ export class CMI extends BaseCMI {
* @param {string} suspend_data
*/
set suspend_data(suspend_data) {
if (check2004ValidFormat(suspend_data, regex.CMIString64000)) {
if (check2004ValidFormat(suspend_data, regex.CMIString64000, true)) {
this.#suspend_data = suspend_data;
}
}

View File

@@ -4,12 +4,13 @@ import {scorm12_error_codes} from '../../src/constants/error_codes';
import {
CMI,
CMIEvaluationCommentsObject,
CMITriesObject, NAV,
CMITriesObject,
} from '../../src/cmi/aicc_cmi';
import * as h from '../cmi_helpers';
import {
CMIInteractionsObject,
CMIObjectivesObject,
NAV,
} from '../../src/cmi/scorm12_cmi';
import {expect} from 'chai';
import {scorm12_values} from '../../src/constants/field_values';