Actualización

This commit is contained in:
xesmyd committed 2025-04-10 12:24:57 +02:00
1 parent 8969cc929d
commit 45420b6f0d
39760 files changed
+4303286

No files matched your search

+107
View File
@@ -0,0 +1,107 @@
/**
* @class
* @augments H5P.EventDispatcher
* @param {Object} displayOptions
* @param {boolean} displayOptions.export Triggers the display of the 'Download' button
* @param {boolean} displayOptions.copyright Triggers the display of the 'Copyright' button
* @param {boolean} displayOptions.embed Triggers the display of the 'Embed' button
* @param {boolean} displayOptions.icon Triggers the display of the 'H5P icon' link
*/
H5P.ActionBar = (function ($, EventDispatcher) {
"use strict";
function ActionBar(displayOptions) {
EventDispatcher.call(this);
/** @alias H5P.ActionBar# */
var self = this;
var hasActions = false;
// Create action bar
var $actions = H5P.jQuery('<ul class="h5p-actions"></ul>');
/**
* Helper for creating action bar buttons.
*
* @private
* @param {string} type
* @param {string} customClass Instead of type class
*/
var addActionButton = function (type, customClass) {
/**
* Handles selection of action
*/
var handler = function () {
self.trigger(type);
};
const $actionList = H5P.jQuery('<li/>', {
'class': 'h5p-button h5p-noselect h5p-' + (customClass ? customClass : type),
appendTo: $actions
});
const $actionButton = H5P.jQuery('<button/>', {
tabindex: 0,
'aria-label': H5P.t(type + 'Description'),
html: H5P.t(type),
on: {
click: handler,
keypress: function (e) {
if (e.which === 32) {
handler();
e.preventDefault(); // (since return false will block other inputs)
}
}
},
appendTo: $actionList
});
H5P.Tooltip($actionButton.get(0));
hasActions = true;
};
// Register action bar buttons
if (displayOptions.export || displayOptions.copy) {
// Add export button
addActionButton('reuse', 'export');
}
if (displayOptions.copyright) {
addActionButton('copyrights');
}
if (displayOptions.embed) {
addActionButton('embed');
}
if (displayOptions.icon) {
// Add about H5P button icon
const $h5pLogo = H5P.jQuery('<li><a class="h5p-link" href="http://h5p.org" target="_blank" aria-label="' + H5P.t('h5pDescription') + '"></a></li>').appendTo($actions);
H5P.Tooltip($h5pLogo.find('.h5p-link').get(0));
hasActions = true;
}
/**
* Returns a reference to the dom element
*
* @return {H5P.jQuery}
*/
self.getDOMElement = function () {
return $actions;
};
/**
* Does the actionbar contain actions?
*
* @return {Boolean}
*/
self.hasActions = function () {
return hasActions;
};
}
ActionBar.prototype = Object.create(EventDispatcher.prototype);
ActionBar.prototype.constructor = ActionBar;
return ActionBar;
})(H5P.jQuery, H5P.EventDispatcher);
+420
View File
@@ -0,0 +1,420 @@
/*global H5P*/
H5P.ConfirmationDialog = (function (EventDispatcher) {
"use strict";
/**
* Create a confirmation dialog
*
* @param [options] Options for confirmation dialog
* @param [options.instance] Instance that uses confirmation dialog
* @param [options.headerText] Header text
* @param [options.dialogText] Dialog text
* @param [options.cancelText] Cancel dialog button text
* @param [options.confirmText] Confirm dialog button text
* @param [options.hideCancel] Hide cancel button
* @param [options.hideExit] Hide exit button
* @param [options.skipRestoreFocus] Skip restoring focus when hiding the dialog
* @param [options.classes] Extra classes for popup
* @constructor
*/
function ConfirmationDialog(options) {
EventDispatcher.call(this);
var self = this;
// Make sure confirmation dialogs have unique id
H5P.ConfirmationDialog.uniqueId += 1;
var uniqueId = H5P.ConfirmationDialog.uniqueId;
// Default options
options = options || {};
options.headerText = options.headerText || H5P.t('confirmDialogHeader');
options.dialogText = options.dialogText || H5P.t('confirmDialogBody');
options.cancelText = options.cancelText || H5P.t('cancelLabel');
options.confirmText = options.confirmText || H5P.t('confirmLabel');
/**
* Handle confirming event
* @param {Event} e
*/
function dialogConfirmed(e) {
self.hide();
self.trigger('confirmed');
e.preventDefault();
}
/**
* Handle dialog canceled
* @param {Event} e
*/
function dialogCanceled(e) {
self.hide();
self.trigger('canceled');
e.preventDefault();
}
/**
* Flow focus to element
* @param {HTMLElement} element Next element to be focused
* @param {Event} e Original tab event
*/
function flowTo(element, e) {
element.focus();
e.preventDefault();
}
// Offset of exit button
var exitButtonOffset = 2 * 16;
var shadowOffset = 8;
// Determine if we are too large for our container and must resize
var resizeIFrame = false;
// Create background
var popupBackground = document.createElement('div');
popupBackground.classList
.add('h5p-confirmation-dialog-background', 'hidden', 'hiding');
// Create outer popup
var popup = document.createElement('div');
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
if (options.classes) {
options.classes.forEach(function (popupClass) {
popup.classList.add(popupClass);
});
}
popup.setAttribute('role', 'dialog');
popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
popupBackground.appendChild(popup);
popup.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {// Esc key
// Exit dialog
dialogCanceled(e);
}
});
// Popup header
var header = document.createElement('div');
header.classList.add('h5p-confirmation-dialog-header');
popup.appendChild(header);
// Header text
var headerText = document.createElement('div');
headerText.classList.add('h5p-confirmation-dialog-header-text');
headerText.innerHTML = options.headerText;
header.appendChild(headerText);
// Popup body
var body = document.createElement('div');
body.classList.add('h5p-confirmation-dialog-body');
popup.appendChild(body);
// Popup text
var text = document.createElement('div');
text.classList.add('h5p-confirmation-dialog-text');
text.innerHTML = options.dialogText;
text.id = 'h5p-confirmation-dialog-dialog-text-' + uniqueId;
body.appendChild(text);
// Popup buttons
var buttons = document.createElement('div');
buttons.classList.add('h5p-confirmation-dialog-buttons');
body.appendChild(buttons);
// Cancel button
var cancelButton = document.createElement('button');
cancelButton.classList.add('h5p-core-cancel-button');
cancelButton.textContent = options.cancelText;
// Confirm button
var confirmButton = document.createElement('button');
confirmButton.classList.add('h5p-core-button');
confirmButton.classList.add('h5p-confirmation-dialog-confirm-button');
confirmButton.textContent = options.confirmText;
// Exit button
var exitButton = document.createElement('button');
exitButton.classList.add('h5p-confirmation-dialog-exit');
exitButton.tabIndex = -1;
exitButton.setAttribute('aria-label', options.cancelText);
// Cancel handler
cancelButton.addEventListener('click', dialogCanceled);
cancelButton.addEventListener('keydown', function (e) {
if (e.key === ' ') { // Space
dialogCanceled(e);
}
else if (e.key === 'Tab' && e.shiftKey) { // Shift-tab
const nextbutton = options.hideExit ? confirmButton : exitButton;
flowTo(nextbutton, e);
}
});
if (!options.hideCancel) {
buttons.appendChild(cancelButton);
}
else {
// Center buttons
buttons.classList.add('center');
}
// Confirm handler
confirmButton.addEventListener('click', dialogConfirmed);
confirmButton.addEventListener('keydown', function (e) {
if (e.key === ' ') { // Space
dialogConfirmed(e);
}
else if (e.key === 'Tab' && !e.shiftKey) { // Tab
let nextButton = confirmButton;
if (!options.hideExit) {
nextButton = exitButton;
}
else if (!options.hideCancel) {
nextButton = cancelButton;
}
flowTo(nextButton, e);
}
});
buttons.appendChild(confirmButton);
// Exit handler
exitButton.addEventListener('click', dialogCanceled);
exitButton.addEventListener('keydown', function (e) {
if (e.key === ' ') { // Space
dialogCanceled(e);
}
else if (e.key === 'Tab' && !e.shiftKey) { // Tab
const nextButton = options.hideCancel ? confirmButton : cancelButton;
flowTo(nextButton, e);
}
});
if (!options.hideExit) {
popup.appendChild(exitButton);
}
// Wrapper element
var wrapperElement;
// Focus capturing
var focusPredator;
// Maintains hidden state of elements
var wrapperSiblingsHidden = [];
var popupSiblingsHidden = [];
// Element with focus before dialog
var previouslyFocused;
/**
* Set parent of confirmation dialog
* @param {HTMLElement} wrapper
* @returns {H5P.ConfirmationDialog}
*/
this.appendTo = function (wrapper) {
wrapperElement = wrapper;
return this;
};
/**
* Capture the focus element, send it to confirmation button
* @param {Event} e Original focus event
*/
var captureFocus = function (e) {
if (!popupBackground.contains(e.target)) {
e.preventDefault();
confirmButton.focus();
}
};
/**
* Hide siblings of element from assistive technology
*
* @param {HTMLElement} element
* @returns {Array} The previous hidden state of all siblings
*/
var hideSiblings = function (element) {
var hiddenSiblings = [];
var siblings = element.parentNode.children;
var i;
for (i = 0; i < siblings.length; i += 1) {
// Preserve hidden state
hiddenSiblings[i] = siblings[i].getAttribute('aria-hidden') ?
true : false;
if (siblings[i] !== element) {
siblings[i].setAttribute('aria-hidden', true);
}
}
return hiddenSiblings;
};
/**
* Restores assistive technology state of element's siblings
*
* @param {HTMLElement} element
* @param {Array} hiddenSiblings Hidden state of all siblings
*/
var restoreSiblings = function (element, hiddenSiblings) {
var siblings = element.parentNode.children;
var i;
for (i = 0; i < siblings.length; i += 1) {
if (siblings[i] !== element && !hiddenSiblings[i]) {
siblings[i].removeAttribute('aria-hidden');
}
}
};
/**
* Start capturing focus of parent and send it to dialog
*/
var startCapturingFocus = function () {
focusPredator = wrapperElement.parentNode || wrapperElement;
focusPredator.addEventListener('focus', captureFocus, true);
};
/**
* Clean up event listener for capturing focus
*/
var stopCapturingFocus = function () {
focusPredator.removeAttribute('aria-hidden');
focusPredator.removeEventListener('focus', captureFocus, true);
};
/**
* Hide siblings in underlay from assistive technologies
*/
var disableUnderlay = function () {
wrapperSiblingsHidden = hideSiblings(wrapperElement);
popupSiblingsHidden = hideSiblings(popupBackground);
};
/**
* Restore state of underlay for assistive technologies
*/
var restoreUnderlay = function () {
restoreSiblings(wrapperElement, wrapperSiblingsHidden);
restoreSiblings(popupBackground, popupSiblingsHidden);
};
/**
* Fit popup to container. Makes sure it doesn't overflow.
* @params {number} [offsetTop] Offset of popup
*/
var fitToContainer = function (offsetTop) {
var popupOffsetTop = parseInt(popup.style.top, 10);
if (offsetTop !== undefined) {
popupOffsetTop = offsetTop;
}
if (!popupOffsetTop) {
popupOffsetTop = 0;
}
// Overflows height
if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) {
popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset;
}
if (popupOffsetTop - exitButtonOffset <= 0) {
popupOffsetTop = exitButtonOffset + shadowOffset;
// We are too big and must resize
resizeIFrame = true;
}
popup.style.top = popupOffsetTop + 'px';
};
/**
* Show confirmation dialog
* @params {number} offsetTop Offset top
* @returns {H5P.ConfirmationDialog}
*/
this.show = function (offsetTop) {
// Capture focused item
previouslyFocused = document.activeElement;
wrapperElement.appendChild(popupBackground);
startCapturingFocus();
disableUnderlay();
popupBackground.classList.remove('hidden');
fitToContainer(offsetTop);
setTimeout(function () {
popup.classList.remove('hidden');
popupBackground.classList.remove('hiding');
setTimeout(function () {
// Focus confirm button
confirmButton.focus();
// Resize iFrame if necessary
if (resizeIFrame && options.instance) {
var minHeight = parseInt(popup.offsetHeight, 10) +
exitButtonOffset + (2 * shadowOffset);
self.setViewPortMinimumHeight(minHeight);
options.instance.trigger('resize');
resizeIFrame = false;
}
}, 100);
}, 0);
return this;
};
/**
* Hide confirmation dialog
* @returns {H5P.ConfirmationDialog}
*/
this.hide = function () {
popupBackground.classList.add('hiding');
popup.classList.add('hidden');
// Restore focus
stopCapturingFocus();
if (!options.skipRestoreFocus) {
previouslyFocused.focus();
}
restoreUnderlay();
setTimeout(function () {
popupBackground.classList.add('hidden');
wrapperElement.removeChild(popupBackground);
self.setViewPortMinimumHeight(null);
}, 100);
return this;
};
/**
* Retrieve element
*
* @return {HTMLElement}
*/
this.getElement = function () {
return popup;
};
/**
* Get previously focused element
* @return {HTMLElement}
*/
this.getPreviouslyFocused = function () {
return previouslyFocused;
};
/**
* Sets the minimum height of the view port
*
* @param {number|null} minHeight
*/
this.setViewPortMinimumHeight = function (minHeight) {
var container = document.querySelector('.h5p-container') || document.body;
container.style.minHeight = (typeof minHeight === 'number') ? (minHeight + 'px') : minHeight;
};
}
ConfirmationDialog.prototype = Object.create(EventDispatcher.prototype);
ConfirmationDialog.prototype.constructor = ConfirmationDialog;
return ConfirmationDialog;
}(H5P.EventDispatcher));
H5P.ConfirmationDialog.uniqueId = -1;
+41
View File
@@ -0,0 +1,41 @@
/**
* H5P.ContentType is a base class for all content types. Used by newRunnable()
*
* Functions here may be overridable by the libraries. In special cases,
* it is also possible to override H5P.ContentType on a global level.
*
* NOTE that this doesn't actually 'extend' the event dispatcher but instead
* it creates a single instance which all content types shares as their base
* prototype. (in some cases this may be the root of strange event behavior)
*
* @class
* @augments H5P.EventDispatcher
*/
H5P.ContentType = function (isRootLibrary) {
function ContentType() {}
// Inherit from EventDispatcher.
ContentType.prototype = new H5P.EventDispatcher();
/**
* Is library standalone or not? Not beeing standalone, means it is
* included in another library
*
* @return {Boolean}
*/
ContentType.prototype.isRoot = function () {
return isRootLibrary;
};
/**
* Returns the file path of a file in the current library
* @param {string} filePath The path to the file relative to the library folder
* @return {string} The full path to the file
*/
ContentType.prototype.getLibraryFilePath = function (filePath) {
return H5P.getLibraryPath(this.libraryInfo.versionedNameNoSpaces) + '/' + filePath;
};
return ContentType;
};
+313
View File
@@ -0,0 +1,313 @@
/*jshint -W083 */
var H5PUpgrades = H5PUpgrades || {};
H5P.ContentUpgradeProcess = (function (Version) {
/**
* @class
* @namespace H5P
*/
function ContentUpgradeProcess(name, oldVersion, newVersion, params, id, loadLibrary, done) {
var self = this;
// Make params possible to work with
try {
params = JSON.parse(params);
if (!(params instanceof Object)) {
throw true;
}
}
catch (event) {
return done({
type: 'errorParamsBroken',
id: id
});
}
self.loadLibrary = loadLibrary;
self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
if (err) {
err.id = id;
return done(err);
}
done(null, JSON.stringify({params: upgradedParams, metadata: upgradedMetadata}));
});
}
/**
* Run content upgrade.
*
* @public
* @param {string} name
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Object} metadata
* @param {Function} done
*/
ContentUpgradeProcess.prototype.upgrade = function (name, oldVersion, newVersion, params, metadata, done) {
var self = this;
// Load library details and upgrade routines
self.loadLibrary(name, newVersion, function (err, library) {
if (err) {
return done(err);
}
if (library.semantics === null) {
return done({
type: 'libraryMissing',
library: library.name + ' ' + library.version.major + '.' + library.version.minor
});
}
// Run upgrade routines on params
self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) {
if (err) {
return done(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) {
if (upgradedParams) {
params[field.name] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params, metadata);
});
});
});
};
/**
* Run upgrade hooks on params.
*
* @public
* @param {Object} library
* @param {Version} oldVersion
* @param {Version} newVersion
* @param {Object} params
* @param {Function} next
*/
ContentUpgradeProcess.prototype.processParams = function (library, oldVersion, newVersion, params, metadata, next) {
if (H5PUpgrades[library.name] === undefined) {
if (library.upgradesScript) {
// Upgrades script should be loaded so the upgrades should be here.
return next({
type: 'scriptMissing',
library: library.name + ' ' + newVersion
});
}
// No upgrades script. Move on
return next(null, params, metadata);
}
// 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
nextMajor();
}
else {
// Go through the minor versions for this major version
asyncSerial(minors, function (minor, upgrade, nextMinor) {
minor =+ minor;
if (minor <= oldVersion.minor || minor > newVersion.minor) {
// Older than or equal to the current version or newer than the selected
nextMinor();
}
else {
// We found an upgrade hook, run it
var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade);
try {
unnecessaryWrapper(params, function (err, upgradedParams, upgradedExtras) {
params = upgradedParams;
if (upgradedExtras && upgradedExtras.metadata) { // Optional
metadata = upgradedExtras.metadata;
}
nextMinor(err);
}, {metadata: metadata});
}
catch (err) {
if (console && console.error) {
console.error("Error", err.stack);
console.error("Error", err.name);
console.error("Error", err.message);
}
next(err);
}
}
}, nextMajor);
}
}, function (err) {
next(err, params, metadata);
});
};
/**
* Process parameter fields to find and upgrade sub-libraries.
*
* @public
* @param {Object} field
* @param {Object} params
* @param {Function} done
*/
ContentUpgradeProcess.prototype.processField = function (field, params, done) {
var self = this;
if (params === undefined || params === null) {
return done();
}
switch (field.type) {
case 'library':
if (params.library === undefined || params.params === undefined) {
return done();
}
// Look for available upgrades
var usedLib = params.library.split(' ', 2);
for (var i = 0; i < field.options.length; i++) {
var availableLib = (typeof field.options[i] === 'string') ? field.options[i].split(' ', 2) : field.options[i].name.split(' ', 2);
if (availableLib[0] === usedLib[0]) {
if (availableLib[1] === usedLib[1]) {
return done(); // 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 done({
type: 'errorTooHighVersion',
used: usedLib[0] + ' ' + usedVer,
supported: availableLib[0] + ' ' + availableVer
}); // Larger or same version that's available
}
// A newer version is available, upgrade params
return self.upgrade(availableLib[0], usedVer, availableVer, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) {
if (!err) {
params.library = availableLib[0] + ' ' + availableVer.major + '.' + availableVer.minor;
params.params = upgradedParams;
if (upgradedMetadata) {
params.metadata = upgradedMetadata;
}
}
done(err, params);
});
}
}
// Content type was not supporte by the higher version
done({
type: 'errorNotSupported',
used: usedLib[0] + ' ' + usedVer
});
break;
case 'group':
if (field.fields.length === 1 && field.isSubContent !== true) {
// Single field to process, wrapper will be skipped
self.processField(field.fields[0], params, function (err, upgradedParams) {
if (upgradedParams) {
params = upgradedParams;
}
done(err, params);
});
}
else {
// Go through all fields in the group
asyncSerial(field.fields, function (index, subField, next) {
var paramsToProcess = params ? params[subField.name] : null;
self.processField(subField, paramsToProcess, function (err, upgradedParams) {
if (upgradedParams) {
params[subField.name] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params);
});
}
break;
case 'list':
// Go trough all params in the list
asyncSerial(params, function (index, subParams, next) {
self.processField(field.field, subParams, function (err, upgradedParams) {
if (upgradedParams) {
params[index] = upgradedParams;
}
next(err);
});
}, function (err) {
done(err, params);
});
break;
default:
done();
}
};
/**
* Helps process each property on the given object asynchronously in serial order.
*
* @private
* @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.
if (!isArray) {
var ids = [];
for (id in obj) {
if (obj.hasOwnProperty(id)) {
ids.push(id);
}
}
}
var i = -1; // Keeps track of the current property
/**
* Private. Process the next property
*/
var next = function () {
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) {
// We need to use a real async function in order for the stack to clear.
setTimeout(function () {
i++;
if (i === (isArray ? obj.length : ids.length) || (err !== undefined && err !== null)) {
finished(err);
}
else {
next();
}
}, 0);
};
check(); // Start
};
return ContentUpgradeProcess;
})(H5P.Version);
+63
View File
@@ -0,0 +1,63 @@
/* global importScripts */
var H5P = H5P || {};
importScripts('h5p-version.js', 'h5p-content-upgrade-process.js');
var libraryLoadedCallback;
/**
* Register message handlers
*/
var messageHandlers = {
newJob: function (job) {
// Start new job
new H5P.ContentUpgradeProcess(job.name, new H5P.Version(job.oldVersion), new H5P.Version(job.newVersion), job.params, job.id, function loadLibrary(name, version, next) {
// TODO: Cache?
postMessage({
action: 'loadLibrary',
name: name,
version: version.toString()
});
libraryLoadedCallback = next;
}, function done(err, result) {
if (err) {
// Return error
postMessage({
action: 'error',
id: job.id,
err: err.message ? err.message : err
});
return;
}
// Return upgraded content
postMessage({
action: 'done',
id: job.id,
params: result
});
});
},
libraryLoaded: function (data) {
var library = data.library;
if (library.upgradesScript) {
try {
importScripts(library.upgradesScript);
}
catch (err) {
libraryLoadedCallback(err);
return;
}
}
libraryLoadedCallback(null, data.library);
}
};
/**
* Handle messages from our master
*/
onmessage = function (event) {
if (event.data.action !== undefined && messageHandlers[event.data.action]) {
messageHandlers[event.data.action].call(this, event.data);
}
};
+445
View File
@@ -0,0 +1,445 @@
/* global H5PAdminIntegration H5PUtils */
(function ($, Version) {
var info, $log, $container, librariesCache = {}, scriptsCache = {};
// Initialize
$(document).ready(function () {
// Get library info
info = H5PAdminIntegration.libraryInfo;
// Get and reset container
const $wrapper = $('#h5p-admin-container').html('');
$log = $('<ul class="content-upgrade-log"></ul>').appendTo($wrapper);
$container = $('<div><p>' + info.message + '</p></div>').appendTo($wrapper);
// Make it possible to select version
var $version = $(getVersionSelect(info.versions)).appendTo($container);
// Add "go" button
$('<button/>', {
class: 'h5p-admin-upgrade-button',
text: info.buttonLabel,
click: function () {
// Start new content upgrade
new ContentUpgrade($version.val());
}
}).appendTo($container);
});
/**
* Generate html for version select.
*
* @param {Object} versions
* @returns {String}
*/
var getVersionSelect = function (versions) {
var html = '';
for (var id in versions) {
html += '<option value="' + id + '">' + versions[id] + '</option>';
}
if (html !== '') {
html = '<select>' + html + '</select>';
return html;
}
};
/**
* 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) {
$throbber.text(msg + ' ' + progress);
};
}
/**
* Start a new content upgrade.
*
* @param {Number} libraryId
* @returns {_L1.ContentUpgrade}
*/
function ContentUpgrade(libraryId) {
var self = this;
// Get selected version
self.version = new Version(info.versions[libraryId]);
self.version.libraryId = libraryId;
// Create throbber with loading text and progress
self.throbber = new Throbber(info.inProgress.replace('%ver', self.version));
self.started = new Date().getTime();
self.io = 0;
// Track number of working
self.working = 0;
var start = function () {
// Get the next batch
self.nextBatch({
libraryId: libraryId,
token: info.token
});
};
if (window.Worker !== undefined) {
// Prepare our workers
self.initWorkers();
start();
}
else {
// No workers, do the job ourselves
self.loadScript(info.scriptBaseUrl + '/h5p-content-upgrade-process.js' + info.buster, start);
}
}
/**
* Initialize workers
*/
ContentUpgrade.prototype.initWorkers = function () {
var self = this;
// Determine number of workers (defaults to 4)
var numWorkers = (window.navigator !== undefined && window.navigator.hardwareConcurrency ? window.navigator.hardwareConcurrency : 4);
self.workers = new Array(numWorkers);
// Register message handlers
var messageHandlers = {
done: function (result) {
self.workDone(result.id, result.params, this);
},
error: function (error) {
self.printError(error.err);
self.workDone(error.id, null, this);
},
loadLibrary: function (details) {
var worker = this;
self.loadLibrary(details.name, new Version(details.version), function (err, library) {
if (err) {
// Reset worker?
return;
}
worker.postMessage({
action: 'libraryLoaded',
library: library
});
});
}
};
for (var i = 0; i < numWorkers; i++) {
self.workers[i] = new Worker(info.scriptBaseUrl + '/h5p-content-upgrade-worker.js' + info.buster);
self.workers[i].onmessage = function (event) {
if (event.data.action !== undefined && messageHandlers[event.data.action]) {
messageHandlers[event.data.action].call(this, event.data);
}
};
}
};
/**
* Get the next batch and start processing it.
*
* @param {Object} outData
*/
ContentUpgrade.prototype.nextBatch = function (outData) {
var self = this;
// Track time spent on IO
var start = new Date().getTime();
$.post(info.infoUrl, outData, function (inData) {
self.io += new Date().getTime() - start;
if (!(inData instanceof Object)) {
// Print errors from backend
return self.setStatus(inData);
}
if (inData.left === 0) {
var total = new Date().getTime() - self.started;
if (window.console && console.log) {
console.log('The upgrade process took ' + (total / 1000) + ' seconds. (' + (Math.round((self.io / (total / 100)) * 100) / 100) + ' % IO)' );
}
// Terminate workers
self.terminate();
// Nothing left to process
return self.setStatus(info.done);
}
self.left = inData.left;
self.token = inData.token;
// Start processing
self.processBatch(inData.params, inData.skipped);
});
};
/**
* Set current status message.
*
* @param {String} msg
*/
ContentUpgrade.prototype.setStatus = function (msg) {
$container.html(msg);
};
/**
* Process the given parameters.
*
* @param {Object} parameters
*/
ContentUpgrade.prototype.processBatch = function (parameters, skipped) {
var self = this;
// Track upgraded params
self.upgraded = {};
self.skipped = skipped;
// Track current batch
self.parameters = parameters;
// Create id mapping
self.ids = [];
for (var id in parameters) {
if (parameters.hasOwnProperty(id)) {
self.ids.push(id);
}
}
// Keep track of current content
self.current = -1;
if (self.workers !== undefined) {
// Assign each worker content to upgrade
for (var i = 0; i < self.workers.length; i++) {
self.assignWork(self.workers[i]);
}
}
else {
self.assignWork();
}
};
/**
*
*/
ContentUpgrade.prototype.assignWork = function (worker) {
var self = this;
var id = self.ids[self.current + 1];
if (id === undefined) {
return false; // Out of work
}
self.current++;
self.working++;
if (worker) {
worker.postMessage({
action: 'newJob',
id: id,
name: info.library.name,
oldVersion: info.library.version,
newVersion: self.version.toString(),
params: self.parameters[id]
});
}
else {
new H5P.ContentUpgradeProcess(info.library.name, new Version(info.library.version), self.version, self.parameters[id], id, function loadLibrary(name, version, next) {
self.loadLibrary(name, version, function (err, library) {
if (library.upgradesScript) {
self.loadScript(library.upgradesScript, function (err) {
if (err) {
err = info.errorScript.replace('%lib', name + ' ' + version);
}
next(err, library);
});
}
else {
next(null, library);
}
});
}, function done(err, result) {
if (err) {
self.printError(err);
result = null;
}
self.workDone(id, result);
});
}
};
/**
*
*/
ContentUpgrade.prototype.workDone = function (id, result, worker) {
var self = this;
self.working--;
if (result === null) {
self.skipped.push(id);
}
else {
self.upgraded[id] = result;
}
// Update progress message
self.throbber.setProgress(Math.round((info.total - self.left + self.current) / (info.total / 100)) + ' %');
// Assign next job
if (self.assignWork(worker) === false && self.working === 0) {
// All workers have finsihed.
self.nextBatch({
libraryId: self.version.libraryId,
token: self.token,
skipped: JSON.stringify(self.skipped),
params: JSON.stringify(self.upgraded)
});
}
};
/**
*
*/
ContentUpgrade.prototype.terminate = function () {
var self = this;
if (self.workers) {
// Stop all workers
for (var i = 0; i < self.workers.length; i++) {
self.workers[i].terminate();
}
}
};
var librariesLoadedCallbacks = {};
/**
* 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] === true) {
// Library is being loaded, que callback
if (librariesLoadedCallbacks[key] === undefined) {
librariesLoadedCallbacks[key] = [next];
return;
}
librariesLoadedCallbacks[key].push(next);
return;
}
else if (librariesCache[key] !== undefined) {
// Library has been loaded before. Return cache.
next(null, librariesCache[key]);
return;
}
// Track time spent loading
var start = new Date().getTime();
librariesCache[key] = true;
$.ajax({
dataType: 'json',
cache: true,
url: info.libraryBaseUrl + '/' + key
}).fail(function () {
self.io += new Date().getTime() - start;
next(info.errorData.replace('%lib', name + ' ' + version));
}).done(function (library) {
self.io += new Date().getTime() - start;
librariesCache[key] = library;
next(null, library);
if (librariesLoadedCallbacks[key] !== undefined) {
for (var i = 0; i < librariesLoadedCallbacks[key].length; i++) {
librariesLoadedCallbacks[key][i](null, library);
}
}
delete librariesLoadedCallbacks[key];
});
};
/**
* Load script with upgrade hooks.
*
* @param {String} url
* @param {Function} next
*/
ContentUpgrade.prototype.loadScript = function (url, next) {
var self = this;
if (scriptsCache[url] !== undefined) {
next();
return;
}
// Track time spent loading
var start = new Date().getTime();
$.ajax({
dataType: 'script',
cache: true,
url: url
}).fail(function () {
self.io += new Date().getTime() - start;
next(true);
}).done(function () {
scriptsCache[url] = true;
self.io += new Date().getTime() - start;
next();
});
};
/**
*
*/
ContentUpgrade.prototype.printError = function (error) {
var self = this;
switch (error.type) {
case 'errorParamsBroken':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorParamsBroken;
break;
case 'libraryMissing':
error = info.errorLibrary.replace('%lib', error.library);
break;
case 'scriptMissing':
error = info.errorScript.replace('%lib', error.library);
break;
case 'errorTooHighVersion':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorTooHighVersion.replace('%used', error.used).replace('%supported', error.supported);
break;
case 'errorNotSupported':
error = info.errorContent.replace('%id', error.id) + ' ' + info.errorNotSupported.replace('%used', error.used);
break;
}
$('<li>' + info.error + '<br/>' + error + '</li>').appendTo($log);
};
})(H5P.jQuery, H5P.Version);
+442
View File
@@ -0,0 +1,442 @@
/* global H5PUtils */
var H5PDataView = (function ($) {
/**
* Initialize a new H5P data view.
*
* @class
* @param {Object} container
* Element to clear out and append to.
* @param {String} source
* URL to get data from. Data format: {num: 123, rows:[[1,2,3],[2,4,6]]}
* @param {Array} headers
* List with column headers. Can be strings or objects with options like
* "text" and "sortable". E.g.
* [{text: 'Col 1', sortable: true}, 'Col 2', 'Col 3']
* @param {Object} l10n
* Localization / translations. e.g.
* {
* loading: 'Loading data.',
* ajaxFailed: 'Failed to load data.',
* noData: "There's no data available that matches your criteria.",
* currentPage: 'Page $current of $total',
* nextPage: 'Next page',
* previousPage: 'Previous page',
* search: 'Search'
* }
* @param {Object} classes
* Custom html classes to use on elements.
* e.g. {tableClass: 'fixed'}.
* @param {Array} filters
* Make it possible to filter/search in the given column.
* e.g. [null, true, null, null] will make it possible to do a text
* search in column 2.
* @param {Function} loaded
* Callback for when data has been loaded.
* @param {Object} order
*/
function H5PDataView(container, source, headers, l10n, classes, filters, loaded, order) {
var self = this;
self.$container = $(container).addClass('h5p-data-view').html('');
self.source = source;
self.headers = headers;
self.l10n = l10n;
self.classes = (classes === undefined ? {} : classes);
self.filters = (filters === undefined ? [] : filters);
self.loaded = loaded;
self.order = order;
self.limit = 20;
self.offset = 0;
self.filterOn = [];
self.facets = {};
// Index of column with author name; could be made more general by passing database column names and checking for position
self.columnIdAuthor = 2;
// Future option: Create more general solution for filter presets
if (H5PIntegration.user && parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) === 1) {
self.updateTable([]);
self.filterByFacet(self.columnIdAuthor, H5PIntegration.user.id, H5PIntegration.user.name || '');
}
else {
self.loadData();
}
}
/**
* Load data from source URL.
*/
H5PDataView.prototype.loadData = function () {
var self = this;
// Throbb
self.setMessage(H5PUtils.throbber(self.l10n.loading));
// Create URL
var url = self.source;
url += (url.indexOf('?') === -1 ? '?' : '&') + 'offset=' + self.offset + '&limit=' + self.limit;
// Add sorting
if (self.order !== undefined) {
url += '&sortBy=' + self.order.by + '&sortDir=' + self.order.dir;
}
// Add filters
var filtering;
for (var i = 0; i < self.filterOn.length; i++) {
if (self.filterOn[i] === undefined) {
continue;
}
filtering = true;
url += '&filters[' + i + ']=' + encodeURIComponent(self.filterOn[i]);
}
// Add facets
for (var col in self.facets) {
if (!self.facets.hasOwnProperty(col)) {
continue;
}
url += '&facets[' + col + ']=' + self.facets[col].id;
}
// Fire ajax request
$.ajax({
dataType: 'json',
cache: true,
url: url
}).fail(function () {
// Error handling
self.setMessage($('<p/>', {text: self.l10n.ajaxFailed}));
}).done(function (data) {
if (!data.rows.length) {
self.setMessage($('<p/>', {text: filtering ? self.l10n.noData : self.l10n.empty}));
}
else {
// Update table data
self.updateTable(data.rows);
}
// Update pagination widget
self.updatePagination(data.num);
if (self.loaded !== undefined) {
self.loaded();
}
});
};
/**
* Display the given message to the user.
*
* @param {jQuery} $message wrapper with message
*/
H5PDataView.prototype.setMessage = function ($message) {
var self = this;
if (self.table === undefined) {
self.$container.html('').append($message);
}
else {
self.table.setBody($message);
}
};
/**
* Update table data.
*
* @param {Array} rows
*/
H5PDataView.prototype.updateTable = function (rows) {
var self = this;
if (self.table === undefined) {
// Clear out container
self.$container.html('');
// Add filters
self.addFilters();
// Add toggler for others' content
if (H5PIntegration.user && parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) > 0) {
// canToggleViewOthersH5PContents = 1 is setting for only showing current user's contents
self.addOthersContentToggler(parseInt(H5PIntegration.user.canToggleViewOthersH5PContents) === 1);
}
// Add facets
self.$facets = $('<div/>', {
'class': 'h5p-facet-wrapper',
appendTo: self.$container
});
// Create new table
self.table = new H5PUtils.Table(self.classes, self.headers);
self.table.setHeaders(self.headers, function (order) {
// Sorting column or direction has changed.
self.order = order;
self.loadData();
}, self.order);
self.table.appendTo(self.$container);
}
// Process cell data before updating table
for (var i = 0; i < self.headers.length; i++) {
if (self.headers[i].facet === true) {
// Process rows for col, expect object or array
for (var j = 0; j < rows.length; j++) {
rows[j][i] = self.createFacets(rows[j][i], i);
}
}
}
// Add/update rows
var $tbody = self.table.setRows(rows);
// Add event handlers for facets
$('.h5p-facet', $tbody).click(function () {
var $facet = $(this);
self.filterByFacet($facet.data('col'), $facet.data('id'), $facet.text());
}).keypress(function (event) {
if (event.which === 32) {
var $facet = $(this);
self.filterByFacet($facet.data('col'), $facet.data('id'), $facet.text());
}
});
};
/**
* Create button for adding facet to filter.
*
* @param (object|Array) input
* @param number col ID of column
*/
H5PDataView.prototype.createFacets = function (input, col) {
var facets = '';
if (input instanceof Array) {
// Facet can be filtered on multiple values at the same time
for (var i = 0; i < input.length; i++) {
if (facets !== '') {
facets += ', ';
}
facets += '<span class="h5p-facet" role="button" tabindex="0" data-id="' + input[i].id + '" data-col="' + col + '">' + input[i].title + '</span>';
}
}
else {
// Single value facet filtering
facets += '<span class="h5p-facet" role="button" tabindex="0" data-id="' + input.id + '" data-col="' + col + '">' + input.title + '</span>';
}
return facets === '' ? '—' : facets;
};
/**
* Adds a filter based on the given facet.
*
* @param number col ID of column we're filtering
* @param number id ID to filter on
* @param string text Human readable label for the filter
*/
H5PDataView.prototype.filterByFacet = function (col, id, text) {
var self = this;
if (self.facets[col] !== undefined) {
if (self.facets[col].id === id) {
return; // Don't use the same filter again
}
// Remove current filter for this col
self.facets[col].$tag.remove();
}
// Add to UI
self.facets[col] = {
id: id,
'$tag': $('<span/>', {
'class': 'h5p-facet-tag',
text: text,
appendTo: self.$facets,
})
};
/**
* Callback for removing filter.
*
* @private
*/
var remove = function () {
// Uncheck toggler for others' H5P contents
if ( self.$othersContentToggler && self.facets.hasOwnProperty( self.columnIdAuthor ) ) {
self.$othersContentToggler.prop('checked', false );
}
self.facets[col].$tag.remove();
delete self.facets[col];
self.loadData();
};
// Remove button
$('<span/>', {
role: 'button',
tabindex: 0,
appendTo: self.facets[col].$tag,
text: self.l10n.remove,
title: self.l10n.remove,
on: {
click: remove,
keypress: function (event) {
if (event.which === 32) {
remove();
}
}
}
});
// Load data with new filter
self.loadData();
};
/**
* Update pagination widget.
*
* @param {Number} num size of data collection
*/
H5PDataView.prototype.updatePagination = function (num) {
var self = this;
if (self.pagination === undefined) {
if (self.table === undefined) {
// No table, no pagination
return;
}
// Create new widget
var $pagerContainer = $('<div/>', {'class': 'h5p-pagination'});
self.pagination = new H5PUtils.Pagination(num, self.limit, function (offset) {
// Handle page changes in pagination widget
self.offset = offset;
self.loadData();
}, self.l10n);
self.pagination.appendTo($pagerContainer);
self.table.setFoot($pagerContainer);
}
else {
// Update existing widget
self.pagination.update(num, self.limit);
}
};
/**
* Add filters.
*/
H5PDataView.prototype.addFilters = function () {
var self = this;
for (var i = 0; i < self.filters.length; i++) {
if (self.filters[i] === true) {
// Add text input filter for col i
self.addTextFilter(i);
}
}
};
/**
* Add text filter for given col num.
*
* @param {Number} col
*/
H5PDataView.prototype.addTextFilter = function (col) {
var self = this;
/**
* Find input value and filter on it.
* @private
*/
var search = function () {
var filterOn = $input.val().replace(/^\s+|\s+$/g, '');
if (filterOn === '') {
filterOn = undefined;
}
if (filterOn !== self.filterOn[col]) {
self.filterOn[col] = filterOn;
self.loadData();
}
};
// Add text field for filtering
var typing;
var $input = $('<input/>', {
type: 'text',
placeholder: self.l10n.search,
on: {
'blur': function () {
clearTimeout(typing);
search();
},
'keyup': function (event) {
if (event.keyCode === 13) {
clearTimeout(typing);
search();
return false;
}
else {
clearTimeout(typing);
typing = setTimeout(function () {
search();
}, 500);
}
}
}
}).appendTo(self.$container);
};
/**
* Add toggle for others' H5P content.
* @param {boolean} [checked=false] Initial check setting.
*/
H5PDataView.prototype.addOthersContentToggler = function (checked) {
var self = this;
checked = (typeof checked === 'undefined') ? false : checked;
// Checkbox
this.$othersContentToggler = $('<input/>', {
type: 'checkbox',
'class': 'h5p-others-contents-toggler',
'id': 'h5p-others-contents-toggler',
'checked': checked,
'click': function () {
if ( this.checked ) {
// Add filter on current user
self.filterByFacet( self.columnIdAuthor, H5PIntegration.user.id, H5PIntegration.user.name );
}
else {
// Remove facet indicator and reload full data view
if ( self.facets.hasOwnProperty( self.columnIdAuthor ) && self.facets[self.columnIdAuthor].$tag ) {
self.facets[self.columnIdAuthor].$tag.remove();
}
delete self.facets[self.columnIdAuthor];
self.loadData();
}
}
});
// Label
var $label = $('<label>', {
'class': 'h5p-others-contents-toggler-label',
'text': this.l10n.showOwnContentOnly,
'for': 'h5p-others-contents-toggler'
}).prepend(this.$othersContentToggler);
$('<div>', {
'class': 'h5p-others-contents-toggler-wrapper'
}).append($label)
.appendTo(this.$container);
};
return H5PDataView;
})(H5P.jQuery);
+54
View File
@@ -0,0 +1,54 @@
/**
* Utility that makes it possible to hide fields when a checkbox is unchecked
*/
(function ($) {
function setupHiding() {
var $toggler = $(this);
// Getting the field which should be hidden:
var $subject = $($toggler.data('h5p-visibility-subject-selector'));
var toggle = function () {
$subject.toggle($toggler.is(':checked'));
};
$toggler.change(toggle);
toggle();
}
function setupRevealing() {
var $button = $(this);
// Getting the field which should have the value:
var $input = $('#' + $button.data('control'));
if (!$input.data('value')) {
$button.remove();
return;
}
// Setup button action
var revealed = false;
var text = $button.html();
$button.click(function () {
if (revealed) {
$input.val('');
$button.html(text);
revealed = false;
}
else {
$input.val($input.data('value'));
$button.html($button.data('hide'));
revealed = true;
}
});
}
$(document).ready(function () {
// Get the checkboxes making other fields being hidden:
$('.h5p-visibility-toggler').each(setupHiding);
// Get the buttons making other fields have hidden values:
$('.h5p-reveal-value').each(setupRevealing);
});
})(H5P.jQuery);
+75
View File
@@ -0,0 +1,75 @@
/*jshint multistr: true */
/**
* Converts old script tag embed to iframe
*/
var H5POldEmbed = H5POldEmbed || (function () {
var head = document.getElementsByTagName('head')[0];
var resizer = false;
/**
* Loads the resizing script
*/
var loadResizer = function (url) {
var data, callback = 'H5POldEmbed';
resizer = true;
// Callback for when content data is loaded.
window[callback] = function (content) {
// Add resizing script to head
var resizer = document.createElement('script');
resizer.src = content;
head.appendChild(resizer);
// Clean up
head.removeChild(data);
delete window[callback];
};
// Create data script
data = document.createElement('script');
data.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback;
head.appendChild(data);
};
/**
* Replaced script tag with iframe
*/
var addIframe = function (script) {
// Add iframe
var iframe = document.createElement('iframe');
iframe.src = script.getAttribute('data-h5p');
iframe.frameBorder = false;
iframe.allowFullscreen = true;
var parent = script.parentNode;
parent.insertBefore(iframe, script);
parent.removeChild(script);
};
/**
* Go throught all script tags with the data-h5p attribute and load content.
*/
function H5POldEmbed() {
var scripts = document.getElementsByTagName('script');
var h5ps = []; // Use seperate array since scripts grow in size.
for (var i = 0; i < scripts.length; i++) {
var script = scripts[i];
if (script.src.indexOf('/h5p-resizer.js') !== -1) {
resizer = true;
}
else if (script.hasAttribute('data-h5p')) {
h5ps.push(script);
}
}
for (i = 0; i < h5ps.length; i++) {
if (!resizer) {
loadResizer(h5ps[i].getAttribute('data-h5p'));
}
addIframe(h5ps[i]);
}
}
return H5POldEmbed;
})();
new H5POldEmbed();
+258
View File
@@ -0,0 +1,258 @@
var H5P = window.H5P = window.H5P || {};
/**
* The Event class for the EventDispatcher.
*
* @class
* @param {string} type
* @param {*} data
* @param {Object} [extras]
* @param {boolean} [extras.bubbles]
* @param {boolean} [extras.external]
*/
H5P.Event = function (type, data, extras) {
this.type = type;
this.data = data;
var bubbles = false;
// Is this an external event?
var external = false;
// Is this event scheduled to be sent externally?
var scheduledForExternal = false;
if (extras === undefined) {
extras = {};
}
if (extras.bubbles === true) {
bubbles = true;
}
if (extras.external === true) {
external = true;
}
/**
* Prevent this event from bubbling up to parent
*/
this.preventBubbling = function () {
bubbles = false;
};
/**
* Get bubbling status
*
* @returns {boolean}
* true if bubbling false otherwise
*/
this.getBubbles = function () {
return bubbles;
};
/**
* Try to schedule an event for externalDispatcher
*
* @returns {boolean}
* true if external and not already scheduled, otherwise false
*/
this.scheduleForExternal = function () {
if (external && !scheduledForExternal) {
scheduledForExternal = true;
return true;
}
return false;
};
};
/**
* Callback type for event listeners.
*
* @callback H5P.EventCallback
* @param {H5P.Event} event
*/
H5P.EventDispatcher = (function () {
/**
* The base of the event system.
* Inherit this class if you want your H5P to dispatch events.
*
* @class
* @memberof H5P
*/
function EventDispatcher() {
var self = this;
/**
* Keep track of listeners for each event.
*
* @private
* @type {Object}
*/
var triggers = {};
/**
* Add new event listener.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
* @param {Object} [thisArg]
* Optionally specify the this value when calling listener.
*/
this.on = function (type, listener, thisArg) {
if (typeof listener !== 'function') {
throw TypeError('listener must be a function');
}
// Trigger event before adding to avoid recursion
self.trigger('newListener', {'type': type, 'listener': listener});
var trigger = {'listener': listener, 'thisArg': thisArg};
if (!triggers[type]) {
// First
triggers[type] = [trigger];
}
else {
// Append
triggers[type].push(trigger);
}
};
/**
* Add new event listener that will be fired only once.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
* @param {Object} thisArg
* Optionally specify the this value when calling listener.
*/
this.once = function (type, listener, thisArg) {
if (!(listener instanceof Function)) {
throw TypeError('listener must be a function');
}
var once = function (event) {
self.off(event.type, once);
listener.call(this, event);
};
self.on(type, once, thisArg);
};
/**
* Remove event listener.
* If no listener is specified, all listeners will be removed.
*
* @throws {TypeError}
* listener must be a function
* @param {string} type
* Event type
* @param {H5P.EventCallback} listener
* Event listener
*/
this.off = function (type, listener) {
if (listener !== undefined && !(listener instanceof Function)) {
throw TypeError('listener must be a function');
}
if (triggers[type] === undefined) {
return;
}
if (listener === undefined) {
// Remove all listeners
delete triggers[type];
self.trigger('removeListener', type);
return;
}
// Find specific listener
for (var i = 0; i < triggers[type].length; i++) {
if (triggers[type][i].listener === listener) {
triggers[type].splice(i, 1);
self.trigger('removeListener', type, {'listener': listener});
break;
}
}
// Clean up empty arrays
if (!triggers[type].length) {
delete triggers[type];
}
};
/**
* Try to call all event listeners for the given event type.
*
* @private
* @param {string} Event type
*/
var call = function (type, event) {
if (triggers[type] === undefined) {
return;
}
// Clone array (prevents triggers from being modified during the event)
var handlers = triggers[type].slice();
// Call all listeners
for (var i = 0; i < handlers.length; i++) {
var trigger = handlers[i];
var thisArg = (trigger.thisArg ? trigger.thisArg : this);
trigger.listener.call(thisArg, event);
}
};
/**
* Dispatch event.
*
* @param {string|H5P.Event} event
* Event object or event type as string
* @param {*} [eventData]
* Custom event data(used when event type as string is used as first
* argument).
* @param {Object} [extras]
* @param {boolean} [extras.bubbles]
* @param {boolean} [extras.external]
*/
this.trigger = function (event, eventData, extras) {
if (event === undefined) {
return;
}
if (event instanceof String || typeof event === 'string') {
event = new H5P.Event(event, eventData, extras);
}
else if (eventData !== undefined) {
event.data = eventData;
}
// Check to see if this event should go externally after all triggering and bubbling is done
var scheduledForExternal = event.scheduleForExternal();
// Call all listeners
call.call(this, event.type, event);
// Call all * listeners
call.call(this, '*', event);
// Bubble
if (event.getBubbles() && self.parent instanceof H5P.EventDispatcher &&
(self.parent.trigger instanceof Function || typeof self.parent.trigger === 'function')) {
self.parent.trigger(event);
}
if (scheduledForExternal) {
H5P.externalDispatcher.trigger.call(this, event);
}
};
}
return EventDispatcher;
})();
+37
View File
@@ -0,0 +1,37 @@
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=57)}([function(e,t,n){"use strict";e.exports=n(19)},function(e,t,n){e.exports=n(28)()},function(e,t,n){"use strict";var r=n(8),i=Object.prototype.toString;function o(e){return"[object Array]"===i.call(e)}function a(e){return void 0===e}function l(e){return null!==e&&"object"==typeof e}function u(e){if("[object Object]"!==i.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function c(e){return"[object Function]"===i.call(e)}function s(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),o(e))for(var n=0,r=e.length;n<r;n++)t.call(null,e[n],n,e);else for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.call(null,e[i],i,e)}e.exports={isArray:o,isArrayBuffer:function(e){return"[object ArrayBuffer]"===i.call(e)},isBuffer:function(e){return null!==e&&!a(e)&&null!==e.constructor&&!a(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)},isFormData:function(e){return"undefined"!=typeof FormData&&e instanceof FormData},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer},isString:function(e){return"string"==typeof e},isNumber:function(e){return"number"==typeof e},isObject:l,isPlainObject:u,isUndefined:a,isDate:function(e){return"[object Date]"===i.call(e)},isFile:function(e){return"[object File]"===i.call(e)},isBlob:function(e){return"[object Blob]"===i.call(e)},isFunction:c,isStream:function(e){return l(e)&&c(e.pipe)},isURLSearchParams:function(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)},forEach:s,merge:function e(){var t={};function n(n,r){u(t[r])&&u(n)?t[r]=e(t[r],n):u(n)?t[r]=e({},n):o(n)?t[r]=n.slice():t[r]=n}for(var r=0,i=arguments.length;r<i;r++)s(arguments[r],n);return t},extend:function(e,t,n){return s(t,(function(t,i){e[i]=n&&"function"==typeof t?r(t,n):t})),e},trim:function(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}}},function(e,t,n){var r=n(23),i=n(24),o=n(25),a=n(27);e.exports=function(e,t){return r(e)||i(e,t)||o(e,t)||a()}},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){e.exports=n(32)},function(e,t){var n,r,i=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function l(e){if(n===setTimeout)return setTimeout(e,0);if((n===o||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:o}catch(e){n=o}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var u,c=[],s=!1,f=-1;function d(){s&&u&&(s=!1,u.length?c=u.concat(c):f=-1,c.length&&p())}function p(){if(!s){var e=l(d);s=!0;for(var t=c.length;t;){for(u=c,c=[];++f<t;)u&&u[f].run();f=-1,t=c.length}u=null,s=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===a||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function h(e,t){this.fun=e,this.array=t}function m(){}i.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new h(e,t)),1!==c.length||s||l(p)},h.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=m,i.addListener=m,i.once=m,i.off=m,i.removeListener=m,i.removeAllListeners=m,i.emit=m,i.prependListener=m,i.prependOnceListener=m,i.listeners=function(e){return[]},i.binding=function(e){throw new Error("process.binding is not supported")}Line truncated
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/var r=Object.getOwnPropertySymbols,i=Object.prototype.hasOwnProperty,o=Object.prototype.propertyIsEnumerable;function a(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,l,u=a(e),c=1;c<arguments.length;c++){for(var s in n=Object(arguments[c]))i.call(n,s)&&(u[s]=n[s]);if(r){l=r(n);for(var f=0;f<l.length;f++)o.call(n,l[f])&&(u[l[f]]=n[l[f]])}}return u}},function(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";var r=n(2);function i(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var o;if(n)o=n(t);else if(r.isURLSearchParams(t))o=t.toString();else{var a=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),a.push(i(t)+"="+i(e))})))})),o=a.join("&")}if(o){var l=e.indexOf("#");-1!==l&&(e=e.slice(0,l)),e+=(-1===e.indexOf("?")?"?":"&")+o}return e}},function(e,t,n){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";(function(t){var r=n(2),i=n(37),o={"Content-Type":"application/x-www-form-urlencoded"};function a(e,t){!r.isUndefined(e)&&r.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var l,u={adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==t&&"[object process]"===Object.prototype.toString.call(t))&&(l=n(12)),l),transformRequest:[function(e,t){return i(t,"Accept"),i(t,"Content-Type"),r.isFormData(e)||r.isArrayBuffer(e)||r.isBuffer(e)||r.isStream(e)||r.isFile(e)||r.isBlob(e)?e:r.isArrayBufferView(e)?e.buffer:r.isURLSearchParams(e)?(a(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):r.isObject(e)?(a(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){u.headers[e]=r.merge(o)})),e.exports=u}).call(this,n(6))},function(e,t,n){"use strict";var r=n(2),i=n(38),o=n(40),a=n(9),l=n(41),u=n(44),c=n(45),s=n(13);e.exports=function(e){return new Promise((function(t,n){var f=e.data,d=e.headers;r.isFormData(f)&&delete d["Content-Type"];var p=new XMLHttpRequest;if(e.auth){var h=e.auth.username||"",m=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";d.Authorization="Basic "+btoa(h+":"+m)}var v=l(e.baseURL,e.url);if(p.open(e.method.toUpperCase(),a(v,e.params,e.paramsSerializer),!0),p.timeout=e.timeout,p.onreadystatechange=function(){if(p&&4===p.readyState&&(0!==p.status||p.responseURL&&0===p.responseURL.indexOf("file:"))){var r="getAllResponseHeaders"in p?u(p.getAllResponseHeaders()):null,o={data:e.responseType&&"text"!==e.responseType?p.response:p.responseText,status:p.status,statusText:p.statusText,headers:r,config:e,request:p};i(t,n,o),p=null}},p.onabort=function(){p&&(n(s("Request aborted",e,"ECONNABORTED",p)),p=null)},p.onerror=function(){n(s("Network Error",e,null,p)),p=null},p.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(s(t,e,"ECONNABORTED",p)),p=null},r.isStandardBrowserEnv()){var g=(e.withCredentials||c(v))&&e.xsrfCookieName?o.read(e.xsrfCookieName):void 0;g&&(d[e.xsrfHeaderName]=g)}if("setRequestHeader"in p&&r.forEach(d,(function(e,t){void 0===f&&"content-type"===t.toLowerCase()?delete d[t]:p.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(p.withCredentials=!!e.withCredentials),e.responseType)try{p.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&p.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&p.upload&&p.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then((function(e){p&&(p.abort(),n(e),p=null)})),f||(f=null),p.send(f)}))}},function(e,t,n){"use strict";var r=n(39);e.exports=function(e,t,n,i,o){var a=new Error(e);return r(a,t,n,i,o)}},function(e,t,nLine truncated
/*!
* @overview es6-promise - a tiny implementation of Promises/A+.
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
* @license Licensed under MIT license
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
* @version v4.2.8+1e68dce6
*/var r;r=function(){"use strict";function e(e){return"function"==typeof e}var r=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},i=0,o=void 0,a=void 0,l=function(e,t){h[i]=e,h[i+1]=t,2===(i+=2)&&(a?a(m):w())},u="undefined"!=typeof window?window:void 0,c=u||{},s=c.MutationObserver||c.WebKitMutationObserver,f="undefined"==typeof self&&void 0!==t&&"[object process]"==={}.toString.call(t),d="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function p(){var e=setTimeout;return function(){return e(m,1)}}var h=new Array(1e3);function m(){for(var e=0;e<i;e+=2)(0,h[e])(h[e+1]),h[e]=void 0,h[e+1]=void 0;i=0}var v,g,y,b,w=void 0;function k(e,t){var n=this,r=new this.constructor(T);void 0===r[E]&&I(r);var i=n._state;if(i){var o=arguments[i-1];l((function(){return z(i,r,o,n._result)}))}else O(n,r,e,t);return r}function x(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(T);return C(t,e),t}f?w=function(){return t.nextTick(m)}:s?(g=0,y=new s(m),b=document.createTextNode(""),y.observe(b,{characterData:!0}),w=function(){b.data=g=++g%2}):d?((v=new MessageChannel).port1.onmessage=m,w=function(){return v.port2.postMessage(0)}):w=void 0===u?function(){try{var e=Function("return this")().require("vertx");return void 0!==(o=e.runOnLoop||e.runOnContext)?function(){o(m)}:p()}catch(e){return p()}}():p();var E=Math.random().toString(36).substring(2);function T(){}function S(t,n,r){n.constructor===t.constructor&&r===k&&n.constructor.resolve===x?function(e,t){1===t._state?P(e,t._result):2===t._state?N(e,t._result):O(t,void 0,(function(t){return C(e,t)}),(function(t){return N(e,t)}))}(t,n):void 0===r?P(t,n):e(r)?function(e,t,n){l((function(e){var r=!1,i=function(e,t,n,r){try{e.call(t,n,r)}catch(e){return e}}(n,t,(function(n){r||(r=!0,t!==n?C(e,n):P(e,n))}),(function(t){r||(r=!0,N(e,t))}),e._label);!r&&i&&(r=!0,N(e,i))}),e)}(t,n,r):P(t,n)}function C(e,t){if(e===t)N(e,new TypeError("You cannot resolve a promise with itself"));else if(i=typeof(r=t),null===r||"object"!==i&&"function"!==i)P(e,t);else{var n=void 0;try{n=t.then}catch(t){return void N(e,t)}S(e,t,n)}var r,i}function _(e){e._onerror&&e._onerror(e._result),R(e)}function P(e,t){void 0===e._state&&(e._result=t,e._state=1,0!==e._subscribers.length&&l(R,e))}function N(e,t){void 0===e._state&&(e._state=2,e._result=t,l(_,e))}function O(e,t,n,r){var i=e._subscribers,o=i.length;e._onerror=null,i[o]=t,i[o+1]=n,i[o+2]=r,0===o&&e._state&&l(R,e)}function R(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r=void 0,i=void 0,o=e._result,a=0;a<t.length;a+=3)r=t[a],i=t[a+n],r?z(n,r,i,o):i(o);e._subscribers.length=0}}function z(t,n,r,i){var o=e(r),a=void 0,l=void 0,u=!0;if(o){try{a=r(i)}catch(e){u=!1,l=e}if(n===a)return void N(n,new TypeError("A promises callback cannot return that same promise."))}else a=i;void 0!==n._state||(o&&u?C(n,a):!1===u?N(n,l):1===t?P(n,a):2===t&&N(n,a))}var L=0;function I(e){e[E]=L++,e._state=void 0,e._result=void 0,e._subscribers=[]}var D=function(){function e(e,t){this._instanceConstructor=e,this.promise=new e(T),this.promise[E]||I(this.promise),r(t)?(this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?P(this.promise,this._result):(this.length=this.length||0,this._enumerate(t),0===this._remaining&&P(this.promise,this._result))):N(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;void 0===this._state&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,r=n.resolve;if(r===x){var i=void 0,o=void 0,a=!1;try{i=e.then}catch(e){a=!0,o=e}if(i===k&&void 0!==e._state)this._settledAt(e._state,t,e._result);else if("function"!=typeof i)this._remaining--,this._result[t]=e;else if(n===M){var l=new n(T);a?N(l,o):S(l,e,i),this._willSettleAt(l,t)}else this._willSettleAt(new n((function(t){return t(e)})),t)}else this._willSettleAt(r(e),t)},e.prototype._settledAt=function(e,t,n){var r=this.promise;void 0===r._state&&(this._remaining--,2===e?N(r,n):this._result[t]=n),0===this._remaining&&P(r,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;O(e,void 0,(function(e){return n._settledAt(1,t,e)}),(function(e){return n._settledAt(2,t,e)}))},e}(),M=function(){function t(e){this[E]=L++,this._result=this._state=void 0,this._subscribers=[],T!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t((function(t){C(e,t)}),(function(t){N(e,t)}))}catch(t){N(e,t)}}(this,e):function(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}())}return t.prototype.catch=function(e){return this.then(null,e)},t.prototype.finally=function(t){var n=this.constructor;returLine truncated
/** @license React v16.14.0
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r=n(7),i="function"==typeof Symbol&&Symbol.for,o=i?Symbol.for("react.element"):60103,a=i?Symbol.for("react.portal"):60106,l=i?Symbol.for("react.fragment"):60107,u=i?Symbol.for("react.strict_mode"):60108,c=i?Symbol.for("react.profiler"):60114,s=i?Symbol.for("react.provider"):60109,f=i?Symbol.for("react.context"):60110,d=i?Symbol.for("react.forward_ref"):60112,p=i?Symbol.for("react.suspense"):60113,h=i?Symbol.for("react.memo"):60115,m=i?Symbol.for("react.lazy"):60116,v="function"==typeof Symbol&&Symbol.iterator;function g(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var y={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},b={};function w(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||y}function k(){}function x(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||y}w.prototype.isReactComponent={},w.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(g(85));this.updater.enqueueSetState(this,e,t,"setState")},w.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},k.prototype=w.prototype;var E=x.prototype=new k;E.constructor=x,r(E,w.prototype),E.isPureReactComponent=!0;var T={current:null},S=Object.prototype.hasOwnProperty,C={key:!0,ref:!0,__self:!0,__source:!0};function _(e,t,n){var r,i={},a=null,l=null;if(null!=t)for(r in void 0!==t.ref&&(l=t.ref),void 0!==t.key&&(a=""+t.key),t)S.call(t,r)&&!C.hasOwnProperty(r)&&(i[r]=t[r]);var u=arguments.length-2;if(1===u)i.children=n;else if(1<u){for(var c=Array(u),s=0;s<u;s++)c[s]=arguments[s+2];i.children=c}if(e&&e.defaultProps)for(r in u=e.defaultProps)void 0===i[r]&&(i[r]=u[r]);return{$$typeof:o,type:e,key:a,ref:l,props:i,_owner:T.current}}function P(e){return"object"==typeof e&&null!==e&&e.$$typeof===o}var N=/\/+/g,O=[];function R(e,t,n,r){if(O.length){var i=O.pop();return i.result=e,i.keyPrefix=t,i.func=n,i.context=r,i.count=0,i}return{result:e,keyPrefix:t,func:n,context:r,count:0}}function z(e){e.result=null,e.keyPrefix=null,e.func=null,e.context=null,e.count=0,10>O.length&&O.push(e)}function L(e,t,n){return null==e?0:function e(t,n,r,i){var l=typeof t;"undefined"!==l&&"boolean"!==l||(t=null);var u=!1;if(null===t)u=!0;else switch(l){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case o:case a:u=!0}}if(u)return r(i,t,""===n?"."+I(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var c=0;c<t.length;c++){var s=n+I(l=t[c],c);u+=e(l,s,r,i)}else if(null===t||"object"!=typeof t?s=null:s="function"==typeof(s=v&&t[v]||t["@@iterator"])?s:null,"function"==typeof s)for(t=s.call(t),c=0;!(l=t.next()).done;)u+=e(l=l.value,s=n+I(l,c++),r,i);else if("object"===l)throw r=""+t,Error(g(31,"[object Object]"===r?"object with keys {"+Object.keys(t).join(", ")+"}":r,""));return u}(e,"",t,n)}function I(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,(function(e){return t[e]}))}(e.key):t.toString(36)}function D(e,t){e.func.call(e.context,t,e.count++)}function M(e,t,n){var r=e.result,i=e.keyPrefix;e=e.func.call(e.context,t,e.count++),Array.isArray(e)?j(e,r,n,(function(e){return e})):null!=e&&(P(e)&&(e=function(e,t){return{$$typeof:o,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(e,i+(!e.key||t&&t.key===e.key?"":(""+e.key).replace(N,"$&/")+"/")+n)),r.push(e))}function j(e,t,n,r,i){var o="";null!=n&&(o=(""+n).replace(N,"$&/")+"/"),L(e,M,t=R(t,o,r,i)),z(t)}var A={current:null};function F(){var e=A.current;if(null===e)throw Error(g(321));return e}var U={ReactCurrentDispatcher:A,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:T,IsSomeRendererActing:{current:!1},assign:r};t.Children={map:function(e,t,n){if(null==e)return e;var r=[];return j(e,r,null,t,n),r},forEach:function(e,t,n){if(null==e)return e;L(e,D,t=R(null,null,t,n)),z(t)},count:function(e){return L(e,(function(){return null}),null)},toArray:function(e){var t=[];return j(e,t,null,(function(e){return e})),t},only:function(e){if(!P(e))throw Error(g(143));return e}},t.Component=w,t.Fragment=l,t.Profiler=c,t.PureComponent=x,t.StrictMode=u,t.Suspense=p,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=U,t.cloneElement=function(e,t,n){if(null==e)throw Error(g(267,e));var i=r({},e.props),a=e.key,l=e.ref,u=e._owner;if(null!=t){if(void 0!==t.ref&&(l=t.ref,u=T.current),void 0!==t.key&&(a=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(s in t)S.call(t,s)&&!C.hasOwnProperty(s)&&(i[s]=void 0===t[s]&&void 0!==c?c[s]:t[s])}var s=arguments.length-2;if(1===s)i.children=n;else if(1<s){c=Array(s);for(var f=0;f<s;f++)c[f]=arguments[f+2];i.children=c}return{$$typeof:o,typLine truncated
/** @license React v16.14.0
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r=n(0),i=n(7),o=n(21);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!r)throw Error(a(227));function l(e,t,n,r,i,o,a,l,u){var c=Array.prototype.slice.call(arguments,3);try{t.apply(n,c)}catch(e){this.onError(e)}}var u=!1,c=null,s=!1,f=null,d={onError:function(e){u=!0,c=e}};function p(e,t,n,r,i,o,a,s,f){u=!1,c=null,l.apply(d,arguments)}var h=null,m=null,v=null;function g(e,t,n){var r=e.type||"unknown-event";e.currentTarget=v(n),function(e,t,n,r,i,o,l,d,h){if(p.apply(this,arguments),u){if(!u)throw Error(a(198));var m=c;u=!1,c=null,s||(s=!0,f=m)}}(r,t,void 0,e),e.currentTarget=null}var y=null,b={};function w(){if(y)for(var e in b){var t=b[e],n=y.indexOf(e);if(!(-1<n))throw Error(a(96,e));if(!x[n]){if(!t.extractEvents)throw Error(a(97,e));for(var r in x[n]=t,n=t.eventTypes){var i=void 0,o=n[r],l=t,u=r;if(E.hasOwnProperty(u))throw Error(a(99,u));E[u]=o;var c=o.phasedRegistrationNames;if(c){for(i in c)c.hasOwnProperty(i)&&k(c[i],l,u);i=!0}else o.registrationName?(k(o.registrationName,l,u),i=!0):i=!1;if(!i)throw Error(a(98,r,e))}}}}function k(e,t,n){if(T[e])throw Error(a(100,e));T[e]=t,S[e]=t.eventTypes[n].dependencies}var x=[],E={},T={},S={};function C(e){var t,n=!1;for(t in e)if(e.hasOwnProperty(t)){var r=e[t];if(!b.hasOwnProperty(t)||b[t]!==r){if(b[t])throw Error(a(102,t));b[t]=r,n=!0}}n&&w()}var _=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),P=null,N=null,O=null;function R(e){if(e=m(e)){if("function"!=typeof P)throw Error(a(280));var t=e.stateNode;t&&(t=h(t),P(e.stateNode,e.type,t))}}function z(e){N?O?O.push(e):O=[e]:N=e}function L(){if(N){var e=N,t=O;if(O=N=null,R(e),t)for(e=0;e<t.length;e++)R(t[e])}}function I(e,t){return e(t)}function D(e,t,n,r,i){return e(t,n,r,i)}function M(){}var j=I,A=!1,F=!1;function U(){null===N&&null===O||(M(),L())}function B(e,t,n){if(F)return e(t,n);F=!0;try{return j(e,t,n)}finally{F=!1,U()}}var V=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,H=Object.prototype.hasOwnProperty,W={},q={};function Q(e,t,n,r,i,o){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=i,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=o}var $={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){$[e]=new Q(e,0,!1,e,null,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];$[t]=new Q(t,1,!1,e[1],null,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){$[e]=new Q(e,2,!1,e.toLowerCase(),null,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){$[e]=new Q(e,2,!1,e,null,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){$[e]=new Q(e,3,!1,e.toLowerCase(),null,!1)})),["checked","multiple","muted","selected"].forEach((function(e){$[e]=new Q(e,3,!0,e,null,!1)})),["capture","download"].forEach((function(e){$[e]=new Q(e,4,!1,e,null,!1)})),["cols","rows","size","span"].forEach((function(e){$[e]=new Q(e,6,!1,e,null,!1)})),["rowSpan","start"].forEach((function(e){$[e]=new Q(e,5,!1,e.toLowerCase(),null,!1)}));var K=/[\-:]([a-z])/g;function Y(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-rangLine truncated
/** @license React v0.19.1
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r,i,o,a,l;if("undefined"==typeof window||"function"!=typeof MessageChannel){var u=null,c=null,s=function(){if(null!==u)try{var e=t.unstable_now();u(!0,e),u=null}catch(e){throw setTimeout(s,0),e}},f=Date.now();t.unstable_now=function(){return Date.now()-f},r=function(e){null!==u?setTimeout(r,0,e):(u=e,setTimeout(s,0))},i=function(e,t){c=setTimeout(e,t)},o=function(){clearTimeout(c)},a=function(){return!1},l=t.unstable_forceFrameRate=function(){}}else{var d=window.performance,p=window.Date,h=window.setTimeout,m=window.clearTimeout;if("undefined"!=typeof console){var v=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof v&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof d&&"function"==typeof d.now)t.unstable_now=function(){return d.now()};else{var g=p.now();t.unstable_now=function(){return p.now()-g}}var y=!1,b=null,w=-1,k=5,x=0;a=function(){return t.unstable_now()>=x},l=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):k=0<e?Math.floor(1e3/e):5};var E=new MessageChannel,T=E.port2;E.port1.onmessage=function(){if(null!==b){var e=t.unstable_now();x=e+k;try{b(!0,e)?T.postMessage(null):(y=!1,b=null)}catch(e){throw T.postMessage(null),e}}else y=!1},r=function(e){b=e,y||(y=!0,T.postMessage(null))},i=function(e,n){w=h((function(){e(t.unstable_now())}),n)},o=function(){m(w),w=-1}}function S(e,t){var n=e.length;e.push(t);e:for(;;){var r=n-1>>>1,i=e[r];if(!(void 0!==i&&0<P(i,t)))break e;e[r]=t,e[n]=i,n=r}}function C(e){return void 0===(e=e[0])?null:e}function _(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,i=e.length;r<i;){var o=2*(r+1)-1,a=e[o],l=o+1,u=e[l];if(void 0!==a&&0>P(a,n))void 0!==u&&0>P(u,a)?(e[r]=u,e[l]=n,r=l):(e[r]=a,e[o]=n,r=o);else{if(!(void 0!==u&&0>P(u,n)))break e;e[r]=u,e[l]=n,r=l}}}return t}return null}function P(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var N=[],O=[],R=1,z=null,L=3,I=!1,D=!1,M=!1;function j(e){for(var t=C(O);null!==t;){if(null===t.callback)_(O);else{if(!(t.startTime<=e))break;_(O),t.sortIndex=t.expirationTime,S(N,t)}t=C(O)}}function A(e){if(M=!1,j(e),!D)if(null!==C(N))D=!0,r(F);else{var t=C(O);null!==t&&i(A,t.startTime-e)}}function F(e,n){D=!1,M&&(M=!1,o()),I=!0;var r=L;try{for(j(n),z=C(N);null!==z&&(!(z.expirationTime>n)||e&&!a());){var l=z.callback;if(null!==l){z.callback=null,L=z.priorityLevel;var u=l(z.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?z.callback=u:z===C(N)&&_(N),j(n)}else _(N);z=C(N)}if(null!==z)var c=!0;else{var s=C(O);null!==s&&i(A,s.startTime-n),c=!1}return c}finally{z=null,L=r,I=!1}}function U(e){switch(e){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=l;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){D||I||(D=!0,r(F))},t.unstable_getCurrentPriorityLevel=function(){return L},t.unstable_getFirstCallbackNode=function(){return C(N)},t.unstable_next=function(e){switch(L){case 1:case 2:case 3:var t=3;break;default:t=L}var n=L;L=t;try{return e()}finally{L=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=B,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=L;L=e;try{return t()}finally{L=n}},t.unstable_scheduleCallback=function(e,n,a){var l=t.unstable_now();if("object"==typeof a&&null!==a){var u=a.delay;u="number"==typeof u&&0<u?l+u:l,a="number"==typeof a.timeout?a.timeout:U(e)}else a=U(e),u=l;return e={id:R++,callback:n,priorityLevel:e,startTime:u,expirationTime:a=u+a,sortIndex:-1},u>l?(e.sortIndex=u,S(O,e),null===C(N)&&e===C(O)&&(M?o():M=!0,i(A,u-l))):(e.sortIndex=a,S(N,e),D||I||(D=!0,r(F))),e},t.unstable_shouldYield=function(){var e=t.unstable_now();j(e);var n=C(N);return n!==z&&null!==z&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime<z.expirationTime||a()},t.unstable_wrapCallback=function(e){var t=L;return function(){var n=L;L=t;try{return e.apply(this,arguments)}finally{L=n}}}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var n=[],r=!0,i=!1,o=void 0;try{for(var a,l=e[Symbol.iterator]();!(r=(a=l.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){i=!0,o=e}finally{try{r||null==l.return||l.return()}finally{if(i)throw o}}return n}}},function(e,t,n){var r=n(26) Line truncated
+54
View File
@@ -0,0 +1,54 @@
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=101)}([function(e,t,n){"use strict";e.exports=n(38)},function(e,t,n){e.exports=n(43)()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){var r=n(16),o=n(42),a=n(10),i=n(18);e.exports=function(e,t){return r(e)||o(e,t)||a(e,t)||i()}},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t,n){"use strict";var r=n(19),o=Object.prototype.toString;function a(e){return"[object Array]"===o.call(e)}function i(e){return void 0===e}function l(e){return null!==e&&"object"==typeof e}function u(e){if("[object Object]"!==o.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function s(e){return"[object Function]"===o.call(e)}function c(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),a(e))for(var n=0,r=e.length;n<r;n++)t.call(null,e[n],n,e);else for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.call(null,e[o],o,e)}e.exports={isArray:a,isArrayBuffer:function(e){return"[object ArrayBuffer]"===o.call(e)},isBuffer:function(e){return null!==e&&!i(e)&&null!==e.constructor&&!i(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)},isFormData:function(e){return"undefined"!=typeof FormData&&e instanceof FormData},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer},isString:function(e){return"string"==typeof e},isNumber:function(e){return"number"==typeof e},isObject:l,isPlainObject:u,isUndefined:i,isDate:function(e){return"[object Date]"===o.call(e)},isFile:function(e){return"[object File]"===o.call(e)},isBlob:function(e){return"[object Blob]"===o.call(e)},isFunction:s,isStream:function(e){return l(e)&&s(e.pipe)},isURLSearchParams:function(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)},forEach:c,merge:function e(){var t={};function n(n,r){u(t[r])&&u(n)?t[r]=e(t[r],n):u(n)?t[r]=e({},n):a(n)?t[r]=n.slice():t[r]=n}for(var r=0,o=arguments.length;r<o;r++)c(arguments[r],n);return t},extend:function(e,t,n){return c(t,(function(t,o){e[o]=n&&"function"==typeof t?r(t,n):t})),e},trim:function(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}}},function(e,t,n){var r=n(81),o=n(30),a=n(10),i=n(82);e.exports=function(e){return r(e)||o(e)||a(e)||i()}},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(39)},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}},function(e,t,n){var r=n(17);e.exports=function(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(e,t):void 0}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.canUseDOM=void 0;var r,o=n(72);var a=((r=o)&&r.__esModule?r:{default:r}).default,i=a.canUseDOM?window.HTMLElement:{};t.canUseDOM=a.canUseDOM;t.default=i},function(e,t,n){e.exports=n(50)},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e._Line truncated
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/var r=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,a=Object.prototype.propertyIsEnumerable;function i(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,l,u=i(e),s=1;s<arguments.length;s++){for(var c in n=Object(arguments[s]))o.call(n,c)&&(u[c]=n[c]);if(r){l=r(n);for(var f=0;f<l.length;f++)a.call(n,l[f])&&(u[l[f]]=n[l[f]])}}return u}},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}},function(e,t){e.exports=function(){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(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";var r=n(5);function o(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var a;if(n)a=n(t);else if(r.isURLSearchParams(t))a=t.toString();else{var i=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),i.push(o(t)+"="+o(e))})))})),a=i.join("&")}if(a){var l=e.indexOf("#");-1!==l&&(e=e.slice(0,l)),e+=(-1===e.indexOf("?")?"?":"&")+a}return e}},function(e,t,n){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";(function(t){var r=n(5),o=n(55),a={"Content-Type":"application/x-www-form-urlencoded"};function i(e,t){!r.isUndefined(e)&&r.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var l,u={adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==t&&"[object process]"===Object.prototype.toString.call(t))&&(l=n(23)),l),transformRequest:[function(e,t){return o(t,"Accept"),o(t,"Content-Type"),r.isFormData(e)||r.isArrayBuffer(e)||r.isBuffer(e)||r.isStream(e)||r.isFile(e)||r.isBlob(e)?e:r.isArrayBufferView(e)?e.buffer:r.isURLSearchParams(e)?(i(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):r.isObject(e)?(i(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){u.headers[e]=r.merge(a)})),e.exports=u}).call(this,n(14))},function(e,t,n){"use strict";var r=n(5),o=n(56),a=n(58),i=n(20),l=n(59),u=n(62),s=n(63),c=n(24);e.exports=function(e){return new Promise((function(t,n){var f=e.data,d=e.headers;r.isFormData(f)&&delete d["Content-Type"];var p=new XMLHttpRequest;if(e.auth){var h=e.auth.username||"",m=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";d.Authorization="Basic "+btoa(h+":"+m)}var v=l(e.baseURL,e.url);if(p.open(e.method.toUpperCase(),i(v,e.params,e.paramsSerializer),!0),p.timeout=e.timeout,p.onreadystatechange=function(){if(p&&4===p.readyState&&(0!==p.status||p.responseURL&&0===p.responseURL.indexOf("file:"))){var r="getAllResponseHeaders"in p?u(p.getAllResponseHeaders()):null,a={data:e.responseType&&"text"!==e.responseType?p.response:p.responseText,status:p.status,statusText:p.statusText,headers:r,config:e,request:p};o(t,n,a),p=null}},p.onabort=function(){p&&(n(c("Request aborted",e,"ECONNABORTED",p)),p=null)},p.onerror=function(){n(c("Network Error",e,null,p)),p=null},p.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(c(t,e,"ECONNABORTED",p)),p=null},r.isStandardBrowserEnv()){var g=(e.withCredentials||s(v))&&e.xsrfCookieName?a.read(e.xsrfCookieName):void 0;g&&(d[e.xsrfHeaderName]=g)}if("setRequestHeader"in p&&r.forEach(d,(function(e,t){void 0===f&&"content-type"===t.toLowerCase()?delete d[t]:p.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(p.withCredentials=!!e.withCredentials),e.responseType)try{p.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&Line truncated
/*!
* Adapted from jQuery UI core
*
* http://jqueryui.com
*
* Copyright 2014 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/category/ui-core/
*/
var r=/input|select|textarea|button|object/;function o(e){var t=e.offsetWidth<=0&&e.offsetHeight<=0;if(t&&!e.innerHTML)return!0;var n=window.getComputedStyle(e);return t?"visible"!==n.getPropertyValue("overflow")||e.scrollWidth<=0&&e.scrollHeight<=0:"none"==n.getPropertyValue("display")}function a(e,t){var n=e.nodeName.toLowerCase();return(r.test(n)&&!e.disabled||"a"===n&&e.href||t)&&function(e){for(var t=e;t&&t!==document.body;){if(o(t))return!1;t=t.parentNode}return!0}(e)}function i(e){var t=e.getAttribute("tabindex");null===t&&(t=void 0);var n=isNaN(t);return(n||t>=0)&&a(e,!n)}e.exports=t.default},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.assertNodeList=u,t.setElement=function(e){var t=e;if("string"==typeof t&&i.canUseDOM){var n=document.querySelectorAll(t);u(n,t),t="length"in n?n[0]:n}return l=t||l},t.validateElement=s,t.hide=function(e){s(e)&&(e||l).setAttribute("aria-hidden","true")},t.show=function(e){s(e)&&(e||l).removeAttribute("aria-hidden")},t.documentNotReadyOrSSRTesting=function(){l=null},t.resetForTesting=function(){l=null};var r,o=n(71),a=(r=o)&&r.__esModule?r:{default:r},i=n(11);var l=null;function u(e,t){if(!e||!e.length)throw new Error("react-modal: No elements were found for selector "+t+".")}function s(e){return!(!e&&!l)||((0,a.default)(!1,["react-modal: App element is not defined.","Please use `Modal.setAppElement(el)` or set `appElement={el}`.","This is needed so screen readers don't see main content","when modal is opened. It is not recommended, but you can opt-out","by setting `ariaHideApp={false}`."].join(" ")),!1)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=new function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.register=function(e){-1===t.openInstances.indexOf(e)&&(t.openInstances.push(e),t.emit("register"))},this.deregister=function(e){var n=t.openInstances.indexOf(e);-1!==n&&(t.openInstances.splice(n,1),t.emit("deregister"))},this.subscribe=function(e){t.subscribers.push(e)},this.emit=function(e){t.subscribers.forEach((function(n){return n(e,t.openInstances.slice())}))},this.openInstances=[],this.subscribers=[]};t.default=r,e.exports=t.default},function(e,t){e.exports=function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,o=n(67),a=(r=o)&&r.__esModule?r:{default:r};t.default=a.default,e.exports=t.default},function(e,t,n){var r=n(88);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}},function(e,t,n){var r=n(89),o=n(4);e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?o(e):t}},function(e,t,n){var r=n(16),o=n(30),a=n(10),i=n(18);e.exports=function(e){return r(e)||o(e)||a(e)||i()}},,function(e,t,n){(function(t,n){
/*!
* @overview es6-promise - a tiny implementation of Promises/A+.
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
* @license Licensed under MIT license
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
* @version v4.2.8+1e68dce6
*/var r;r=function(){"use strict";function e(e){return"function"==typeof e}var r=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},o=0,a=void 0,i=void 0,l=function(e,t){h[o]=e,h[o+1]=t,2===(o+=2)&&(i?i(m):w())},u="undefined"!=typeof window?window:void 0,s=u||{},c=s.MutationObserver||s.WebKitMutationObserver,f="undefined"==typeof self&&void 0!==t&&"[object process]"==={}.toString.call(t),d="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel;function p(){var e=setTimeout;return function(){return e(m,1)}}var h=new Array(1e3);function m(){for(var e=0;e<o;e+=2)(0,h[e])(h[e+1]),h[e]=void 0,h[e+1]=void 0;o=0}var v,g,y,b,w=void 0;function E(e,t){var n=this,r=new this.constructor(C);void 0===r[x]&&I(r);var o=n._state;if(o){var a=arguments[o-1];l((function(){return D(o,r,a,n._result)}))}else P(n,r,e,t);return r}function k(e){if(e&&"object"==typeof e&&e.constructor===this)return e;var t=new this(C);return T(t,e),t}f?w=function(){return t.nextTick(m)}:c?(g=0,y=new c(m),b=document.createTextNode(""),y.observe(b,{characterData:!0}),w=function(){b.data=g=++g%2}):d?((v=new MessageChannel).port1.onmessage=m,w=function(){return v.port2.postMessage(0)}):w=void 0===u?function(){try{var e=Function("return this")().require("vertx");return void 0!==(a=e.runOnLoop||e.runOnContext)?function(){a(m)}:p()}catch(e){return p()}}():p();var x=Math.random().toString(36).substring(2);function C(){}function S(t,n,r){n.constructor===t.constructor&&r===E&&n.constructor.resolve===k?function(e,t){1===t._state?_(e,t._result):2===t._state?N(e,t._result):P(t,void 0,(function(t){return T(e,t)}),(function(t){return N(e,t)}))}(t,n):void 0===r?_(t,n):e(r)?function(e,t,n){l((function(e){var r=!1,o=function(e,t,n,r){try{e.call(t,n,r)}catch(e){return e}}(n,t,(function(n){r||(r=!0,t!==n?T(e,n):_(e,n))}),(function(t){r||(r=!0,N(e,t))}),e._label);!r&&o&&(r=!0,N(e,o))}),e)}(t,n,r):_(t,n)}function T(e,t){if(e===t)N(e,new TypeError("You cannot resolve a promise with itself"));else if(o=typeof(r=t),null===r||"object"!==o&&"function"!==o)_(e,t);else{var n=void 0;try{n=t.then}catch(t){return void N(e,t)}S(e,t,n)}var r,o}function O(e){e._onerror&&e._onerror(e._result),R(e)}function _(e,t){void 0===e._state&&(e._result=t,e._state=1,0!==e._subscribers.length&&l(R,e))}function N(e,t){void 0===e._state&&(e._state=2,e._result=t,l(O,e))}function P(e,t,n,r){var o=e._subscribers,a=o.length;e._onerror=null,o[a]=t,o[a+1]=n,o[a+2]=r,0===a&&e._state&&l(R,e)}function R(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r=void 0,o=void 0,a=e._result,i=0;i<t.length;i+=3)r=t[i],o=t[i+n],r?D(n,r,o,a):o(a);e._subscribers.length=0}}function D(t,n,r,o){var a=e(r),i=void 0,l=void 0,u=!0;if(a){try{i=r(o)}catch(e){u=!1,l=e}if(n===i)return void N(n,new TypeError("A promises callback cannot return that same promise."))}else i=o;void 0!==n._state||(a&&u?T(n,i):!1===u?N(n,l):1===t?_(n,i):2===t&&N(n,i))}var j=0;function I(e){e[x]=j++,e._state=void 0,e._result=void 0,e._subscribers=[]}var L=function(){function e(e,t){this._instanceConstructor=e,this.promise=new e(C),this.promise[x]||I(this.promise),r(t)?(this.length=t.length,this._remaining=t.length,this._result=new Array(this.length),0===this.length?_(this.promise,this._result):(this.length=this.length||0,this._enumerate(t),0===this._remaining&&_(this.promise,this._result))):N(this.promise,new Error("Array Methods must be provided an Array"))}return e.prototype._enumerate=function(e){for(var t=0;void 0===this._state&&t<e.length;t++)this._eachEntry(e[t],t)},e.prototype._eachEntry=function(e,t){var n=this._instanceConstructor,r=n.resolve;if(r===k){var o=void 0,a=void 0,i=!1;try{o=e.then}catch(e){i=!0,a=e}if(o===E&&void 0!==e._state)this._settledAt(e._state,t,e._result);else if("function"!=typeof o)this._remaining--,this._result[t]=e;else if(n===M){var l=new n(C);i?N(l,a):S(l,e,o),this._willSettleAt(l,t)}else this._willSettleAt(new n((function(t){return t(e)})),t)}else this._willSettleAt(r(e),t)},e.prototype._settledAt=function(e,t,n){var r=this.promise;void 0===r._state&&(this._remaining--,2===e?N(r,n):this._result[t]=n),0===this._remaining&&_(r,this._result)},e.prototype._willSettleAt=function(e,t){var n=this;P(e,void 0,(function(e){return n._settledAt(1,t,e)}),(function(e){return n._settledAt(2,t,e)}))},e}(),M=function(){function t(e){this[x]=j++,this._result=this._state=void 0,this._subscribers=[],C!==e&&("function"!=typeof e&&function(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}(),this instanceof t?function(e,t){try{t((function(t){T(e,t)}),(function(t){N(e,t)}))}catch(t){N(e,t)}}(this,e):function(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}())}return t.prototype.catch=function(e){return this.then(null,e)},t.prototype.finally=function(t){var n=this.constructor;returLine truncated
/** @license React v16.14.0
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r=n(15),o="function"==typeof Symbol&&Symbol.for,a=o?Symbol.for("react.element"):60103,i=o?Symbol.for("react.portal"):60106,l=o?Symbol.for("react.fragment"):60107,u=o?Symbol.for("react.strict_mode"):60108,s=o?Symbol.for("react.profiler"):60114,c=o?Symbol.for("react.provider"):60109,f=o?Symbol.for("react.context"):60110,d=o?Symbol.for("react.forward_ref"):60112,p=o?Symbol.for("react.suspense"):60113,h=o?Symbol.for("react.memo"):60115,m=o?Symbol.for("react.lazy"):60116,v="function"==typeof Symbol&&Symbol.iterator;function g(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var y={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},b={};function w(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||y}function E(){}function k(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||y}w.prototype.isReactComponent={},w.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error(g(85));this.updater.enqueueSetState(this,e,t,"setState")},w.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},E.prototype=w.prototype;var x=k.prototype=new E;x.constructor=k,r(x,w.prototype),x.isPureReactComponent=!0;var C={current:null},S=Object.prototype.hasOwnProperty,T={key:!0,ref:!0,__self:!0,__source:!0};function O(e,t,n){var r,o={},i=null,l=null;if(null!=t)for(r in void 0!==t.ref&&(l=t.ref),void 0!==t.key&&(i=""+t.key),t)S.call(t,r)&&!T.hasOwnProperty(r)&&(o[r]=t[r]);var u=arguments.length-2;if(1===u)o.children=n;else if(1<u){for(var s=Array(u),c=0;c<u;c++)s[c]=arguments[c+2];o.children=s}if(e&&e.defaultProps)for(r in u=e.defaultProps)void 0===o[r]&&(o[r]=u[r]);return{$$typeof:a,type:e,key:i,ref:l,props:o,_owner:C.current}}function _(e){return"object"==typeof e&&null!==e&&e.$$typeof===a}var N=/\/+/g,P=[];function R(e,t,n,r){if(P.length){var o=P.pop();return o.result=e,o.keyPrefix=t,o.func=n,o.context=r,o.count=0,o}return{result:e,keyPrefix:t,func:n,context:r,count:0}}function D(e){e.result=null,e.keyPrefix=null,e.func=null,e.context=null,e.count=0,10>P.length&&P.push(e)}function j(e,t,n){return null==e?0:function e(t,n,r,o){var l=typeof t;"undefined"!==l&&"boolean"!==l||(t=null);var u=!1;if(null===t)u=!0;else switch(l){case"string":case"number":u=!0;break;case"object":switch(t.$$typeof){case a:case i:u=!0}}if(u)return r(o,t,""===n?"."+I(t,0):n),1;if(u=0,n=""===n?".":n+":",Array.isArray(t))for(var s=0;s<t.length;s++){var c=n+I(l=t[s],s);u+=e(l,c,r,o)}else if(null===t||"object"!=typeof t?c=null:c="function"==typeof(c=v&&t[v]||t["@@iterator"])?c:null,"function"==typeof c)for(t=c.call(t),s=0;!(l=t.next()).done;)u+=e(l=l.value,c=n+I(l,s++),r,o);else if("object"===l)throw r=""+t,Error(g(31,"[object Object]"===r?"object with keys {"+Object.keys(t).join(", ")+"}":r,""));return u}(e,"",t,n)}function I(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+(""+e).replace(/[=:]/g,(function(e){return t[e]}))}(e.key):t.toString(36)}function L(e,t){e.func.call(e.context,t,e.count++)}function M(e,t,n){var r=e.result,o=e.keyPrefix;e=e.func.call(e.context,t,e.count++),Array.isArray(e)?A(e,r,n,(function(e){return e})):null!=e&&(_(e)&&(e=function(e,t){return{$$typeof:a,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(e,o+(!e.key||t&&t.key===e.key?"":(""+e.key).replace(N,"$&/")+"/")+n)),r.push(e))}function A(e,t,n,r,o){var a="";null!=n&&(a=(""+n).replace(N,"$&/")+"/"),j(e,M,t=R(t,a,r,o)),D(t)}var F={current:null};function U(){var e=F.current;if(null===e)throw Error(g(321));return e}var z={ReactCurrentDispatcher:F,ReactCurrentBatchConfig:{suspense:null},ReactCurrentOwner:C,IsSomeRendererActing:{current:!1},assign:r};t.Children={map:function(e,t,n){if(null==e)return e;var r=[];return A(e,r,null,t,n),r},forEach:function(e,t,n){if(null==e)return e;j(e,L,t=R(null,null,t,n)),D(t)},count:function(e){return j(e,(function(){return null}),null)},toArray:function(e){var t=[];return A(e,t,null,(function(e){return e})),t},only:function(e){if(!_(e))throw Error(g(143));return e}},t.Component=w,t.Fragment=l,t.Profiler=s,t.PureComponent=k,t.StrictMode=u,t.Suspense=p,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=z,t.cloneElement=function(e,t,n){if(null==e)throw Error(g(267,e));var o=r({},e.props),i=e.key,l=e.ref,u=e._owner;if(null!=t){if(void 0!==t.ref&&(l=t.ref,u=C.current),void 0!==t.key&&(i=""+t.key),e.type&&e.type.defaultProps)var s=e.type.defaultProps;for(c in t)S.call(t,c)&&!T.hasOwnProperty(c)&&(o[c]=void 0===t[c]&&void 0!==s?s[c]:t[c])}var c=arguments.length-2;if(1===c)o.children=n;else if(1<c){s=Array(c);for(var f=0;f<c;f++)s[f]=arguments[f+2];o.children=s}return{$$typeof:a,tyLine truncated
/** @license React v16.14.0
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r=n(0),o=n(15),a=n(40);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n<arguments.length;n++)t+="&args[]="+encodeURIComponent(arguments[n]);return"Minified React error #"+e+"; visit "+t+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}if(!r)throw Error(i(227));function l(e,t,n,r,o,a,i,l,u){var s=Array.prototype.slice.call(arguments,3);try{t.apply(n,s)}catch(e){this.onError(e)}}var u=!1,s=null,c=!1,f=null,d={onError:function(e){u=!0,s=e}};function p(e,t,n,r,o,a,i,c,f){u=!1,s=null,l.apply(d,arguments)}var h=null,m=null,v=null;function g(e,t,n){var r=e.type||"unknown-event";e.currentTarget=v(n),function(e,t,n,r,o,a,l,d,h){if(p.apply(this,arguments),u){if(!u)throw Error(i(198));var m=s;u=!1,s=null,c||(c=!0,f=m)}}(r,t,void 0,e),e.currentTarget=null}var y=null,b={};function w(){if(y)for(var e in b){var t=b[e],n=y.indexOf(e);if(!(-1<n))throw Error(i(96,e));if(!k[n]){if(!t.extractEvents)throw Error(i(97,e));for(var r in k[n]=t,n=t.eventTypes){var o=void 0,a=n[r],l=t,u=r;if(x.hasOwnProperty(u))throw Error(i(99,u));x[u]=a;var s=a.phasedRegistrationNames;if(s){for(o in s)s.hasOwnProperty(o)&&E(s[o],l,u);o=!0}else a.registrationName?(E(a.registrationName,l,u),o=!0):o=!1;if(!o)throw Error(i(98,r,e))}}}}function E(e,t,n){if(C[e])throw Error(i(100,e));C[e]=t,S[e]=t.eventTypes[n].dependencies}var k=[],x={},C={},S={};function T(e){var t,n=!1;for(t in e)if(e.hasOwnProperty(t)){var r=e[t];if(!b.hasOwnProperty(t)||b[t]!==r){if(b[t])throw Error(i(102,t));b[t]=r,n=!0}}n&&w()}var O=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),_=null,N=null,P=null;function R(e){if(e=m(e)){if("function"!=typeof _)throw Error(i(280));var t=e.stateNode;t&&(t=h(t),_(e.stateNode,e.type,t))}}function D(e){N?P?P.push(e):P=[e]:N=e}function j(){if(N){var e=N,t=P;if(P=N=null,R(e),t)for(e=0;e<t.length;e++)R(t[e])}}function I(e,t){return e(t)}function L(e,t,n,r,o){return e(t,n,r,o)}function M(){}var A=I,F=!1,U=!1;function z(){null===N&&null===P||(M(),j())}function q(e,t,n){if(U)return e(t,n);U=!0;try{return A(e,t,n)}finally{U=!1,z()}}var B=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,V=Object.prototype.hasOwnProperty,W={},H={};function $(e,t,n,r,o,a){this.acceptsBooleans=2===t||3===t||4===t,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=a}var Q={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){Q[e]=new $(e,0,!1,e,null,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var t=e[0];Q[t]=new $(t,1,!1,e[1],null,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){Q[e]=new $(e,2,!1,e.toLowerCase(),null,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){Q[e]=new $(e,2,!1,e,null,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){Q[e]=new $(e,3,!1,e.toLowerCase(),null,!1)})),["checked","multiple","muted","selected"].forEach((function(e){Q[e]=new $(e,3,!0,e,null,!1)})),["capture","download"].forEach((function(e){Q[e]=new $(e,4,!1,e,null,!1)})),["cols","rows","size","span"].forEach((function(e){Q[e]=new $(e,6,!1,e,null,!1)})),["rowSpan","start"].forEach((function(e){Q[e]=new $(e,5,!1,e.toLowerCase(),null,!1)}));var K=/[\-:]([a-z])/g;function Y(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-ranLine truncated
/** @license React v0.19.1
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var r,o,a,i,l;if("undefined"==typeof window||"function"!=typeof MessageChannel){var u=null,s=null,c=function(){if(null!==u)try{var e=t.unstable_now();u(!0,e),u=null}catch(e){throw setTimeout(c,0),e}},f=Date.now();t.unstable_now=function(){return Date.now()-f},r=function(e){null!==u?setTimeout(r,0,e):(u=e,setTimeout(c,0))},o=function(e,t){s=setTimeout(e,t)},a=function(){clearTimeout(s)},i=function(){return!1},l=t.unstable_forceFrameRate=function(){}}else{var d=window.performance,p=window.Date,h=window.setTimeout,m=window.clearTimeout;if("undefined"!=typeof console){var v=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof v&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof d&&"function"==typeof d.now)t.unstable_now=function(){return d.now()};else{var g=p.now();t.unstable_now=function(){return p.now()-g}}var y=!1,b=null,w=-1,E=5,k=0;i=function(){return t.unstable_now()>=k},l=function(){},t.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):E=0<e?Math.floor(1e3/e):5};var x=new MessageChannel,C=x.port2;x.port1.onmessage=function(){if(null!==b){var e=t.unstable_now();k=e+E;try{b(!0,e)?C.postMessage(null):(y=!1,b=null)}catch(e){throw C.postMessage(null),e}}else y=!1},r=function(e){b=e,y||(y=!0,C.postMessage(null))},o=function(e,n){w=h((function(){e(t.unstable_now())}),n)},a=function(){m(w),w=-1}}function S(e,t){var n=e.length;e.push(t);e:for(;;){var r=n-1>>>1,o=e[r];if(!(void 0!==o&&0<_(o,t)))break e;e[r]=t,e[n]=o,n=r}}function T(e){return void 0===(e=e[0])?null:e}function O(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,o=e.length;r<o;){var a=2*(r+1)-1,i=e[a],l=a+1,u=e[l];if(void 0!==i&&0>_(i,n))void 0!==u&&0>_(u,i)?(e[r]=u,e[l]=n,r=l):(e[r]=i,e[a]=n,r=a);else{if(!(void 0!==u&&0>_(u,n)))break e;e[r]=u,e[l]=n,r=l}}}return t}return null}function _(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var N=[],P=[],R=1,D=null,j=3,I=!1,L=!1,M=!1;function A(e){for(var t=T(P);null!==t;){if(null===t.callback)O(P);else{if(!(t.startTime<=e))break;O(P),t.sortIndex=t.expirationTime,S(N,t)}t=T(P)}}function F(e){if(M=!1,A(e),!L)if(null!==T(N))L=!0,r(U);else{var t=T(P);null!==t&&o(F,t.startTime-e)}}function U(e,n){L=!1,M&&(M=!1,a()),I=!0;var r=j;try{for(A(n),D=T(N);null!==D&&(!(D.expirationTime>n)||e&&!i());){var l=D.callback;if(null!==l){D.callback=null,j=D.priorityLevel;var u=l(D.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?D.callback=u:D===T(N)&&O(N),A(n)}else O(N);D=T(N)}if(null!==D)var s=!0;else{var c=T(P);null!==c&&o(F,c.startTime-n),s=!1}return s}finally{D=null,j=r,I=!1}}function z(e){switch(e){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var q=l;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){L||I||(L=!0,r(U))},t.unstable_getCurrentPriorityLevel=function(){return j},t.unstable_getFirstCallbackNode=function(){return T(N)},t.unstable_next=function(e){switch(j){case 1:case 2:case 3:var t=3;break;default:t=j}var n=j;j=t;try{return e()}finally{j=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=q,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=j;j=e;try{return t()}finally{j=n}},t.unstable_scheduleCallback=function(e,n,i){var l=t.unstable_now();if("object"==typeof i&&null!==i){var u=i.delay;u="number"==typeof u&&0<u?l+u:l,i="number"==typeof i.timeout?i.timeout:z(e)}else i=z(e),u=l;return e={id:R++,callback:n,priorityLevel:e,startTime:u,expirationTime:i=u+i,sortIndex:-1},u>l?(e.sortIndex=u,S(P,e),null===T(N)&&e===T(P)&&(M?a():M=!0,o(F,u-l))):(e.sortIndex=i,S(N,e),L||I||(L=!0,r(U))),e},t.unstable_shouldYield=function(){var e=t.unstable_now();A(e);var n=T(N);return n!==D&&null!==D&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime<D.expirationTime||i()},t.unstable_wrapCallback=function(e){var t=j;return function(){var n=j;j=t;try{return e.apply(this,arguments)}finally{j=n}}}},function(e,t){e.exports=function(e,t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e)){var n=[],r=!0,o=!1,a=void 0;try{for(var i,l=e[Symbol.iterator]();!(r=(i=l.next()).done)&&(n.push(i.value),!t||n.length!==t);r=!0);}catch(e){o=!0,a=e}finally{try{r||null==l.return||l.return()}finally{if(o)throw a}}return n}}},function(e,t,n){"use strict";var r=n(44);function o(){}function a(){}a.resetWarningCache=o,e.e Line truncated
/*!
Copyright (c) 2015 Jed Watson.
Based on code that is Copyright 2013-2015, Facebook, Inc.
All rights reserved.
*/!function(){"use strict";var o=!("undefined"==typeof window||!window.document||!window.document.createElement),a={canUseDOM:o,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:o&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:o&&!!window.screen};void 0===(r=function(){return a}.call(t,n,t,e))||(e.exports=r)}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.dumpClassLists=function(){0};var r={},o={};t.add=function(e,t){return n=e.classList,a="html"==e.nodeName.toLowerCase()?r:o,void t.split(" ").forEach((function(e){!function(e,t){e[t]||(e[t]=0),e[t]+=1}(a,e),n.add(e)}));var n,a},t.remove=function(e,t){return n=e.classList,a="html"==e.nodeName.toLowerCase()?r:o,void t.split(" ").forEach((function(e){!function(e,t){e[t]&&(e[t]-=1)}(a,e),0===a[e]&&n.remove(e)}));var n,a}},function(e,t,n){"use strict";var r,o=n(29),a=(r=o)&&r.__esModule?r:{default:r};var i=void 0,l=void 0,u=[];function s(){0!==u.length&&u[u.length-1].focusContent()}a.default.subscribe((function(e,t){i&&l||((i=document.createElement("div")).setAttribute("data-react-modal-body-trap",""),i.style.position="absolute",i.style.opacity="0",i.setAttribute("tabindex","0"),i.addEventListener("focus",s),(l=i.cloneNode()).addEventListener("focus",s)),(u=t).length>0?(document.body.firstChild!==i&&document.body.insertBefore(i,document.body.firstChild),document.body.lastChild!==l&&document.body.appendChild(l)):(i.parentElement&&i.parentElement.removeChild(i),l.parentElement&&l.parentElement.removeChild(l))}))},function(e,t,n){"use strict";function r(){var e=this.constructor.getDerivedStateFromProps(this.props,this.state);null!=e&&this.setState(e)}function o(e){this.setState(function(t){var n=this.constructor.getDerivedStateFromProps(e,t);return null!=n?n:null}.bind(this))}function a(e,t){try{var n=this.props,r=this.state;this.props=e,this.state=t,this.__reactInternalSnapshotFlag=!0,this.__reactInternalSnapshot=this.getSnapshotBeforeUpdate(n,r)}finally{this.props=n,this.state=r}}function i(e){var t=e.prototype;if(!t||!t.isReactComponent)throw new Error("Can only polyfill class components");if("function"!=typeof e.getDerivedStateFromProps&&"function"!=typeof t.getSnapshotBeforeUpdate)return e;var n=null,i=null,l=null;if("function"==typeof t.componentWillMount?n="componentWillMount":"function"==typeof t.UNSAFE_componentWillMount&&(n="UNSAFE_componentWillMount"),"function"==typeof t.componentWillReceiveProps?i="componentWillReceiveProps":"function"==typeof t.UNSAFE_componentWillReceiveProps&&(i="UNSAFE_componentWillReceiveProps"),"function"==typeof t.componentWillUpdate?l="componentWillUpdate":"function"==typeof t.UNSAFE_componentWillUpdate&&(l="UNSAFE_componentWillUpdate"),null!==n||null!==i||null!==l){var u=e.displayName||e.name,s="function"==typeof e.getDerivedStateFromProps?"getDerivedStateFromProps()":"getSnapshotBeforeUpdate()";throw Error("Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n"+u+" uses "+s+" but also contains the following legacy lifecycles:"+(null!==n?"\n "+n:"")+(null!==i?"\n "+i:"")+(null!==l?"\n "+l:"")+"\n\nThe above lifecycles should be removed. Learn more about this warning here:\nhttps://fb.me/react-async-component-lifecycle-hooks")}if("function"==typeof e.getDerivedStateFromProps&&(t.componentWillMount=r,t.componentWillReceiveProps=o),"function"==typeof t.getSnapshotBeforeUpdate){if("function"!=typeof t.componentDidUpdate)throw new Error("Cannot polyfill getSnapshotBeforeUpdate() for components that do not define componentDidUpdate() on the prototype");t.componentWillUpdate=a;var c=t.componentDidUpdate;t.componentDidUpdate=function(e,t,n){var r=this.__reactInternalSnapshotFlag?this.__reactInternalSnapshot:n;c.call(this,e,t,r)}}return e}n.r(t),n.d(t,"polyfill",(function(){return i})),r.__suppressDeprecationWarning=!0,o.__suppressDeprecationWarning=!0,a.__suppressDeprecationWarning=!0},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){var r=n(17);e.exports=function(e){if(Array.isArray(e))return r(e)}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?e.exports=n=function(e){return typeof e}:e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(t)}e.exports=n},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},funLine truncated
+297
View File
@@ -0,0 +1,297 @@
/* global H5PAdminIntegration H5PUtils */
var H5PLibraryDetails = H5PLibraryDetails || {};
(function ($) {
H5PLibraryDetails.PAGER_SIZE = 20;
/**
* Initializing
*/
H5PLibraryDetails.init = function () {
H5PLibraryDetails.$adminContainer = H5P.jQuery(H5PAdminIntegration.containerSelector);
H5PLibraryDetails.library = H5PAdminIntegration.libraryInfo;
// currentContent holds the current list if data (relevant for filtering)
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
// The current page index (for pager)
H5PLibraryDetails.currentPage = 0;
// The current filter
H5PLibraryDetails.currentFilter = '';
// We cache the filtered results, so we don't have to do unneccessary searches
H5PLibraryDetails.filterCache = [];
// Append library info
H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createLibraryInfo());
// Append node list
H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createContentElement());
};
/**
* Create the library details view
*/
H5PLibraryDetails.createLibraryInfo = function () {
var $libraryInfo = $('<div class="h5p-library-info"></div>');
$.each(H5PLibraryDetails.library.info, function (title, value) {
$libraryInfo.append(H5PUtils.createLabeledField(title, value));
});
return $libraryInfo;
};
/**
* Create the content list with searching and paging
*/
H5PLibraryDetails.createContentElement = function () {
if (H5PLibraryDetails.library.notCached !== undefined) {
return H5PUtils.getRebuildCache(H5PLibraryDetails.library.notCached);
}
if (H5PLibraryDetails.currentContent === undefined) {
H5PLibraryDetails.$content = $('<div class="h5p-content empty">' + H5PLibraryDetails.library.translations.noContent + '</div>');
}
else {
H5PLibraryDetails.$content = $('<div class="h5p-content"><h3>' + H5PLibraryDetails.library.translations.contentHeader + '</h3></div>');
H5PLibraryDetails.createSearchElement();
H5PLibraryDetails.createPageSizeSelector();
H5PLibraryDetails.createContentTable();
H5PLibraryDetails.createPagerElement();
return H5PLibraryDetails.$content;
}
};
/**
* Creates the content list
*/
H5PLibraryDetails.createContentTable = function () {
// Remove it if it exists:
if (H5PLibraryDetails.$contentTable) {
H5PLibraryDetails.$contentTable.remove();
}
H5PLibraryDetails.$contentTable = H5PUtils.createTable();
var i = (H5PLibraryDetails.currentPage*H5PLibraryDetails.PAGER_SIZE);
var lastIndex = (i+H5PLibraryDetails.PAGER_SIZE);
if (lastIndex > H5PLibraryDetails.currentContent.length) {
lastIndex = H5PLibraryDetails.currentContent.length;
}
for (; i<lastIndex; i++) {
var content = H5PLibraryDetails.currentContent[i];
H5PLibraryDetails.$contentTable.append(H5PUtils.createTableRow(['<a href="' + content.url + '">' + content.title + '</a>']));
}
// Appends it to the browser DOM
H5PLibraryDetails.$contentTable.insertAfter(H5PLibraryDetails.$search);
};
/**
* Creates the pager element on the bottom of the list
*/
H5PLibraryDetails.createPagerElement = function () {
H5PLibraryDetails.$previous = $('<button type="button" class="previous h5p-admin"><</button>');
H5PLibraryDetails.$next = $('<button type="button" class="next h5p-admin">></button>');
H5PLibraryDetails.$previous.on('click', function () {
if (H5PLibraryDetails.$previous.hasClass('disabled')) {
return;
}
H5PLibraryDetails.currentPage--;
H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable();
});
H5PLibraryDetails.$next.on('click', function () {
if (H5PLibraryDetails.$next.hasClass('disabled')) {
return;
}
H5PLibraryDetails.currentPage++;
H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable();
});
// This is the Page x of y widget:
H5PLibraryDetails.$pagerInfo = $('<span class="pager-info"></span>');
H5PLibraryDetails.$pager = $('<div class="h5p-content-pager"></div>').append(H5PLibraryDetails.$previous, H5PLibraryDetails.$pagerInfo, H5PLibraryDetails.$next);
H5PLibraryDetails.$content.append(H5PLibraryDetails.$pager);
H5PLibraryDetails.$pagerInfo.on('click', function () {
var width = H5PLibraryDetails.$pagerInfo.innerWidth();
H5PLibraryDetails.$pagerInfo.hide();
// User has updated the pageNumber
var pageNumerUpdated = function () {
var newPageNum = $gotoInput.val()-1;
var intRegex = /^\d+$/;
$goto.remove();
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
// Check if input value is valid, and that it has actually changed
if (!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
return;
}
H5PLibraryDetails.currentPage = newPageNum;
H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable();
};
// We create an input box where the user may type in the page number
// he wants to be displayed.
// Reson for doing this is when user has ten-thousands of elements in list,
// this is the easiest way of getting to a specified page
var $gotoInput = $('<input/>', {
type: 'number',
min : 1,
max: H5PLibraryDetails.getNumPages(),
on: {
// Listen to blur, and the enter-key:
'blur': pageNumerUpdated,
'keyup': function (event) {
if (event.keyCode === 13) {
pageNumerUpdated();
}
}
}
}).css({width: width});
var $goto = $('<span/>', {
'class': 'h5p-pager-goto'
}).css({width: width}).append($gotoInput).insertAfter(H5PLibraryDetails.$pagerInfo);
$gotoInput.focus();
});
H5PLibraryDetails.updatePager();
};
/**
* Calculates number of pages
*/
H5PLibraryDetails.getNumPages = function () {
return Math.ceil(H5PLibraryDetails.currentContent.length / H5PLibraryDetails.PAGER_SIZE);
};
/**
* Update the pager text, and enables/disables the next and previous buttons as needed
*/
H5PLibraryDetails.updatePager = function () {
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
if (H5PLibraryDetails.getNumPages() > 0) {
var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, {
'$x': (H5PLibraryDetails.currentPage+1),
'$y': H5PLibraryDetails.getNumPages()
});
H5PLibraryDetails.$pagerInfo.html(message);
}
else {
H5PLibraryDetails.$pagerInfo.html('');
}
H5PLibraryDetails.$previous.toggleClass('disabled', H5PLibraryDetails.currentPage <= 0);
H5PLibraryDetails.$next.toggleClass('disabled', H5PLibraryDetails.currentContent.length < (H5PLibraryDetails.currentPage+1)*H5PLibraryDetails.PAGER_SIZE);
};
/**
* Creates the search element
*/
H5PLibraryDetails.createSearchElement = function () {
H5PLibraryDetails.$search = $('<div class="h5p-content-search"><input placeholder="' + H5PLibraryDetails.library.translations.filterPlaceholder + '" type="search"></div>');
var performSeach = function () {
var searchString = $('.h5p-content-search > input').val();
// If search string same as previous, just do nothing
if (H5PLibraryDetails.currentFilter === searchString) {
return;
}
if (searchString.trim().length === 0) {
// If empty search, use the complete list
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
}
else if (H5PLibraryDetails.filterCache[searchString]) {
// If search is cached, no need to filter
H5PLibraryDetails.currentContent = H5PLibraryDetails.filterCache[searchString];
}
else {
var listToFilter = H5PLibraryDetails.library.content;
// Check if we can filter the already filtered results (for performance)
if (searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
listToFilter = H5PLibraryDetails.currentContent;
}
H5PLibraryDetails.currentContent = $.grep(listToFilter, function (content) {
return content.title && content.title.match(new RegExp(searchString, 'i'));
});
}
H5PLibraryDetails.currentFilter = searchString;
// Cache the current result
H5PLibraryDetails.filterCache[searchString] = H5PLibraryDetails.currentContent;
H5PLibraryDetails.currentPage = 0;
H5PLibraryDetails.createContentTable();
// Display search results:
if (H5PLibraryDetails.$searchResults) {
H5PLibraryDetails.$searchResults.remove();
}
if (searchString.trim().length > 0) {
H5PLibraryDetails.$searchResults = $('<span class="h5p-admin-search-results">' + H5PLibraryDetails.currentContent.length + ' hits on ' + H5PLibraryDetails.currentFilter + '</span>');
H5PLibraryDetails.$search.append(H5PLibraryDetails.$searchResults);
}
H5PLibraryDetails.updatePager();
};
var inputTimer;
$('input', H5PLibraryDetails.$search).on('change keypress paste input', function () {
// Here we start the filtering
// We wait at least 500 ms after last input to perform search
if (inputTimer) {
clearTimeout(inputTimer);
}
inputTimer = setTimeout( function () {
performSeach();
}, 500);
});
H5PLibraryDetails.$content.append(H5PLibraryDetails.$search);
};
/**
* Creates the page size selector
*/
H5PLibraryDetails.createPageSizeSelector = function () {
H5PLibraryDetails.$search.append('<div class="h5p-admin-pager-size-selector">' + H5PLibraryDetails.library.translations.pageSizeSelectorLabel + ':<span data-page-size="10">10</span><span class="selected" data-page-size="20">20</span><span data-page-size="50">50</span><span data-page-size="100">100</span><span data-page-size="200">200</span></div>');
// Listen to clicks on the page size selector:
$('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).on('click', function () {
H5PLibraryDetails.PAGER_SIZE = $(this).data('page-size');
$('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).removeClass('selected');
$(this).addClass('selected');
H5PLibraryDetails.currentPage = 0;
H5PLibraryDetails.createContentTable();
H5PLibraryDetails.updatePager();
});
};
// Initialize me:
$(document).ready(function () {
if (!H5PLibraryDetails.initialized) {
H5PLibraryDetails.initialized = true;
H5PLibraryDetails.init();
}
});
})(H5P.jQuery);
+140
View File
@@ -0,0 +1,140 @@
/* global H5PAdminIntegration H5PUtils */
var H5PLibraryList = H5PLibraryList || {};
(function ($) {
/**
* Initializing
*/
H5PLibraryList.init = function () {
var $adminContainer = H5P.jQuery(H5PAdminIntegration.containerSelector).html('');
var libraryList = H5PAdminIntegration.libraryList;
if (libraryList.notCached) {
$adminContainer.append(H5PUtils.getRebuildCache(libraryList.notCached));
}
// Create library list
$adminContainer.append(H5PLibraryList.createLibraryList(H5PAdminIntegration.libraryList));
};
/**
* Create the library list
*
* @param {object} libraries List of libraries and headers
*/
H5PLibraryList.createLibraryList = function (libraries) {
var t = H5PAdminIntegration.l10n;
if (libraries.listData === undefined || libraries.listData.length === 0) {
return $('<div>' + t.NA + '</div>');
}
// Create table
var $table = H5PUtils.createTable(libraries.listHeaders);
$table.addClass('libraries');
// Add libraries
$.each (libraries.listData, function (index, library) {
var $libraryRow = H5PUtils.createTableRow([
library.title,
'<input class="h5p-admin-restricted" type="checkbox"/>',
{
text: library.numContent,
class: 'h5p-admin-center'
},
{
text: library.numContentDependencies,
class: 'h5p-admin-center'
},
{
text: library.numLibraryDependencies,
class: 'h5p-admin-center'
},
'<div class="h5p-admin-buttons-wrapper">' +
'<button class="h5p-admin-upgrade-library"></button>' +
(library.detailsUrl ? '<button class="h5p-admin-view-library" title="' + t.viewLibrary + '"></button>' : '') +
(library.deleteUrl ? '<button class="h5p-admin-delete-library"></button>' : '') +
'</div>'
]);
H5PLibraryList.addRestricted($('.h5p-admin-restricted', $libraryRow), library.restrictedUrl, library.restricted);
var hasContent = !(library.numContent === '' || library.numContent === 0);
if (library.upgradeUrl === null) {
$('.h5p-admin-upgrade-library', $libraryRow).remove();
}
else if (library.upgradeUrl === false || !hasContent) {
$('.h5p-admin-upgrade-library', $libraryRow).attr('disabled', true);
}
else {
$('.h5p-admin-upgrade-library', $libraryRow).attr('title', t.upgradeLibrary).click(function () {
window.location.href = library.upgradeUrl;
});
}
// Open details view when clicked
$('.h5p-admin-view-library', $libraryRow).on('click', function () {
window.location.href = library.detailsUrl;
});
var $deleteButton = $('.h5p-admin-delete-library', $libraryRow);
if (libraries.notCached !== undefined ||
hasContent ||
(library.numContentDependencies !== '' &&
library.numContentDependencies !== 0) ||
(library.numLibraryDependencies !== '' &&
library.numLibraryDependencies !== 0)) {
// Disabled delete if content.
$deleteButton.attr('disabled', true);
}
else {
// Go to delete page om click.
$deleteButton.attr('title', t.deleteLibrary).on('click', function () {
window.location.href = library.deleteUrl;
});
}
$table.append($libraryRow);
});
return $table;
};
H5PLibraryList.addRestricted = function ($checkbox, url, selected) {
if (selected === null) {
$checkbox.remove();
}
else {
$checkbox.change(function () {
$checkbox.attr('disabled', true);
$.ajax({
dataType: 'json',
url: url,
cache: false
}).fail(function () {
$checkbox.attr('disabled', false);
// Reset
$checkbox.attr('checked', !$checkbox.is(':checked'));
}).done(function (result) {
url = result.url;
$checkbox.attr('disabled', false);
});
});
if (selected) {
$checkbox.attr('checked', true);
}
}
};
// Initialize me:
$(document).ready(function () {
if (!H5PLibraryList.initialized) {
H5PLibraryList.initialized = true;
H5PLibraryList.init();
}
});
})(H5P.jQuery);
+131
View File
@@ -0,0 +1,131 @@
// H5P iframe Resizer
(function () {
if (!window.postMessage || !window.addEventListener || window.h5pResizerInitialized) {
return; // Not supported
}
window.h5pResizerInitialized = true;
// Map actions to handlers
var actionHandlers = {};
/**
* Prepare iframe resize.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.hello = function (iframe, data, respond) {
// Make iframe responsive
iframe.style.width = '100%';
// Bugfix for Chrome: Force update of iframe width. If this is not done the
// document size may not be updated before the content resizes.
iframe.getBoundingClientRect();
// Tell iframe that it needs to resize when our window resizes
var resize = function () {
if (iframe.contentWindow) {
// Limit resize calls to avoid flickering
respond('resize');
}
else {
// Frame is gone, unregister.
window.removeEventListener('resize', resize);
}
};
window.addEventListener('resize', resize, false);
// Respond to let the iframe know we can resize it
respond('hello');
};
/**
* Prepare iframe resize.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.prepareResize = function (iframe, data, respond) {
// Do not resize unless page and scrolling differs
if (iframe.clientHeight !== data.scrollHeight ||
data.scrollHeight !== data.clientHeight) {
// Reset iframe height, in case content has shrinked.
iframe.style.height = data.clientHeight + 'px';
respond('resizePrepared');
}
};
/**
* Resize parent and iframe to desired height.
*
* @private
* @param {Object} iframe Element
* @param {Object} data Payload
* @param {Function} respond Send a response to the iframe
*/
actionHandlers.resize = function (iframe, data) {
// Resize iframe so all content is visible. Use scrollHeight to make sure we get everything
iframe.style.height = data.scrollHeight + 'px';
};
/**
* Keyup event handler. Exits full screen on escape.
*
* @param {Event} event
*/
var escape = function (event) {
if (event.keyCode === 27) {
exitFullScreen();
}
};
// Listen for messages from iframes
window.addEventListener('message', function receiveMessage(event) {
if (event.data.context !== 'h5p') {
return; // Only handle h5p requests.
}
// Find out who sent the message
var iframe, iframes = document.getElementsByTagName('iframe');
for (var i = 0; i < iframes.length; i++) {
if (iframes[i].contentWindow === event.source) {
iframe = iframes[i];
break;
}
}
if (!iframe) {
return; // Cannot find sender
}
// Find action handler handler
if (actionHandlers[event.data.action]) {
actionHandlers[event.data.action](iframe, event.data, function respond(action, data) {
if (data === undefined) {
data = {};
}
data.action = action;
data.context = 'h5p';
event.source.postMessage(data, event.origin);
});
}
}, false);
// Let h5p iframes know we're ready!
var iframes = document.getElementsByTagName('iframe');
var ready = {
context: 'h5p',
action: 'ready'
};
for (var i = 0; i < iframes.length; i++) {
if (iframes[i].src.indexOf('h5p') !== -1) {
iframes[i].contentWindow.postMessage(ready, '*');
}
}
})();
+217
View File
@@ -0,0 +1,217 @@
/*global H5P*/
H5P.Tooltip = (function () {
'use strict';
/**
* Create an accessible tooltip
*
* @param {HTMLElement} triggeringElement The element that should trigger the tooltip
* @param {Object} options Options for tooltip
* @param {String} options.text The text to be displayed in the tooltip
* If not set, will attempt to set text = aria-label of triggeringElement
* @param {String[]} options.classes Extra css classes for the tooltip
* @param {Boolean} options.ariaHidden Whether the hover should be read by screen readers or not (default: true)
* @param {String} options.position Where the tooltip should appear in relation to the
* triggeringElement. Accepted positions are "top" (default), "left", "right" and "bottom"
*
* @constructor
*/
function Tooltip(triggeringElement, options) {
// Make sure tooltips have unique id
H5P.Tooltip.uniqueId += 1;
const tooltipId = 'h5p-tooltip-' + H5P.Tooltip.uniqueId;
// Default options
options = options || {};
options.classes = options.classes || [];
options.ariaHidden = options.ariaHidden || true;
// Initiate state
let hover = false;
let focus = false;
// Function used by the escape listener
const escapeFunction = function (e) {
if (e.key === 'Escape') {
tooltip.classList.remove('h5p-tooltip-visible');
}
}
// Create element
const tooltip = document.createElement('div');
tooltip.classList.add('h5p-tooltip');
tooltip.id = tooltipId;
tooltip.role = 'tooltip';
tooltip.innerHTML = options.text || triggeringElement.getAttribute('aria-label') || '';
tooltip.setAttribute('aria-hidden', options.ariaHidden);
tooltip.classList.add(...options.classes);
triggeringElement.appendChild(tooltip);
// Set the initial position based on options.position
switch (options.position) {
case 'left':
tooltip.classList.add('h5p-tooltip-left');
break;
case 'right':
tooltip.classList.add('h5p-tooltip-right');
break;
case 'bottom':
tooltip.classList.add('h5p-tooltip-bottom');
break;
default:
options.position = 'top';
}
// Aria-describedby will override aria-hidden
if (!options.ariaHidden) {
triggeringElement.setAttribute('aria-describedby', tooltipId);
}
// Add event listeners to triggeringElement
triggeringElement.addEventListener('mouseenter', function () {
showTooltip(true);
});
triggeringElement.addEventListener('mouseleave', function () {
hideTooltip(true);
});
triggeringElement.addEventListener('focusin', function () {
showTooltip(false);
});
triggeringElement.addEventListener('focusout', function () {
hideTooltip(false);
});
// Prevent clicks on the tooltip from triggering onClick listeners on the triggeringElement
tooltip.addEventListener('click', function (event) {
event.stopPropagation();
});
// Use a mutation observer to listen for aria-label being
// changed for the triggering element. If so, update the tooltip.
// Mutation observer will be used even if the original elements
// doesn't have any aria-label.
new MutationObserver(function (mutations) {
const ariaLabel = mutations[0].target.getAttribute('aria-label');
if (ariaLabel) {
tooltip.innerHTML = options.text || ariaLabel;
}
}).observe(triggeringElement, {
attributes: true,
attributeFilter: ['aria-label'],
});
// Use intersection observer to adjust the tooltip if it is not completely visible
new IntersectionObserver(function (entries) {
entries.forEach((entry) => {
const target = entry.target;
const positionClass = 'h5p-tooltip-' + options.position;
// Stop adjusting when hidden (to prevent a false positive next time)
if (entry.intersectionRatio === 0) {
['h5p-tooltip-down', 'h5p-tooltip-left', 'h5p-tooltip-right']
.forEach(function (adjustmentClass) {
if (adjustmentClass !== positionClass) {
target.classList.remove(adjustmentClass);
}
});
}
// Adjust if not completely visible when meant to be
else if (entry.intersectionRatio < 1 && (hover || focus)) {
const targetRect = entry.boundingClientRect;
const intersectionRect = entry.intersectionRect;
// Going out of screen on left side
if (intersectionRect.left > targetRect.left) {
target.classList.add('h5p-tooltip-right');
target.classList.remove(positionClass);
}
// Going out of screen on right side
else if (intersectionRect.right < targetRect.right) {
target.classList.add('h5p-tooltip-left');
target.classList.remove(positionClass);
}
// going out of top of screen
if (intersectionRect.top > targetRect.top) {
target.classList.add('h5p-tooltip-down');
target.classList.remove(positionClass);
}
// going out of bottom of screen
else if (intersectionRect.bottom < targetRect.bottom) {
target.classList.add('h5p-tooltip-up');
target.classList.remove(positionClass);
}
}
});
}).observe(tooltip);
/**
* Makes the tooltip visible and activates it's functionality
*
* @param {Boolean} triggeredByHover True if triggered by mouse, false if triggered by focus
*/
const showTooltip = function (triggeredByHover) {
if (triggeredByHover) {
hover = true;
}
else {
focus = true;
}
tooltip.classList.add('h5p-tooltip-visible');
// Add listener to iframe body, as esc keypress would not be detected otherwise
document.body.addEventListener('keydown', escapeFunction, true);
}
/**
* Hides the tooltip and removes listeners
*
* @param {Boolean} triggeredByHover True if triggered by mouse, false if triggered by focus
*/
const hideTooltip = function (triggeredByHover) {
if (triggeredByHover) {
hover = false;
}
else {
focus = false;
}
// Only hide tooltip if neither hovered nor focused
if (!hover && !focus) {
tooltip.classList.remove('h5p-tooltip-visible');
// Remove iframe body listener
document.body.removeEventListener('keydown', escapeFunction, true);
}
}
/**
* Change the text displayed by the tooltip
*
* @param {String} text The new text to be displayed
* Set to null to use aria-label of triggeringElement instead
*/
this.setText = function (text) {
options.text = text;
tooltip.innerHTML = options.text || triggeringElement.getAttribute('aria-label') || '';
};
/**
* Retrieve tooltip
*
* @return {HTMLElement}
*/
this.getElement = function () {
return tooltip;
};
}
return Tooltip;
})();
H5P.Tooltip.uniqueId = -1;
+506
View File
@@ -0,0 +1,506 @@
/* global H5PAdminIntegration*/
var H5PUtils = H5PUtils || {};
(function ($) {
/**
* Generic function for creating a table including the headers
*
* @param {array} headers List of headers
*/
H5PUtils.createTable = function (headers) {
var $table = $('<table class="h5p-admin-table' + (H5PAdminIntegration.extraTableClasses !== undefined ? ' ' + H5PAdminIntegration.extraTableClasses : '') + '"></table>');
if (headers) {
var $thead = $('<thead></thead>');
var $tr = $('<tr></tr>');
$.each(headers, function (index, value) {
if (!(value instanceof Object)) {
value = {
html: value
};
}
$('<th/>', value).appendTo($tr);
});
$table.append($thead.append($tr));
}
return $table;
};
/**
* Generic function for creating a table row
*
* @param {array} rows Value list. Object name is used as class name in <TD>
*/
H5PUtils.createTableRow = function (rows) {
var $tr = $('<tr></tr>');
$.each(rows, function (index, value) {
if (!(value instanceof Object)) {
value = {
html: value
};
}
$('<td/>', value).appendTo($tr);
});
return $tr;
};
/**
* Generic function for creating a field containing label and value
*
* @param {string} label The label displayed in front of the value
* @param {string} value The value
*/
H5PUtils.createLabeledField = function (label, value) {
var $field = $('<div class="h5p-labeled-field"></div>');
$field.append('<div class="h5p-label">' + label + '</div>');
$field.append('<div class="h5p-value">' + value + '</div>');
return $field;
};
/**
* Replaces placeholder fields in translation strings
*
* @param {string} template The translation template string in the following format: "$name is a $sex"
* @param {array} replacors An js object with key and values. Eg: {'$name': 'Frode', '$sex': 'male'}
*/
H5PUtils.translateReplace = function (template, replacors) {
$.each(replacors, function (key, value) {
template = template.replace(new RegExp('\\'+key, 'g'), value);
});
return template;
};
/**
* Get throbber with given text.
*
* @param {String} text
* @returns {$}
*/
H5PUtils.throbber = function (text) {
return $('<div/>', {
class: 'h5p-throbber',
text: text
});
};
/**
* Makes it possbile to rebuild all content caches from admin UI.
* @param {Object} notCached
* @returns {$}
*/
H5PUtils.getRebuildCache = function (notCached) {
var $container = $('<div class="h5p-admin-rebuild-cache"><p class="message">' + notCached.message + '</p><p class="progress">' + notCached.progress + '</p></div>');
var $button = $('<button>' + notCached.button + '</button>').appendTo($container).click(function () {
var $spinner = $('<div/>', {class: 'h5p-spinner'}).replaceAll($button);
var parts = ['|', '/', '-', '\\'];
var current = 0;
var spinning = setInterval(function () {
$spinner.text(parts[current]);
current++;
if (current === parts.length) current = 0;
}, 100);
var $counter = $container.find('.progress');
var build = function () {
$.post(notCached.url, function (left) {
if (left === '0') {
clearInterval(spinning);
$container.remove();
location.reload();
}
else {
var counter = $counter.text().split(' ');
counter[0] = left;
$counter.text(counter.join(' '));
build();
}
});
};
build();
});
return $container;
};
/**
* Generic table class with useful helpers.
*
* @class
* @param {Object} classes
* Custom html classes to use on elements.
* e.g. {tableClass: 'fixed'}.
*/
H5PUtils.Table = function (classes) {
var numCols;
var sortByCol;
var $sortCol;
var sortCol;
var sortDir;
// Create basic table
var tableOptions = {};
if (classes.table !== undefined) {
tableOptions['class'] = classes.table;
}
var $table = $('<table/>', tableOptions);
var $thead = $('<thead/>').appendTo($table);
var $tfoot = $('<tfoot/>').appendTo($table);
var $tbody = $('<tbody/>').appendTo($table);
/**
* Add columns to given table row.
*
* @private
* @param {jQuery} $tr Table row
* @param {(String|Object)} col Column properties
* @param {Number} id Used to seperate the columns
*/
var addCol = function ($tr, col, id) {
var options = {
on: {}
};
if (!(col instanceof Object)) {
options.text = col;
}
else {
if (col.text !== undefined) {
options.text = col.text;
}
if (col.class !== undefined) {
options.class = col.class;
}
if (sortByCol !== undefined && col.sortable === true) {
// Make sortable
options.role = 'button';
options.tabIndex = 0;
// This is the first sortable column, use as default sort
if (sortCol === undefined) {
sortCol = id;
sortDir = 0;
}
// This is the sort column
if (sortCol === id) {
options['class'] = 'h5p-sort';
if (sortDir === 1) {
options['class'] += ' h5p-reverse';
}
}
options.on.click = function () {
sort($th, id);
};
options.on.keypress = function (event) {
if ((event.charCode || event.keyCode) === 32) { // Space
sort($th, id);
}
};
}
}
// Append
var $th = $('<th>', options).appendTo($tr);
if (sortCol === id) {
$sortCol = $th; // Default sort column
}
};
/**
* Updates the UI when a column header has been clicked.
* Triggers sorting callback.
*
* @private
* @param {jQuery} $th Table header
* @param {Number} id Used to seperate the columns
*/
var sort = function ($th, id) {
if (id === sortCol) {
// Change sorting direction
if (sortDir === 0) {
sortDir = 1;
$th.addClass('h5p-reverse');
}
else {
sortDir = 0;
$th.removeClass('h5p-reverse');
}
}
else {
// Change sorting column
$sortCol.removeClass('h5p-sort').removeClass('h5p-reverse');
$sortCol = $th.addClass('h5p-sort');
sortCol = id;
sortDir = 0;
}
sortByCol({
by: sortCol,
dir: sortDir
});
};
/**
* Set table headers.
*
* @public
* @param {Array} cols
* Table header data. Can be strings or objects with options like
* "text" and "sortable". E.g.
* [{text: 'Col 1', sortable: true}, 'Col 2', 'Col 3']
* @param {Function} sort Callback which is runned when sorting changes
* @param {Object} [order]
*/
this.setHeaders = function (cols, sort, order) {
numCols = cols.length;
sortByCol = sort;
if (order) {
sortCol = order.by;
sortDir = order.dir;
}
// Create new head
var $newThead = $('<thead/>');
var $tr = $('<tr/>').appendTo($newThead);
for (var i = 0; i < cols.length; i++) {
addCol($tr, cols[i], i);
}
// Update DOM
$thead.replaceWith($newThead);
$thead = $newThead;
};
/**
* Set table rows.
*
* @public
* @param {Array} rows Table rows with cols: [[1,'hello',3],[2,'asd',6]]
*/
this.setRows = function (rows) {
var $newTbody = $('<tbody/>');
for (var i = 0; i < rows.length; i++) {
var $tr = $('<tr/>').appendTo($newTbody);
for (var j = 0; j < rows[i].length; j++) {
$('<td>', {
html: rows[i][j]
}).appendTo($tr);
}
}
$tbody.replaceWith($newTbody);
$tbody = $newTbody;
return $tbody;
};
/**
* Set custom table body content. This can be a message or a throbber.
* Will cover all table columns.
*
* @public
* @param {jQuery} $content Custom content
*/
this.setBody = function ($content) {
var $newTbody = $('<tbody/>');
var $tr = $('<tr/>').appendTo($newTbody);
$('<td>', {
colspan: numCols
}).append($content).appendTo($tr);
$tbody.replaceWith($newTbody);
$tbody = $newTbody;
};
/**
* Set custom table foot content. This can be a pagination widget.
* Will cover all table columns.
*
* @public
* @param {jQuery} $content Custom content
*/
this.setFoot = function ($content) {
var $newTfoot = $('<tfoot/>');
var $tr = $('<tr/>').appendTo($newTfoot);
$('<td>', {
colspan: numCols
}).append($content).appendTo($tr);
$tfoot.replaceWith($newTfoot);
};
/**
* Appends the table to the given container.
*
* @public
* @param {jQuery} $container
*/
this.appendTo = function ($container) {
$table.appendTo($container);
};
};
/**
* Generic pagination class. Creates a useful pagination widget.
*
* @class
* @param {Number} num Total number of items to pagiate.
* @param {Number} limit Number of items to dispaly per page.
* @param {Function} goneTo
* Callback which is fired when the user wants to go to another page.
* @param {Object} l10n
* Localization / translations. e.g.
* {
* currentPage: 'Page $current of $total',
* nextPage: 'Next page',
* previousPage: 'Previous page'
* }
*/
H5PUtils.Pagination = function (num, limit, goneTo, l10n) {
var current = 0;
var pages = Math.ceil(num / limit);
// Create components
// Previous button
var $left = $('<button/>', {
html: '&lt;',
'class': 'button',
title: l10n.previousPage
}).click(function () {
goTo(current - 1);
});
// Current page text
var $text = $('<span/>').click(function () {
$input.width($text.width()).show().val(current + 1).focus();
$text.hide();
});
// Jump to page input
var $input = $('<input/>', {
type: 'number',
min : 1,
max: pages,
on: {
'blur': function () {
gotInput();
},
'keyup': function (event) {
if (event.keyCode === 13) {
gotInput();
return false;
}
}
}
}).hide();
// Next button
var $right = $('<button/>', {
html: '&gt;',
'class': 'button',
title: l10n.nextPage
}).click(function () {
goTo(current + 1);
});
/**
* Check what page the user has typed in and jump to it.
*
* @private
*/
var gotInput = function () {
var page = parseInt($input.hide().val());
if (!isNaN(page)) {
goTo(page - 1);
}
$text.show();
};
/**
* Update UI elements.
*
* @private
*/
var updateUI = function () {
var next = current + 1;
// Disable or enable buttons
$left.attr('disabled', current === 0);
$right.attr('disabled', next === pages);
// Update counter
$text.html(l10n.currentPage.replace('$current', next).replace('$total', pages));
};
/**
* Try to go to the requested page.
*
* @private
* @param {Number} page
*/
var goTo = function (page) {
if (page === current || page < 0 || page >= pages) {
return; // Invalid page number
}
current = page;
updateUI();
// Fire callback
goneTo(page * limit);
};
/**
* Update number of items and limit.
*
* @public
* @param {Number} newNum Total number of items to pagiate.
* @param {Number} newLimit Number of items to dispaly per page.
*/
this.update = function (newNum, newLimit) {
if (newNum !== num || newLimit !== limit) {
// Update num and limit
num = newNum;
limit = newLimit;
pages = Math.ceil(num / limit);
$input.attr('max', pages);
if (current >= pages) {
// Content is gone, move to last page.
goTo(pages - 1);
return;
}
updateUI();
}
};
/**
* Append the pagination widget to the given container.
*
* @public
* @param {jQuery} $container
*/
this.appendTo = function ($container) {
$left.add($text).add($input).add($right).appendTo($container);
};
// Update UI
updateUI();
};
})(H5P.jQuery);
+40
View File
@@ -0,0 +1,40 @@
H5P.Version = (function () {
/**
* Make it easy to keep track of version details.
*
* @class
* @namespace H5P
* @param {String} version
*/
function Version(version) {
if (typeof version === 'string') {
// Name version string (used by content upgrade)
var versionSplit = version.split('.', 3);
this.major =+ versionSplit[0];
this.minor =+ versionSplit[1];
}
else {
// Library objects (used by editor)
if (version.localMajorVersion !== undefined) {
this.major =+ version.localMajorVersion;
this.minor =+ version.localMinorVersion;
}
else {
this.major =+ version.majorVersion;
this.minor =+ version.minorVersion;
}
}
/**
* Public. Custom string for this object.
*
* @returns {String}
*/
this.toString = function () {
return version;
};
}
return Version;
})();
+331
View File
@@ -0,0 +1,331 @@
var H5P = window.H5P = window.H5P || {};
/**
* Used for xAPI events.
*
* @class
* @extends H5P.Event
*/
H5P.XAPIEvent = function () {
H5P.Event.call(this, 'xAPI', {'statement': {}}, {bubbles: true, external: true});
};
H5P.XAPIEvent.prototype = Object.create(H5P.Event.prototype);
H5P.XAPIEvent.prototype.constructor = H5P.XAPIEvent;
/**
* Set scored result statements.
*
* @param {number} score
* @param {number} maxScore
* @param {object} instance
* @param {boolean} completion
* @param {boolean} success
*/
H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, completion, success) {
this.data.statement.result = {};
if (typeof score !== 'undefined') {
if (typeof maxScore === 'undefined') {
this.data.statement.result.score = {'raw': score};
}
else {
this.data.statement.result.score = {
'min': 0,
'max': maxScore,
'raw': score
};
if (maxScore > 0) {
this.data.statement.result.score.scaled = Math.round(score / maxScore * 10000) / 10000;
}
}
}
if (typeof completion === 'undefined') {
this.data.statement.result.completion = (this.getVerb() === 'completed' || this.getVerb() === 'answered');
}
else {
this.data.statement.result.completion = completion;
}
if (typeof success !== 'undefined') {
this.data.statement.result.success = success;
}
if (instance && instance.activityStartTime) {
var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100;
// xAPI spec allows a precision of 0.01 seconds
this.data.statement.result.duration = 'PT' + duration + 'S';
}
};
/**
* Set a verb.
*
* @param {string} verb
* Verb in short form, one of the verbs defined at
* {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary}
*
*/
H5P.XAPIEvent.prototype.setVerb = function (verb) {
if (H5P.jQuery.inArray(verb, H5P.XAPIEvent.allowedXAPIVerbs) !== -1) {
this.data.statement.verb = {
'id': 'http://adlnet.gov/expapi/verbs/' + verb,
'display': {
'en-US': verb
}
};
}
else if (verb.id !== undefined) {
this.data.statement.verb = verb;
}
};
/**
* Get the statements verb id.
*
* @param {boolean} full
* if true the full verb id prefixed by http://adlnet.gov/expapi/verbs/
* will be returned
* @returns {string}
* Verb or null if no verb with an id has been defined
*/
H5P.XAPIEvent.prototype.getVerb = function (full) {
var statement = this.data.statement;
if ('verb' in statement) {
if (full === true) {
return statement.verb;
}
return statement.verb.id.slice(31);
}
else {
return null;
}
};
/**
* Set the object part of the statement.
*
* The id is found automatically (the url to the content)
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.setObject = function (instance) {
if (instance.contentId) {
this.data.statement.object = {
'id': this.getContentXAPIId(instance),
'objectType': 'Activity',
'definition': {
'extensions': {
'http://h5p.org/x-api/h5p-local-content-id': instance.contentId
}
}
};
if (instance.subContentId) {
this.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-subContentId'] = instance.subContentId;
// Don't set titles on main content, title should come from publishing platform
if (typeof instance.getTitle === 'function') {
this.data.statement.object.definition.name = {
"en-US": instance.getTitle()
};
}
}
else {
var content = H5P.getContentForInstance(instance.contentId);
if (content && content.metadata && content.metadata.title) {
this.data.statement.object.definition.name = {
"en-US": H5P.createTitle(content.metadata.title)
};
}
}
}
else {
// Content types view always expect to have a contentId when they are displayed.
// This is not the case if they are displayed in the editor as part of a preview.
// The fix is to set an empty object with definition for the xAPI event, so all
// the content types that rely on this does not have to handle it. This means
// that content types that are being previewed will send xAPI completed events,
// but since there are no scripts that catch these events in the editor,
// this is not a problem.
this.data.statement.object = {
definition: {}
};
}
};
/**
* Set the context part of the statement.
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.setContext = function (instance) {
if (instance.parent && (instance.parent.contentId || instance.parent.subContentId)) {
this.data.statement.context = {
"contextActivities": {
"parent": [
{
"id": this.getContentXAPIId(instance.parent),
"objectType": "Activity"
}
]
}
};
}
if (instance.libraryInfo) {
if (this.data.statement.context === undefined) {
this.data.statement.context = {"contextActivities":{}};
}
this.data.statement.context.contextActivities.category = [
{
"id": "http://h5p.org/libraries/" + instance.libraryInfo.versionedNameNoSpaces,
"objectType": "Activity"
}
];
}
};
/**
* Set the actor. Email and name will be added automatically.
*/
H5P.XAPIEvent.prototype.setActor = function () {
if (H5PIntegration.user !== undefined) {
this.data.statement.actor = {
'name': H5PIntegration.user.name,
'mbox': 'mailto:' + H5PIntegration.user.mail,
'objectType': 'Agent'
};
}
else {
var uuid;
try {
if (localStorage.H5PUserUUID) {
uuid = localStorage.H5PUserUUID;
}
else {
uuid = H5P.createUUID();
localStorage.H5PUserUUID = uuid;
}
}
catch (err) {
// LocalStorage and Cookies are probably disabled. Do not track the user.
uuid = 'not-trackable-' + H5P.createUUID();
}
this.data.statement.actor = {
'account': {
'name': uuid,
'homePage': H5PIntegration.siteUrl
},
'objectType': 'Agent'
};
}
};
/**
* Get the max value of the result - score part of the statement
*
* @returns {number}
* The max score, or null if not defined
*/
H5P.XAPIEvent.prototype.getMaxScore = function () {
return this.getVerifiedStatementValue(['result', 'score', 'max']);
};
/**
* Get the raw value of the result - score part of the statement
*
* @returns {number}
* The score, or null if not defined
*/
H5P.XAPIEvent.prototype.getScore = function () {
return this.getVerifiedStatementValue(['result', 'score', 'raw']);
};
/**
* Get content xAPI ID.
*
* @param {Object} instance
* The H5P instance
*/
H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
var xAPIId;
if (instance.contentId && H5PIntegration && H5PIntegration.contents && H5PIntegration.contents['cid-' + instance.contentId]) {
xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url;
if (instance.subContentId) {
xAPIId += '?subContentId=' + instance.subContentId;
}
}
return xAPIId;
};
/**
* Check if this event is sent from a child (i.e not from grandchild)
*
* @return {Boolean}
*/
H5P.XAPIEvent.prototype.isFromChild = function () {
var parentId = this.getVerifiedStatementValue(['context', 'contextActivities', 'parent', 0, 'id']);
return !parentId || parentId.indexOf('subContentId') === -1;
};
/**
* Figure out if a property exists in the statement and return it
*
* @param {string[]} keys
* List describing the property we're looking for. For instance
* ['result', 'score', 'raw'] for result.score.raw
* @returns {*}
* The value of the property if it is set, null otherwise.
*/
H5P.XAPIEvent.prototype.getVerifiedStatementValue = function (keys) {
var val = this.data.statement;
for (var i = 0; i < keys.length; i++) {
if (val[keys[i]] === undefined) {
return null;
}
val = val[keys[i]];
}
return val;
};
/**
* List of verbs defined at {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary}
*
* @type Array
*/
H5P.XAPIEvent.allowedXAPIVerbs = [
'answered',
'asked',
'attempted',
'attended',
'commented',
'completed',
'exited',
'experienced',
'failed',
'imported',
'initialized',
'interacted',
'launched',
'mastered',
'passed',
'preferred',
'progressed',
'registered',
'responded',
'resumed',
'scored',
'shared',
'suspended',
'terminated',
'voided',
// Custom verbs used for action toolbar below content
'downloaded',
'copied',
'accessed-reuse',
'accessed-embed',
'accessed-copyright'
];
+119
View File
@@ -0,0 +1,119 @@
var H5P = window.H5P = window.H5P || {};
/**
* The external event dispatcher. Others, outside of H5P may register and
* listen for H5P Events here.
*
* @type {H5P.EventDispatcher}
*/
H5P.externalDispatcher = new H5P.EventDispatcher();
// EventDispatcher extensions
/**
* Helper function for triggering xAPI added to the EventDispatcher.
*
* @param {string} verb
* The short id of the verb we want to trigger
* @param {Oject} [extra]
* Extra properties for the xAPI statement
*/
H5P.EventDispatcher.prototype.triggerXAPI = function (verb, extra) {
this.trigger(this.createXAPIEventTemplate(verb, extra));
};
/**
* Helper function to create event templates added to the EventDispatcher.
*
* Will in the future be used to add representations of the questions to the
* statements.
*
* @param {string} verb
* Verb id in short form
* @param {Object} [extra]
* Extra values to be added to the statement
* @returns {H5P.XAPIEvent}
* Instance
*/
H5P.EventDispatcher.prototype.createXAPIEventTemplate = function (verb, extra) {
var event = new H5P.XAPIEvent();
event.setActor();
event.setVerb(verb);
if (extra !== undefined) {
for (var i in extra) {
event.data.statement[i] = extra[i];
}
}
if (!('object' in event.data.statement)) {
event.setObject(this);
}
if (!('context' in event.data.statement)) {
event.setContext(this);
}
return event;
};
/**
* Helper function to create xAPI completed events
*
* DEPRECATED - USE triggerXAPIScored instead
*
* @deprecated
* since 1.5, use triggerXAPIScored instead.
* @param {number} score
* Will be set as the 'raw' value of the score object
* @param {number} maxScore
* will be set as the "max" value of the score object
* @param {boolean} success
* will be set as the "success" value of the result object
*/
H5P.EventDispatcher.prototype.triggerXAPICompleted = function (score, maxScore, success) {
this.triggerXAPIScored(score, maxScore, 'completed', true, success);
};
/**
* Helper function to create scored xAPI events
*
* @param {number} score
* Will be set as the 'raw' value of the score object
* @param {number} maxScore
* Will be set as the "max" value of the score object
* @param {string} verb
* Short form of adl verb
* @param {boolean} completion
* Is this a statement from a completed activity?
* @param {boolean} success
* Is this a statement from an activity that was done successfully?
*/
H5P.EventDispatcher.prototype.triggerXAPIScored = function (score, maxScore, verb, completion, success) {
var event = this.createXAPIEventTemplate(verb);
event.setScoredResult(score, maxScore, this, completion, success);
this.trigger(event);
};
H5P.EventDispatcher.prototype.setActivityStarted = function () {
if (this.activityStartTime === undefined) {
// Don't trigger xAPI events in the editor
if (this.contentId !== undefined &&
H5PIntegration.contents !== undefined &&
H5PIntegration.contents['cid-' + this.contentId] !== undefined) {
this.triggerXAPI('attempted');
}
this.activityStartTime = Date.now();
}
};
/**
* Internal H5P function listening for xAPI completed events and stores scores
*
* @param {H5P.XAPIEvent} event
*/
H5P.xAPICompletedListener = function (event) {
if ((event.getVerb() === 'completed' || event.getVerb() === 'answered') && !event.getVerifiedStatementValue(['context', 'contextActivities', 'parent'])) {
var score = event.getScore();
var maxScore = event.getMaxScore();
var contentId = event.getVerifiedStatementValue(['object', 'definition', 'extensions', 'http://h5p.org/x-api/h5p-local-content-id']);
H5P.setFinished(contentId, score, maxScore);
}
};
+2911
View File
File diff suppressed because it is too large. Load diff
+22
View File
@@ -0,0 +1,22 @@
/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-lLine truncated
var H5P = window.H5P = window.H5P || {};
H5P.jQuery = jQuery.noConflict(true);
H5P.jQuery.fn.__originalLoad = H5P.jQuery.load;
H5P.jQuery.fn.load = function (url, params, callback) {
/**
* NOTE:
* This is needed in order to support old libraries that uses the .load() function
* for elements in the deprecated jQuery way (elem.load(fn)), the correct way to do this
* now is elem.on('load', fn)
*/
if (typeof url === "function") {
console.warn('You are using a deprecated H5P library. Please upgrade!');
let args = Array.prototype.slice.call(arguments);
args.unshift('load');
return H5P.jQuery.fn.on.apply(this, args);
}
return H5P.jQuery.fn.__originalLoad.apply(this, arguments);
}
+436
View File
@@ -0,0 +1,436 @@
/**
* Queue requests and handle them at your convenience
*
* @type {RequestQueue}
*/
H5P.RequestQueue = (function ($, EventDispatcher) {
/**
* A queue for requests, will be automatically processed when regaining connection
*
* @param {boolean} [options.showToast] Show toast when losing or regaining connection
* @constructor
*/
const RequestQueue = function (options) {
EventDispatcher.call(this);
this.processingQueue = false;
options = options || {};
this.showToast = options.showToast;
this.itemName = 'requestQueue';
};
/**
* Add request to queue. Only supports posts currently.
*
* @param {string} url
* @param {Object} data
* @returns {boolean}
*/
RequestQueue.prototype.add = function (url, data) {
if (!window.localStorage) {
return false;
}
let storedStatements = this.getStoredRequests();
if (!storedStatements) {
storedStatements = [];
}
storedStatements.push({
url: url,
data: data,
});
window.localStorage.setItem(this.itemName, JSON.stringify(storedStatements));
this.trigger('requestQueued', {
storedStatements: storedStatements,
processingQueue: this.processingQueue,
});
return true;
};
/**
* Get stored requests
*
* @returns {boolean|Array} Stored requests
*/
RequestQueue.prototype.getStoredRequests = function () {
if (!window.localStorage) {
return false;
}
const item = window.localStorage.getItem(this.itemName);
if (!item) {
return [];
}
return JSON.parse(item);
};
/**
* Clear stored requests
*
* @returns {boolean} True if the storage was successfully cleared
*/
RequestQueue.prototype.clearQueue = function () {
if (!window.localStorage) {
return false;
}
window.localStorage.removeItem(this.itemName);
return true;
};
/**
* Start processing of requests queue
*
* @return {boolean} Returns false if it was not possible to resume processing queue
*/
RequestQueue.prototype.resumeQueue = function () {
// Not supported
if (!H5PIntegration || !window.navigator || !window.localStorage) {
return false;
}
// Already processing
if (this.processingQueue) {
return false;
}
// Attempt to send queued requests
const queue = this.getStoredRequests();
const queueLength = queue.length;
// Clear storage, failed requests will be re-added
this.clearQueue();
// No items left in queue
if (!queueLength) {
this.trigger('emptiedQueue', queue);
return true;
}
// Make sure requests are not changed while they're being handled
this.processingQueue = true;
// Process queue in original order
this.processQueue(queue);
return true
};
/**
* Process first item in the request queue
*
* @param {Array} queue Request queue
*/
RequestQueue.prototype.processQueue = function (queue) {
if (!queue.length) {
return;
}
this.trigger('processingQueue');
// Make sure the requests are processed in a FIFO order
const request = queue.shift();
const self = this;
$.post(request.url, request.data)
.fail(self.onQueuedRequestFail.bind(self, request))
.always(self.onQueuedRequestProcessed.bind(self, queue))
};
/**
* Request fail handler
*
* @param {Object} request
*/
RequestQueue.prototype.onQueuedRequestFail = function (request) {
// Queue the failed request again if we're offline
if (!window.navigator.onLine) {
this.add(request.url, request.data);
}
};
/**
* An item in the queue was processed
*
* @param {Array} queue Queue that was processed
*/
RequestQueue.prototype.onQueuedRequestProcessed = function (queue) {
if (queue.length) {
this.processQueue(queue);
return;
}
// Finished processing this queue
this.processingQueue = false;
// Run empty queue callback with next request queue
const requestQueue = this.getStoredRequests();
this.trigger('queueEmptied', requestQueue);
};
/**
* Display toast message on the first content of current page
*
* @param {string} msg Message to display
* @param {boolean} [forceShow] Force override showing the toast
* @param {Object} [configOverride] Override toast message config
*/
RequestQueue.prototype.displayToastMessage = function (msg, forceShow, configOverride) {
if (!this.showToast && !forceShow) {
return;
}
const config = H5P.jQuery.extend(true, {}, {
position: {
horizontal : 'centered',
vertical: 'centered',
noOverflowX: true,
}
}, configOverride);
H5P.attachToastTo(H5P.jQuery('.h5p-content:first')[0], msg, config);
};
return RequestQueue;
})(H5P.jQuery, H5P.EventDispatcher);
/**
* Request queue for retrying failing requests, will automatically retry them when you come online
*
* @type {offlineRequestQueue}
*/
H5P.OfflineRequestQueue = (function (RequestQueue, Dialog) {
/**
* Constructor
*
* @param {Object} [options] Options for offline request queue
* @param {Object} [options.instance] The H5P instance which UI components are placed within
*/
const offlineRequestQueue = function (options) {
const requestQueue = new RequestQueue();
// We could handle requests from previous pages here, but instead we throw them away
requestQueue.clearQueue();
let startTime = null;
const retryIntervals = [10, 20, 40, 60, 120, 300, 600];
let intervalIndex = -1;
let currentInterval = null;
let isAttached = false;
let isShowing = false;
let isLoading = false;
const instance = options.instance;
const offlineDialog = new Dialog({
headerText: H5P.t('offlineDialogHeader'),
dialogText: H5P.t('offlineDialogBody'),
confirmText: H5P.t('offlineDialogRetryButtonLabel'),
hideCancel: true,
hideExit: true,
classes: ['offline'],
instance: instance,
skipRestoreFocus: true,
});
const dialog = offlineDialog.getElement();
// Add retry text to body
const countDownText = document.createElement('div');
countDownText.classList.add('count-down');
countDownText.innerHTML = H5P.t('offlineDialogRetryMessage')
.replace(':num', '<span class="count-down-num">0</span>');
dialog.querySelector('.h5p-confirmation-dialog-text').appendChild(countDownText);
const countDownNum = countDownText.querySelector('.count-down-num');
// Create throbber
const throbberWrapper = document.createElement('div');
throbberWrapper.classList.add('throbber-wrapper');
const throbber = document.createElement('div');
throbber.classList.add('sending-requests-throbber');
throbberWrapper.appendChild(throbber);
requestQueue.on('requestQueued', function (e) {
// Already processing queue, wait until queue has finished processing before showing dialog
if (e.data && e.data.processingQueue) {
return;
}
if (!isAttached) {
const rootContent = document.body.querySelector('.h5p-content');
if (!rootContent) {
return;
}
offlineDialog.appendTo(rootContent);
rootContent.appendChild(throbberWrapper);
isAttached = true;
}
startCountDown();
}.bind(this));
requestQueue.on('queueEmptied', function (e) {
if (e.data && e.data.length) {
// New requests were added while processing queue or requests failed again. Re-queue requests.
startCountDown(true);
return;
}
// Successfully emptied queue
clearInterval(currentInterval);
toggleThrobber(false);
intervalIndex = -1;
if (isShowing) {
offlineDialog.hide();
isShowing = false;
}
requestQueue.displayToastMessage(
H5P.t('offlineSuccessfulSubmit'),
true,
{
position: {
vertical: 'top',
offsetVertical: '100',
}
}
);
}.bind(this));
offlineDialog.on('confirmed', function () {
// Show dialog on next render in case it is being hidden by the 'confirm' button
isShowing = false;
setTimeout(function () {
retryRequests();
}, 100);
}.bind(this));
// Initialize listener for when requests are added to queue
window.addEventListener('online', function () {
retryRequests();
}.bind(this));
// Listen for queued requests outside the iframe
window.addEventListener('message', function (event) {
const isValidQueueEvent = window.parent === event.source
&& event.data.context === 'h5p'
&& event.data.action === 'queueRequest';
if (!isValidQueueEvent) {
return;
}
this.add(event.data.url, event.data.data);
}.bind(this));
/**
* Toggle throbber visibility
*
* @param {boolean} [forceShow] Will force throbber visibility if set
*/
const toggleThrobber = function (forceShow) {
isLoading = !isLoading;
if (forceShow !== undefined) {
isLoading = forceShow;
}
if (isLoading && isShowing) {
offlineDialog.hide();
isShowing = false;
}
if (isLoading) {
throbberWrapper.classList.add('show');
}
else {
throbberWrapper.classList.remove('show');
}
};
/**
* Retries the failed requests
*/
const retryRequests = function () {
clearInterval(currentInterval);
toggleThrobber(true);
requestQueue.resumeQueue();
};
/**
* Increments retry interval
*/
const incrementRetryInterval = function () {
intervalIndex += 1;
if (intervalIndex >= retryIntervals.length) {
intervalIndex = retryIntervals.length - 1;
}
};
/**
* Starts counting down to retrying queued requests.
*
* @param forceDelayedShow
*/
const startCountDown = function (forceDelayedShow) {
// Already showing, wait for retry
if (isShowing) {
return;
}
toggleThrobber(false);
if (!isShowing) {
if (forceDelayedShow) {
// Must force delayed show since dialog may be hiding, and confirmation dialog does not
// support this.
setTimeout(function () {
offlineDialog.show(0);
}, 100);
}
else {
offlineDialog.show(0);
}
}
isShowing = true;
startTime = new Date().getTime();
incrementRetryInterval();
clearInterval(currentInterval);
currentInterval = setInterval(updateCountDown, 100);
};
/**
* Updates the count down timer. Retries requests when time expires.
*/
const updateCountDown = function () {
const time = new Date().getTime();
const timeElapsed = Math.floor((time - startTime) / 1000);
const timeLeft = retryIntervals[intervalIndex] - timeElapsed;
countDownNum.textContent = timeLeft.toString();
// Retry interval reached, retry requests
if (timeLeft <= 0) {
retryRequests();
}
};
/**
* Add request to offline request queue. Only supports posts for now.
*
* @param {string} url The request url
* @param {Object} data The request data
*/
this.add = function (url, data) {
// Only queue request if it failed because we are offline
if (window.navigator.onLine) {
return false;
}
requestQueue.add(url, data);
};
};
return offlineRequestQueue;
})(H5P.RequestQueue, H5P.ConfirmationDialog);
+68
View File
@@ -0,0 +1,68 @@
/* global H5PDisableHubData */
/**
* Global data for disable hub functionality
*
* @typedef {object} H5PDisableHubData Data passed in from the backend
*
* @property {string} selector Selector for the disable hub check-button
* @property {string} overlaySelector Selector for the element that the confirmation dialog will mask
* @property {Array} errors Errors found with the current server setup
*
* @property {string} header Header of the confirmation dialog
* @property {string} confirmationDialogMsg Body of the confirmation dialog
* @property {string} cancelLabel Cancel label of the confirmation dialog
* @property {string} confirmLabel Confirm button label of the confirmation dialog
*
*/
/**
* Utility that makes it possible to force the user to confirm that he really
* wants to use the H5P hub without proper server settings.
*/
(function ($) {
$(document).on('ready', function () {
// No data found
if (!H5PDisableHubData) {
return;
}
// No errors found, no need for confirmation dialog
if (!H5PDisableHubData.errors || !H5PDisableHubData.errors.length) {
return;
}
H5PDisableHubData.selector = H5PDisableHubData.selector ||
'.h5p-settings-disable-hub-checkbox';
H5PDisableHubData.overlaySelector = H5PDisableHubData.overlaySelector ||
'.h5p-settings-container';
var dialogHtml = '<div>' +
'<p>' + H5PDisableHubData.errors.join('</p><p>') + '</p>' +
'<p>' + H5PDisableHubData.confirmationDialogMsg + '</p>';
// Create confirmation dialog, make sure to include translations
var confirmationDialog = new H5P.ConfirmationDialog({
headerText: H5PDisableHubData.header,
dialogText: dialogHtml,
cancelText: H5PDisableHubData.cancelLabel,
confirmText: H5PDisableHubData.confirmLabel
}).appendTo($(H5PDisableHubData.overlaySelector).get(0));
confirmationDialog.on('confirmed', function () {
enableButton.get(0).checked = true;
});
confirmationDialog.on('canceled', function () {
enableButton.get(0).checked = false;
});
var enableButton = $(H5PDisableHubData.selector);
enableButton.change(function () {
if ($(this).is(':checked')) {
confirmationDialog.show(enableButton.offset().top);
}
});
});
})(H5P.jQuery);