diff --git a/js/h5p-content-upgrade.js b/js/h5p-content-upgrade.js index bbea037..5be3428 100644 --- a/js/h5p-content-upgrade.js +++ b/js/h5p-content-upgrade.js @@ -2,18 +2,18 @@ var H5PUpgrades = H5PUpgrades || {}; (function ($) { var info, $container, librariesCache = {}; - + // Initialize $(document).ready(function () { // Get library info info = H5PIntegration.getLibraryInfo(); - + // Get and reset container $container = $('#h5p-admin-container').html('
' + info.message + '
'); - + // Make it possible to select version var $version = $(getVersionSelect(info.versions)).appendTo($container); - + // Add "go" button $('', { class: 'h5p-admin-upgrade-button', @@ -23,11 +23,11 @@ var H5PUpgrades = H5PUpgrades || {}; new ContentUpgrade($version.val()); } }).appendTo($container); - }); + }); /** * Generate html for version select. - * + * * @param {Object} versions * @returns {String} */ @@ -41,18 +41,18 @@ var H5PUpgrades = H5PUpgrades || {}; return html; } }; - + /** * Private. Helps process each property on the given object asynchronously in serial order. - * + * * @param {Object} obj * @param {Function} process * @param {Function} finished */ var asyncSerial = function (obj, process, finished) { var id, isArray = obj instanceof Array; - - // Keep track of each property that belongs to this object. + + // Keep track of each property that belongs to this object. if (!isArray) { var ids = []; for (id in obj) { @@ -61,9 +61,9 @@ var H5PUpgrades = H5PUpgrades || {}; } } } - + var i = -1; // Keeps track of the current property - + /** * Private. Process the next property */ @@ -71,10 +71,10 @@ var H5PUpgrades = H5PUpgrades || {}; id = isArray ? i : ids[i]; process(id, obj[id], check); }; - + /** * Private. Check if we're done or have an error. - * + * * @param {String} err */ var check = function (err) { @@ -89,13 +89,13 @@ var H5PUpgrades = H5PUpgrades || {}; } }, 0); }; - + check(); // Start }; - /** + /** * Make it easy to keep track of version details. - * + * * @param {String} version * @param {Number} libraryId * @returns {_L1.Version} @@ -103,19 +103,19 @@ var H5PUpgrades = H5PUpgrades || {}; function Version(version, libraryId) { if (libraryId !== undefined) { version = info.versions[libraryId]; - + // Public this.libraryId = libraryId; } var versionSplit = version.split('.', 3); - + // Public this.major = versionSplit[0]; this.minor = versionSplit[1]; - + /** * Public. Custom string for this object. - * + * * @returns {String} */ this.toString = function () { @@ -125,17 +125,17 @@ var H5PUpgrades = H5PUpgrades || {}; /** * Displays a throbber in the status field. - * + * * @param {String} msg * @returns {_L1.Throbber} */ function Throbber(msg) { var $throbber = H5PUtils.throbber(msg); $container.html('').append($throbber); - + /** * Makes it possible to set the progress. - * + * * @param {String} progress */ this.setProgress = function (progress) { @@ -145,16 +145,16 @@ var H5PUpgrades = H5PUpgrades || {}; /** * Start a new content upgrade. - * + * * @param {Number} libraryId * @returns {_L1.ContentUpgrade} */ function ContentUpgrade(libraryId) { var self = this; - + // Get selected version self.version = new Version(null, libraryId); - + // Create throbber with loading text and progress self.throbber = new Throbber(info.inProgress.replace('%ver', self.version)); @@ -164,36 +164,36 @@ var H5PUpgrades = H5PUpgrades || {}; token: info.token }); } - + /** * Get the next batch and start processing it. - * + * * @param {Object} outData */ ContentUpgrade.prototype.nextBatch = function (outData) { var self = this; - + $.post(info.infoUrl, outData, function (inData) { if (!(inData instanceof Object)) { // Print errors from backend return self.setStatus(inData); - } + } if (inData.left === 0) { // Nothing left to process return self.setStatus(info.done); } - + self.left = inData.left; self.token = inData.token; - + // Start processing self.processBatch(inData.params); }); }; - + /** * Set current status message. - * + * * @param {String} msg */ ContentUpgrade.prototype.setStatus = function (msg) { @@ -202,28 +202,37 @@ var H5PUpgrades = H5PUpgrades || {}; /** * Process the given parameters. - * + * * @param {Object} parameters */ ContentUpgrade.prototype.processBatch = function (parameters) { var self = this; var upgraded = {}; // Track upgraded params - + var current = 0; // Track progress asyncSerial(parameters, function (id, params, next) { - - // Make params possible to work with - params = JSON.parse(params); - + try { + // Make params possible to work with + params = JSON.parse(params); + if (!(params instanceof Object)) { + throw true; + } + } + catch (event) { + return next(info.errorContent.replace('%id', id) + ' ' + info.errorParamsBroken); + } + // Upgrade this content. self.upgrade(info.library.name, new Version(info.library.version), self.version, params, function (err, params) { - if (!err) { - upgraded[id] = JSON.stringify(params); - - current++; - self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %'); + if (err) { + return next(info.errorContent.replace('%id', id) + ' ' + err); } - next(err); + + upgraded[id] = JSON.stringify(params); + + current++; + self.throbber.setProgress(Math.round((info.total - self.left + current) / (info.total / 100)) + ' %'); + next(); }); }, function (err) { @@ -240,10 +249,10 @@ var H5PUpgrades = H5PUpgrades || {}; }); }); }; - + /** * Upgade the given content. - * + * * @param {String} name * @param {Version} oldVersion * @param {Version} newVersion @@ -253,19 +262,19 @@ var H5PUpgrades = H5PUpgrades || {}; */ ContentUpgrade.prototype.upgrade = function (name, oldVersion, newVersion, params, next) { var self = this; - + // Load library details and upgrade routines self.loadLibrary(name, newVersion, function (err, library) { if (err) { return next(err); } - + // Run upgrade routines on params self.processParams(library, oldVersion, newVersion, params, function (err, params) { if (err) { return next(err); } - + // Check if any of the sub-libraries need upgrading asyncSerial(library.semantics, function (index, field, next) { self.processField(field, params[field.name], function (err, upgradedParams) { @@ -280,24 +289,24 @@ var H5PUpgrades = H5PUpgrades || {}; }); }); }; - + /** * Load library data needed for content upgrade. - * + * * @param {String} name * @param {Version} version * @param {Function} next */ ContentUpgrade.prototype.loadLibrary = function (name, version, next) { var self = this; - + var key = name + '/' + version.major + '/' + version.minor; if (librariesCache[key] !== undefined) { // Library has been loaded before. Return cache. next(null, librariesCache[key]); return; } - + $.ajax({ dataType: 'json', cache: true, @@ -306,7 +315,7 @@ var H5PUpgrades = H5PUpgrades || {}; next(info.errorData.replace('%lib', name + ' ' + version)); }).done(function (library) { librariesCache[key] = library; - + if (library.upgradesScript) { self.loadScript(library.upgradesScript, function (err) { if (err) { @@ -320,10 +329,10 @@ var H5PUpgrades = H5PUpgrades || {}; } }); }; - + /** * Load script with upgrade hooks. - * + * * @param {String} url * @param {Function} next */ @@ -338,10 +347,10 @@ var H5PUpgrades = H5PUpgrades || {}; next(); }); }; - + /** * Run upgrade hooks on params. - * + * * @param {Object} library * @param {Version} oldVersion * @param {Version} newVersion @@ -354,7 +363,7 @@ var H5PUpgrades = H5PUpgrades || {}; // Upgrades script should be loaded so the upgrades should be here. return next(info.errorScript.replace('%lib', library.name + ' ' + newVersion)); } - + // No upgrades script. Move on return next(null, params); } @@ -362,7 +371,7 @@ var H5PUpgrades = H5PUpgrades || {}; // Run upgrade hooks. Start by going through major versions asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) { if (major < oldVersion.major || major > newVersion.major) { - // Older than the current version or newer than the selected + // Older than the current version or newer than the selected nextMajor(); } else { @@ -374,14 +383,16 @@ var H5PUpgrades = H5PUpgrades || {}; } else { // We found an upgrade hook, run it - if (upgrade.contentUpgrade !== undefined && typeof upgrade.contentUpgrade === 'function') { - upgrade.contentUpgrade(params, function (err, upgradedParams) { + var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade); + + try { + unnecessaryWrapper(params, function (err, upgradedParams) { params = upgradedParams; nextMinor(err); }); } - else { - nextMinor(info.errorScript.replace('%lib', library.name + ' ' + newVersion)); + catch (err) { + next(err); } } }, nextMajor); @@ -390,27 +401,27 @@ var H5PUpgrades = H5PUpgrades || {}; next(err, params); }); }; - + /** * Process parameter fields to find and upgrade sub-libraries. - * + * * @param {Object} field * @param {Object} params * @param {Function} next */ ContentUpgrade.prototype.processField = function (field, params, next) { var self = this; - + if (params === undefined) { return next(); } - + switch (field.type) { case 'library': if (params.library === undefined || params.params === undefined) { return next(); } - + // Look for available upgrades var usedLib = params.library.split(' ', 2); for (var i = 0; i < field.options.length; i++) { @@ -419,14 +430,14 @@ var H5PUpgrades = H5PUpgrades || {}; if (availableLib[1] === usedLib[1]) { return next(); // Same version } - + // We have different versions var usedVer = new Version(usedLib[1]); var availableVer = new Version(availableLib[1]); if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) { return next(); // Larger or same version that's available } - + // A newer version is available, upgrade params return self.upgrade(availableLib[0], usedVer, availableVer, params.params, function (err, upgraded) { if (!err) { @@ -484,4 +495,4 @@ var H5PUpgrades = H5PUpgrades || {}; } }; -})(H5P.jQuery); \ No newline at end of file +})(H5P.jQuery);