scorm-again
Version:
A modern SCORM JavaScript run-time library for AICC, SCORM 1.2, and SCORM 2004
1,330 lines (1,098 loc) • 246 kB
JavaScript
/******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/lodash.debounce/index.js":
/*!***********************************************!*\
!*** ./node_modules/lodash.debounce/index.js ***!
\***********************************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
/**
* lodash (Custom Build) <https://lodash.com/>
* Build: `lodash modularize exports="npm" -o ./`
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
/** Used as the `TypeError` message for "Functions" methods. */
var FUNC_ERROR_TEXT = 'Expected a function';
/** Used as references for various `Number` constants. */
var NAN = 0 / 0;
/** `Object#toString` result references. */
var symbolTag = '[object Symbol]';
/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Built-in method references without a dependency on `root`. */
var freeParseInt = parseInt;
/** Detect free variable `global` from Node.js. */
var freeGlobal = (typeof __webpack_require__.g === "undefined" ? "undefined" : _typeof(__webpack_require__.g)) == 'object' && __webpack_require__.g && __webpack_require__.g.Object === Object && __webpack_require__.g;
/** Detect free variable `self`. */
var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Used for built-in method references. */
var objectProto = Object.prototype;
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var objectToString = objectProto.toString;
/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Date
* @returns {number} Returns the timestamp.
* @example
*
* _.defer(function(stamp) {
* console.log(_.now() - stamp);
* }, _.now());
* // => Logs the number of milliseconds it took for the deferred invocation.
*/
var now = function now() {
return root.Date.now();
};
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. The debounced function comes with a `cancel` method to cancel
* delayed `func` invocations and a `flush` method to immediately invoke them.
* Provide `options` to indicate whether `func` should be invoked on the
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
* with the last arguments provided to the debounced function. Subsequent
* calls to the debounced function return the result of the last `func`
* invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to debounce.
* @param {number} [wait=0] The number of milliseconds to delay.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=false]
* Specify invoking on the leading edge of the timeout.
* @param {number} [options.maxWait]
* The maximum time `func` is allowed to be delayed before it's invoked.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // Avoid costly calculations while the window size is in flux.
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
* jQuery(element).on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
* var source = new EventSource('/stream');
* jQuery(source).on('message', debounced);
*
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
result,
timerId,
lastCallTime,
lastInvokeTime = 0,
leading = false,
maxing = false,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs,
thisArg = lastThis;
lastArgs = lastThis = undefined;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time; // Start the timer for the trailing edge.
timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime,
result = wait - timeSinceLastCall;
return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
} // Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined;
return result;
}
function cancel() {
if (timerId !== undefined) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined;
}
function flush() {
return timerId === undefined ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/
function isObject(value) {
var type = _typeof(value);
return !!value && (type == 'object' || type == 'function');
}
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return !!value && _typeof(value) == 'object';
}
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/
function isSymbol(value) {
return _typeof(value) == 'symbol' || isObjectLike(value) && objectToString.call(value) == symbolTag;
}
/**
* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? other + '' : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
var isBinary = reIsBinary.test(value);
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}
module.exports = debounce;
/***/ }),
/***/ "./src/AICC.js":
/*!*********************!*\
!*** ./src/AICC.js ***!
\*********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": function() { return /* binding */ AICC; }
/* harmony export */ });
/* harmony import */ var _Scorm12API__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Scorm12API */ "./src/Scorm12API.js");
/* harmony import */ var _cmi_aicc_cmi__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./cmi/aicc_cmi */ "./src/cmi/aicc_cmi.js");
/* harmony import */ var _cmi_scorm12_cmi__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./cmi/scorm12_cmi */ "./src/cmi/scorm12_cmi.js");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
/**
* The AICC API class
*/
var AICC = /*#__PURE__*/function (_Scorm12API) {
_inherits(AICC, _Scorm12API);
var _super = _createSuper(AICC);
/**
* Constructor to create AICC API object
* @param {object} settings
*/
function AICC(settings) {
var _this;
_classCallCheck(this, AICC);
var finalSettings = _objectSpread(_objectSpread({}, {
mastery_override: false
}), settings);
_this = _super.call(this, finalSettings);
_this.cmi = new _cmi_aicc_cmi__WEBPACK_IMPORTED_MODULE_1__.CMI();
_this.nav = new _cmi_scorm12_cmi__WEBPACK_IMPORTED_MODULE_2__.NAV();
return _this;
}
/**
* Gets or builds a new child element to add to the array.
*
* @param {string} CMIElement
* @param {any} value
* @param {boolean} foundFirstIndex
* @return {object}
*/
_createClass(AICC, [{
key: "getChildElement",
value: function getChildElement(CMIElement, value, foundFirstIndex) {
var newChild = _get(_getPrototypeOf(AICC.prototype), "getChildElement", this).call(this, CMIElement, value, foundFirstIndex);
if (!newChild) {
if (this.stringMatches(CMIElement, 'cmi\\.evaluation\\.comments\\.\\d+')) {
newChild = new _cmi_aicc_cmi__WEBPACK_IMPORTED_MODULE_1__.CMIEvaluationCommentsObject();
} else if (this.stringMatches(CMIElement, 'cmi\\.student_data\\.tries\\.\\d+')) {
newChild = new _cmi_aicc_cmi__WEBPACK_IMPORTED_MODULE_1__.CMITriesObject();
} else if (this.stringMatches(CMIElement, 'cmi\\.student_data\\.attempt_records\\.\\d+')) {
newChild = new _cmi_aicc_cmi__WEBPACK_IMPORTED_MODULE_1__.CMIAttemptRecordsObject();
}
}
return newChild;
}
/**
* Replace the whole API with another
*
* @param {AICC} newAPI
*/
}, {
key: "replaceWithAnotherScormAPI",
value: function replaceWithAnotherScormAPI(newAPI) {
// Data Model
this.cmi = newAPI.cmi;
this.nav = newAPI.nav;
}
}]);
return AICC;
}(_Scorm12API__WEBPACK_IMPORTED_MODULE_0__["default"]);
/***/ }),
/***/ "./src/BaseAPI.js":
/*!************************!*\
!*** ./src/BaseAPI.js ***!
\************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": function() { return /* binding */ BaseAPI; }
/* harmony export */ });
/* harmony import */ var _cmi_common__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./cmi/common */ "./src/cmi/common.js");
/* harmony import */ var _exceptions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./exceptions */ "./src/exceptions.js");
/* harmony import */ var _constants_error_codes__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./constants/error_codes */ "./src/constants/error_codes.js");
/* harmony import */ var _constants_api_constants__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./constants/api_constants */ "./src/constants/api_constants.js");
/* harmony import */ var _utilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utilities */ "./src/utilities.js");
/* harmony import */ var lodash_debounce__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! lodash.debounce */ "./node_modules/lodash.debounce/index.js");
/* harmony import */ var lodash_debounce__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(lodash_debounce__WEBPACK_IMPORTED_MODULE_5__);
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
var global_constants = _constants_api_constants__WEBPACK_IMPORTED_MODULE_3__["default"].global;
var scorm12_error_codes = _constants_error_codes__WEBPACK_IMPORTED_MODULE_2__["default"].scorm12;
/**
* Base API class for AICC, SCORM 1.2, and SCORM 2004. Should be considered
* abstract, and never initialized on it's own.
*/
var _timeout = /*#__PURE__*/new WeakMap();
var _error_codes = /*#__PURE__*/new WeakMap();
var _settings = /*#__PURE__*/new WeakMap();
var BaseAPI = /*#__PURE__*/function () {
/**
* Constructor for Base API class. Sets some shared API fields, as well as
* sets up options for the API.
* @param {object} error_codes
* @param {object} settings
*/
function BaseAPI(error_codes, settings) {
_classCallCheck(this, BaseAPI);
_classPrivateFieldInitSpec(this, _timeout, {
writable: true,
value: void 0
});
_classPrivateFieldInitSpec(this, _error_codes, {
writable: true,
value: void 0
});
_classPrivateFieldInitSpec(this, _settings, {
writable: true,
value: {
autocommit: false,
autocommitSeconds: 10,
asyncCommit: false,
sendBeaconCommit: false,
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,
selfReportSessionTime: false,
alwaysSendTotalTime: false,
strict_errors: true,
xhrHeaders: {},
xhrWithCredentials: false,
responseHandler: function responseHandler(xhr) {
var result;
if (typeof xhr !== 'undefined') {
result = JSON.parse(xhr.responseText);
if (result === null || !{}.hasOwnProperty.call(result, 'result')) {
result = {};
if (xhr.status === 200) {
result.result = global_constants.SCORM_TRUE;
result.errorCode = 0;
} else {
result.result = global_constants.SCORM_FALSE;
result.errorCode = 101;
}
}
}
return result;
},
requestHandler: function requestHandler(commitObject) {
return commitObject;
},
onLogMessage: function onLogMessage(messageLevel, logMessage) {
switch (messageLevel) {
case global_constants.LOG_LEVEL_ERROR:
console.error(logMessage);
break;
case global_constants.LOG_LEVEL_WARNING:
console.warn(logMessage);
break;
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;
}
}
}
});
_defineProperty(this, "cmi", void 0);
_defineProperty(this, "startingData", void 0);
if ((this instanceof BaseAPI ? this.constructor : void 0) === BaseAPI) {
throw new TypeError('Cannot construct BaseAPI instances directly');
}
this.currentState = global_constants.STATE_NOT_INITIALIZED;
this.lastErrorCode = 0;
this.listenerArray = [];
_classPrivateFieldSet(this, _timeout, null);
_classPrivateFieldSet(this, _error_codes, error_codes);
this.settings = settings;
this.apiLogLevel = this.settings.logLevel;
this.selfReportSessionTime = this.settings.selfReportSessionTime;
}
/**
* Initialize the API
* @param {string} callbackName
* @param {string} initializeMessage
* @param {string} terminationMessage
* @return {string}
*/
_createClass(BaseAPI, [{
key: "initialize",
value: function initialize(callbackName, initializeMessage, terminationMessage) {
var returnValue = global_constants.SCORM_FALSE;
if (this.isInitialized()) {
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).INITIALIZED, initializeMessage);
} else if (this.isTerminated()) {
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).TERMINATED, terminationMessage);
} else {
if (this.selfReportSessionTime) {
this.cmi.setStartTime();
}
this.currentState = global_constants.STATE_INITIALIZED;
this.lastErrorCode = 0;
returnValue = global_constants.SCORM_TRUE;
this.processListeners(callbackName);
}
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
this.clearSCORMError(returnValue);
return returnValue;
}
/**
* Getter for #error_codes
* @return {object}
*/
}, {
key: "error_codes",
get: function get() {
return _classPrivateFieldGet(this, _error_codes);
}
/**
* Getter for #settings
* @return {object}
*/
}, {
key: "settings",
get: function get() {
return _classPrivateFieldGet(this, _settings);
}
/**
* Setter for #settings
* @param {object} settings
*/
,
set: function set(settings) {
_classPrivateFieldSet(this, _settings, _objectSpread(_objectSpread({}, _classPrivateFieldGet(this, _settings)), settings));
}
/**
* Terminates the current run of the API
* @param {string} callbackName
* @param {boolean} checkTerminated
* @return {string}
*/
}, {
key: "terminate",
value: function terminate(callbackName, checkTerminated) {
var returnValue = global_constants.SCORM_FALSE;
if (this.checkState(checkTerminated, _classPrivateFieldGet(this, _error_codes).TERMINATION_BEFORE_INIT, _classPrivateFieldGet(this, _error_codes).MULTIPLE_TERMINATION)) {
this.currentState = global_constants.STATE_TERMINATED;
var result = this.storeData(true);
if (!this.settings.sendBeaconCommit && !this.settings.asyncCommit && typeof result.errorCode !== 'undefined' && result.errorCode > 0) {
this.throwSCORMError(result.errorCode);
}
returnValue = typeof result !== 'undefined' && result.result ? result.result : global_constants.SCORM_FALSE;
if (checkTerminated) this.lastErrorCode = 0;
returnValue = global_constants.SCORM_TRUE;
this.processListeners(callbackName);
}
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
this.clearSCORMError(returnValue);
return returnValue;
}
/**
* Get the value of the CMIElement.
*
* @param {string} callbackName
* @param {boolean} checkTerminated
* @param {string} CMIElement
* @return {string}
*/
}, {
key: "getValue",
value: function getValue(callbackName, checkTerminated, CMIElement) {
var returnValue;
if (this.checkState(checkTerminated, _classPrivateFieldGet(this, _error_codes).RETRIEVE_BEFORE_INIT, _classPrivateFieldGet(this, _error_codes).RETRIEVE_AFTER_TERM)) {
if (checkTerminated) this.lastErrorCode = 0;
try {
returnValue = this.getCMIValue(CMIElement);
} catch (e) {
if (e instanceof _exceptions__WEBPACK_IMPORTED_MODULE_1__.ValidationError) {
this.lastErrorCode = e.errorCode;
returnValue = global_constants.SCORM_FALSE;
} else {
if (e.message) {
console.error(e.message);
} else {
console.error(e);
}
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).GENERAL);
}
}
this.processListeners(callbackName, CMIElement);
}
this.apiLog(callbackName, CMIElement, ': returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
this.clearSCORMError(returnValue);
return returnValue;
}
/**
* Sets the value of the CMIElement.
*
* @param {string} callbackName
* @param {string} commitCallback
* @param {boolean} checkTerminated
* @param {string} CMIElement
* @param {*} value
* @return {string}
*/
}, {
key: "setValue",
value: function setValue(callbackName, commitCallback, checkTerminated, CMIElement, value) {
if (value !== undefined) {
value = String(value);
}
var returnValue = global_constants.SCORM_FALSE;
if (this.checkState(checkTerminated, _classPrivateFieldGet(this, _error_codes).STORE_BEFORE_INIT, _classPrivateFieldGet(this, _error_codes).STORE_AFTER_TERM)) {
if (checkTerminated) this.lastErrorCode = 0;
try {
returnValue = this.setCMIValue(CMIElement, value);
} catch (e) {
if (e instanceof _exceptions__WEBPACK_IMPORTED_MODULE_1__.ValidationError) {
this.lastErrorCode = e.errorCode;
returnValue = global_constants.SCORM_FALSE;
} else {
if (e.message) {
console.error(e.message);
} else {
console.error(e);
}
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).GENERAL);
}
}
this.processListeners(callbackName, CMIElement, value);
}
if (returnValue === undefined) {
returnValue = global_constants.SCORM_FALSE;
} // 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 && !_classPrivateFieldGet(this, _timeout)) {
this.scheduleCommit(this.settings.autocommitSeconds * 1000, commitCallback);
}
}
this.apiLog(callbackName, CMIElement, ': ' + value + ': result: ' + returnValue, global_constants.LOG_LEVEL_INFO);
this.clearSCORMError(returnValue);
return returnValue;
}
/**
* Orders LMS to store all content parameters
* @param {string} callbackName
* @param {boolean} checkTerminated
* @return {string}
*/
}, {
key: "commit",
value: function commit(callbackName, checkTerminated) {
this.clearScheduledCommit();
var returnValue = global_constants.SCORM_FALSE;
if (this.checkState(checkTerminated, _classPrivateFieldGet(this, _error_codes).COMMIT_BEFORE_INIT, _classPrivateFieldGet(this, _error_codes).COMMIT_AFTER_TERM)) {
var result = this.storeData(false);
if (!this.settings.sendBeaconCommit && !this.settings.asyncCommit && result.errorCode && result.errorCode > 0) {
this.throwSCORMError(result.errorCode);
}
returnValue = typeof result !== 'undefined' && result.result ? result.result : global_constants.SCORM_FALSE;
this.apiLog(callbackName, 'HttpRequest', ' Result: ' + returnValue, global_constants.LOG_LEVEL_DEBUG);
if (checkTerminated) this.lastErrorCode = 0;
this.processListeners(callbackName);
}
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
this.clearSCORMError(returnValue);
return returnValue;
}
/**
* Returns last error code
* @param {string} callbackName
* @return {string}
*/
}, {
key: "getLastError",
value: function getLastError(callbackName) {
var returnValue = String(this.lastErrorCode);
this.processListeners(callbackName);
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
return returnValue;
}
/**
* Returns the errorNumber error description
*
* @param {string} callbackName
* @param {(string|number)} CMIErrorCode
* @return {string}
*/
}, {
key: "getErrorString",
value: function getErrorString(callbackName, CMIErrorCode) {
var returnValue = '';
if (CMIErrorCode !== null && CMIErrorCode !== '') {
returnValue = this.getLmsErrorMessageDetails(CMIErrorCode);
this.processListeners(callbackName);
}
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
return returnValue;
}
/**
* Returns a comprehensive description of the errorNumber error.
*
* @param {string} callbackName
* @param {(string|number)} CMIErrorCode
* @return {string}
*/
}, {
key: "getDiagnostic",
value: function getDiagnostic(callbackName, CMIErrorCode) {
var returnValue = '';
if (CMIErrorCode !== null && CMIErrorCode !== '') {
returnValue = this.getLmsErrorMessageDetails(CMIErrorCode, true);
this.processListeners(callbackName);
}
this.apiLog(callbackName, null, 'returned: ' + returnValue, global_constants.LOG_LEVEL_INFO);
return returnValue;
}
/**
* Checks the LMS state and ensures it has been initialized.
*
* @param {boolean} checkTerminated
* @param {number} beforeInitError
* @param {number} afterTermError
* @return {boolean}
*/
}, {
key: "checkState",
value: function checkState(checkTerminated, beforeInitError, afterTermError) {
if (this.isNotInitialized()) {
this.throwSCORMError(beforeInitError);
return false;
} else if (checkTerminated && this.isTerminated()) {
this.throwSCORMError(afterTermError);
return false;
}
return true;
}
/**
* Logging for all SCORM actions
*
* @param {string} functionName
* @param {string} CMIElement
* @param {string} logMessage
* @param {number}messageLevel
*/
}, {
key: "apiLog",
value: function apiLog(functionName, CMIElement, logMessage, messageLevel) {
logMessage = this.formatMessage(functionName, CMIElement, logMessage);
if (messageLevel >= this.apiLogLevel) {
this.settings.onLogMessage(messageLevel, logMessage);
}
}
/**
* Formats the SCORM messages for easy reading
*
* @param {string} functionName
* @param {string} CMIElement
* @param {string} message
* @return {string}
*/
}, {
key: "formatMessage",
value: function formatMessage(functionName, CMIElement, message) {
var baseLength = 20;
var messageString = '';
messageString += functionName;
var fillChars = baseLength - messageString.length;
for (var i = 0; i < fillChars; i++) {
messageString += ' ';
}
messageString += ': ';
if (CMIElement) {
var CMIElementBaseLength = 70;
messageString += CMIElement;
fillChars = CMIElementBaseLength - messageString.length;
for (var j = 0; j < fillChars; j++) {
messageString += ' ';
}
}
if (message) {
messageString += message;
}
return messageString;
}
/**
* Checks to see if {str} contains {tester}
*
* @param {string} str String to check against
* @param {string} tester String to check for
* @return {boolean}
*/
}, {
key: "stringMatches",
value: function stringMatches(str, tester) {
return str && tester && str.match(tester);
}
/**
* Check to see if the specific object has the given property
* @param {*} refObject
* @param {string} attribute
* @return {boolean}
* @private
*/
}, {
key: "_checkObjectHasProperty",
value: function _checkObjectHasProperty(refObject, attribute) {
return Object.hasOwnProperty.call(refObject, attribute) || Object.getOwnPropertyDescriptor(Object.getPrototypeOf(refObject), attribute) || attribute in refObject;
}
/**
* Returns the message that corresponds to errorNumber
* APIs that inherit BaseAPI should override this function
*
* @param {(string|number)} _errorNumber
* @param {boolean} _detail
* @return {string}
* @abstract
*/
}, {
key: "getLmsErrorMessageDetails",
value: function getLmsErrorMessageDetails(_errorNumber, _detail) {
throw new Error('The getLmsErrorMessageDetails method has not been implemented');
}
/**
* Gets the value for the specific element.
* APIs that inherit BaseAPI should override this function
*
* @param {string} _CMIElement
* @return {string}
* @abstract
*/
}, {
key: "getCMIValue",
value: function getCMIValue(_CMIElement) {
throw new Error('The getCMIValue method has not been implemented');
}
/**
* Sets the value for the specific element.
* APIs that inherit BaseAPI should override this function
*
* @param {string} _CMIElement
* @param {any} _value
* @return {string}
* @abstract
*/
}, {
key: "setCMIValue",
value: function setCMIValue(_CMIElement, _value) {
throw new Error('The setCMIValue method has not been implemented');
}
/**
* Shared API method to set a valid for a given element.
*
* @param {string} methodName
* @param {boolean} scorm2004
* @param {string} CMIElement
* @param {*} value
* @return {string}
*/
}, {
key: "_commonSetCMIValue",
value: function _commonSetCMIValue(methodName, scorm2004, CMIElement, value) {
if (!CMIElement || CMIElement === '') {
return global_constants.SCORM_FALSE;
}
var structure = CMIElement.split('.');
var refObject = this;
var returnValue = global_constants.SCORM_FALSE;
var foundFirstIndex = false;
var invalidErrorMessage = "The data model element passed to ".concat(methodName, " (").concat(CMIElement, ") is not a valid SCORM data model element.");
var invalidErrorCode = scorm2004 ? _classPrivateFieldGet(this, _error_codes).UNDEFINED_DATA_MODEL : _classPrivateFieldGet(this, _error_codes).GENERAL;
for (var i = 0; i < structure.length; i++) {
var attribute = structure[i];
if (i === structure.length - 1) {
if (scorm2004 && attribute.substr(0, 8) === '{target=' && typeof refObject._isTargetValid == 'function') {
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).READ_ONLY_ELEMENT);
} else if (!this._checkObjectHasProperty(refObject, attribute)) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
} else {
if (this.isInitialized() && this.stringMatches(CMIElement, '\\.correct_responses\\.\\d+')) {
this.validateCorrectResponse(CMIElement, value);
}
if (!scorm2004 || this.lastErrorCode === 0) {
refObject[attribute] = value;
returnValue = global_constants.SCORM_TRUE;
}
}
} else {
refObject = refObject[attribute];
if (!refObject) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
break;
}
if (refObject instanceof _cmi_common__WEBPACK_IMPORTED_MODULE_0__.CMIArray) {
var index = parseInt(structure[i + 1], 10); // SCO is trying to set an item on an array
if (!isNaN(index)) {
var item = refObject.childArray[index];
if (item) {
refObject = item;
foundFirstIndex = true;
} else {
var newChild = this.getChildElement(CMIElement, value, foundFirstIndex);
foundFirstIndex = true;
if (!newChild) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
} else {
if (refObject.initialized) newChild.initialize();
refObject.childArray.push(newChild);
refObject = newChild;
}
} // Have to update i value to skip the array position
i++;
}
}
}
}
if (returnValue === global_constants.SCORM_FALSE) {
this.apiLog(methodName, null, "There was an error setting the value for: ".concat(CMIElement, ", value of: ").concat(value), global_constants.LOG_LEVEL_WARNING);
}
return returnValue;
}
/**
* Abstract method for validating that a response is correct.
*
* @param {string} _CMIElement
* @param {*} _value
*/
}, {
key: "validateCorrectResponse",
value: function validateCorrectResponse(_CMIElement, _value) {// just a stub method
}
/**
* Gets or builds a new child element to add to the array.
* APIs that inherit BaseAPI should override this method.
*
* @param {string} _CMIElement - unused
* @param {*} _value - unused
* @param {boolean} _foundFirstIndex - unused
* @return {*}
* @abstract
*/
}, {
key: "getChildElement",
value: function getChildElement(_CMIElement, _value, _foundFirstIndex) {
throw new Error('The getChildElement method has not been implemented');
}
/**
* Gets a value from the CMI Object
*
* @param {string} methodName
* @param {boolean} scorm2004
* @param {string} CMIElement
* @return {*}
*/
}, {
key: "_commonGetCMIValue",
value: function _commonGetCMIValue(methodName, scorm2004, CMIElement) {
if (!CMIElement || CMIElement === '') {
return '';
}
var structure = CMIElement.split('.');
var refObject = this;
var attribute = null;
var uninitializedErrorMessage = "The data model element passed to ".concat(methodName, " (").concat(CMIElement, ") has not been initialized.");
var invalidErrorMessage = "The data model element passed to ".concat(methodName, " (").concat(CMIElement, ") is not a valid SCORM data model element.");
var invalidErrorCode = scorm2004 ? _classPrivateFieldGet(this, _error_codes).UNDEFINED_DATA_MODEL : _classPrivateFieldGet(this, _error_codes).GENERAL;
for (var i = 0; i < structure.length; i++) {
attribute = structure[i];
if (!scorm2004) {
if (i === structure.length - 1) {
if (!this._checkObjectHasProperty(refObject, attribute)) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
return;
}
}
} else {
if (String(attribute).substr(0, 8) === '{target=' && typeof refObject._isTargetValid == 'function') {
var target = String(attribute).substr(8, String(attribute).length - 9);
return refObject._isTargetValid(target);
} else if (!this._checkObjectHasProperty(refObject, attribute)) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
return;
}
}
refObject = refObject[attribute];
if (refObject === undefined) {
this.throwSCORMError(invalidErrorCode, invalidErrorMessage);
break;
}
if (refObject instanceof _cmi_common__WEBPACK_IMPORTED_MODULE_0__.CMIArray) {
var index = parseInt(structure[i + 1], 10); // SCO is trying to set an item on an array
if (!isNaN(index)) {
var item = refObject.childArray[index];
if (item) {
refObject = item;
} else {
this.throwSCORMError(_classPrivateFieldGet(this, _error_codes).VALUE_NOT_INITIALIZED, uninitializedErrorMessage);
break;
} // Have to update i value to skip the array position
i++;
}
}
}
if (refObject === null || refObject === undefined) {
if (!scorm2004) {
if (attribute === '_children') {
this.throwSCORMError(scorm12_error_codes.CHILDREN_ERROR);
} else if (attribute === '_count') {
this.throwSCORMError(scorm12_error_codes.COUNT_ERROR);
}
}
} else {