Merge branch 'master' of github.com:h5p/h5p-php-library
commit
18e2b79cc6
|
@ -1055,24 +1055,27 @@ class H5PValidator {
|
||||||
$valid = $this->isValidRequiredH5pData($h5pData, $required, $library_name);
|
$valid = $this->isValidRequiredH5pData($h5pData, $required, $library_name);
|
||||||
$valid = $this->isValidOptionalH5pData($h5pData, $optional, $library_name) && $valid;
|
$valid = $this->isValidOptionalH5pData($h5pData, $optional, $library_name) && $valid;
|
||||||
|
|
||||||
// Test library core version requirement. If no requirement is set,
|
// Check the library's required API version of Core.
|
||||||
// this implicitly means 1.0, which shall work on newer versions
|
// If no requirement is set this implicitly means 1.0.
|
||||||
// too.
|
|
||||||
if (isset($h5pData['coreApi']) && !empty($h5pData['coreApi'])) {
|
if (isset($h5pData['coreApi']) && !empty($h5pData['coreApi'])) {
|
||||||
if (($h5pData['coreApi']['majorVersion'] > H5PCore::$coreApi['majorVersion']) ||
|
if (($h5pData['coreApi']['majorVersion'] > H5PCore::$coreApi['majorVersion']) ||
|
||||||
(($h5pData['coreApi']['majorVersion'] == H5PCore::$coreApi['majorVersion']) &&
|
( ($h5pData['coreApi']['majorVersion'] == H5PCore::$coreApi['majorVersion']) &&
|
||||||
($h5pData['coreApi']['minorVersion'] > H5PCore::$coreApi['minorVersion'])))
|
($h5pData['coreApi']['minorVersion'] > H5PCore::$coreApi['minorVersion']) )) {
|
||||||
{
|
|
||||||
$this->h5pF->setErrorMessage(
|
$this->h5pF->setErrorMessage(
|
||||||
$this->h5pF->t('The library "%libraryName" requires H5P %requiredVersion, but only H5P %coreApi is installed.',
|
$this->h5pF->t('The system was unable to install the <em>%component</em> component from the package, it requires a newer version of the H5P plugin. This site is currently running version %current, whereas the required version is %required or higher. You should consider upgrading and then try again.',
|
||||||
array(
|
array(
|
||||||
'%libraryName' => $library_name,
|
'%component' => (isset($h5pData['title']) ? $h5pData['title'] : $library_name),
|
||||||
'%requiredVersion' => $h5pData['coreApi']['majorVersion'] . '.' . $h5pData['coreApi']['minorVersion'],
|
'%current' => H5PCore::$coreApi['majorVersion'] . '.' . H5PCore::$coreApi['minorVersion'],
|
||||||
'%coreApi' => H5PCore::$coreApi['majorVersion'] . '.' . H5PCore::$coreApi['minorVersion']
|
'%required' => $h5pData['coreApi']['majorVersion'] . '.' . $h5pData['coreApi']['minorVersion']
|
||||||
)));
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$valid = false;
|
$valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2469,7 +2472,9 @@ class H5PCore {
|
||||||
|
|
||||||
// Determine remote/visitor origin
|
// Determine remote/visitor origin
|
||||||
if ($type === 'network' ||
|
if ($type === 'network' ||
|
||||||
($type === 'local' && !preg_match('/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i', $_SERVER['REMOTE_ADDR']))) {
|
($type === 'local' &&
|
||||||
|
isset($_SERVER['REMOTE_ADDR']) &&
|
||||||
|
!preg_match('/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i', $_SERVER['REMOTE_ADDR']))) {
|
||||||
if (isset($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
if (isset($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||||
// Internet
|
// Internet
|
||||||
$this->h5pF->setOption('site_type', 'internet');
|
$this->h5pF->setOption('site_type', 'internet');
|
||||||
|
@ -2893,7 +2898,12 @@ class H5PContentValidator {
|
||||||
|
|
||||||
// Check if string is within allowed length
|
// Check if string is within allowed length
|
||||||
if (isset($semantics->maxLength)) {
|
if (isset($semantics->maxLength)) {
|
||||||
$text = mb_substr($text, 0, $semantics->maxLength);
|
if (!extension_loaded('mbstring')) {
|
||||||
|
$this->h5pF->setErrorMessage($this->h5pF->t('The mbstring PHP extension is not loaded. H5P need this to function properly'), 'error');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$text = mb_substr($text, 0, $semantics->maxLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if string is according to optional regexp in semantics
|
// Check if string is according to optional regexp in semantics
|
||||||
|
@ -2943,7 +2953,11 @@ class H5PContentValidator {
|
||||||
// file name, 2. testing against a returned error array that could
|
// file name, 2. testing against a returned error array that could
|
||||||
// never be more than 1 element long anyway, 3. recreating the regex
|
// never be more than 1 element long anyway, 3. recreating the regex
|
||||||
// for every file.
|
// for every file.
|
||||||
if (!preg_match($wl_regex, mb_strtolower($file))) {
|
if (!extension_loaded('mbstring')) {
|
||||||
|
$this->h5pF->setErrorMessage($this->h5pF->t('The mbstring PHP extension is not loaded. H5P need this to function properly'), 'error');
|
||||||
|
$valid = FALSE;
|
||||||
|
}
|
||||||
|
else if (!preg_match($wl_regex, mb_strtolower($file))) {
|
||||||
$this->h5pF->setErrorMessage($this->h5pF->t('File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.', array('%filename' => $file, '%files-allowed' => $whitelist)), 'error');
|
$this->h5pF->setErrorMessage($this->h5pF->t('File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.', array('%filename' => $file, '%files-allowed' => $whitelist)), 'error');
|
||||||
$valid = FALSE;
|
$valid = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,10 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
EventDispatcher.call(this);
|
EventDispatcher.call(this);
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
// Make sure confirmation dialogs have unique id
|
||||||
|
H5P.ConfirmationDialog.uniqueId += 1;
|
||||||
|
var uniqueId = H5P.ConfirmationDialog.uniqueId;
|
||||||
|
|
||||||
// Default options
|
// Default options
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.headerText = options.headerText || H5P.t('confirmDialogHeader');
|
options.headerText = options.headerText || H5P.t('confirmDialogHeader');
|
||||||
|
@ -24,6 +28,36 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
options.cancelText = options.cancelText || H5P.t('cancelLabel');
|
options.cancelText = options.cancelText || H5P.t('cancelLabel');
|
||||||
options.confirmText = options.confirmText || H5P.t('confirmLabel');
|
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
|
// Offset of exit button
|
||||||
var exitButtonOffset = 2 * 16;
|
var exitButtonOffset = 2 * 16;
|
||||||
var shadowOffset = 8;
|
var shadowOffset = 8;
|
||||||
|
@ -39,7 +73,15 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
// Create outer popup
|
// Create outer popup
|
||||||
var popup = document.createElement('div');
|
var popup = document.createElement('div');
|
||||||
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
|
popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
|
||||||
|
popup.setAttribute('role', 'dialog');
|
||||||
|
popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
|
||||||
popupBackground.appendChild(popup);
|
popupBackground.appendChild(popup);
|
||||||
|
popup.addEventListener('keydown', function (e) {
|
||||||
|
if (e.which === 27) {// Esc key
|
||||||
|
// Exit dialog
|
||||||
|
dialogCanceled(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Popup header
|
// Popup header
|
||||||
var header = document.createElement('div');
|
var header = document.createElement('div');
|
||||||
|
@ -61,6 +103,7 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
var text = document.createElement('div');
|
var text = document.createElement('div');
|
||||||
text.classList.add('h5p-confirmation-dialog-text');
|
text.classList.add('h5p-confirmation-dialog-text');
|
||||||
text.innerHTML = options.dialogText;
|
text.innerHTML = options.dialogText;
|
||||||
|
text.id = 'h5p-confirmation-dialog-dialog-text-' + uniqueId;
|
||||||
body.appendChild(text);
|
body.appendChild(text);
|
||||||
|
|
||||||
// Popup buttons
|
// Popup buttons
|
||||||
|
@ -69,89 +112,160 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
body.appendChild(buttons);
|
body.appendChild(buttons);
|
||||||
|
|
||||||
// Cancel button
|
// Cancel button
|
||||||
var cancelButton = document.createElement('a');
|
var cancelButton = document.createElement('button');
|
||||||
cancelButton.classList.add('h5p-core-cancel-button');
|
cancelButton.classList.add('h5p-core-cancel-button');
|
||||||
cancelButton.href = '#';
|
|
||||||
cancelButton.textContent = options.cancelText;
|
cancelButton.textContent = options.cancelText;
|
||||||
cancelButton.onclick = function (e) {
|
|
||||||
self.hide();
|
|
||||||
self.trigger('canceled');
|
|
||||||
e.preventDefault();
|
|
||||||
};
|
|
||||||
cancelButton.onkeydown = function (e) {
|
|
||||||
if (e.which === 32) { // Space
|
|
||||||
// Prevent jumping
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
else if (e.which === 13) { // Enter
|
|
||||||
self.hide();
|
|
||||||
self.trigger('canceled');
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
buttons.appendChild(cancelButton);
|
|
||||||
|
|
||||||
// Confirm button
|
// Confirm button
|
||||||
var confirmButton = document.createElement('a');
|
var confirmButton = document.createElement('button');
|
||||||
confirmButton.classList.add('h5p-core-button',
|
confirmButton.classList.add('h5p-core-button',
|
||||||
'h5p-confirmation-dialog-confirm-button');
|
'h5p-confirmation-dialog-confirm-button');
|
||||||
confirmButton.href = '#';
|
|
||||||
confirmButton.textContent = options.confirmText;
|
confirmButton.textContent = options.confirmText;
|
||||||
confirmButton.onclick = function (e) {
|
|
||||||
self.hide();
|
|
||||||
self.trigger('confirmed');
|
|
||||||
e.preventDefault();
|
|
||||||
};
|
|
||||||
confirmButton.onkeydown = function (e) {
|
|
||||||
if (e.which === 32) { // Space
|
|
||||||
// Prevent jumping
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
else if (e.which === 13) { // Enter
|
|
||||||
self.hide();
|
|
||||||
self.trigger('confirmed');
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
buttons.appendChild(confirmButton);
|
|
||||||
|
|
||||||
// Exit button
|
// Exit button
|
||||||
var exitButton = document.createElement('a');
|
var exitButton = document.createElement('button');
|
||||||
exitButton.href = '#';
|
|
||||||
exitButton.classList.add('h5p-confirmation-dialog-exit');
|
exitButton.classList.add('h5p-confirmation-dialog-exit');
|
||||||
exitButton.onclick = function (e) {
|
exitButton.setAttribute('aria-hidden', 'true');
|
||||||
self.hide();
|
exitButton.tabIndex = -1;
|
||||||
self.trigger('canceled');
|
exitButton.title = options.cancelText;
|
||||||
e.preventDefault();
|
|
||||||
};
|
// Cancel handler
|
||||||
exitButton.onkeydown = function (e) {
|
cancelButton.addEventListener('click', dialogCanceled);
|
||||||
|
cancelButton.addEventListener('keydown', function (e) {
|
||||||
if (e.which === 32) { // Space
|
if (e.which === 32) { // Space
|
||||||
// Prevent jumping
|
dialogCanceled(e);
|
||||||
e.preventDefault();
|
|
||||||
}
|
}
|
||||||
else if (e.which === 13) { // Enter
|
else if (e.which === 9 && e.shiftKey) { // Shift-tab
|
||||||
self.hide();
|
flowTo(confirmButton, e);
|
||||||
self.trigger('canceled');
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
buttons.appendChild(cancelButton);
|
||||||
|
|
||||||
|
// Confirm handler
|
||||||
|
confirmButton.addEventListener('click', dialogConfirmed);
|
||||||
|
confirmButton.addEventListener('keydown', function (e) {
|
||||||
|
if (e.which === 32) { // Space
|
||||||
|
dialogConfirmed(e);
|
||||||
|
}
|
||||||
|
else if (e.which === 9 && !e.shiftKey) { // Tab
|
||||||
|
flowTo(cancelButton, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
buttons.appendChild(confirmButton);
|
||||||
|
|
||||||
|
// Exit handler
|
||||||
|
exitButton.addEventListener('click', dialogCanceled);
|
||||||
|
exitButton.addEventListener('keydown', function (e) {
|
||||||
|
if (e.which === 32) { // Space
|
||||||
|
dialogCanceled(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
popup.appendChild(exitButton);
|
popup.appendChild(exitButton);
|
||||||
|
|
||||||
// Wrapper element
|
// Wrapper element
|
||||||
var wrapperElement;
|
var wrapperElement;
|
||||||
|
|
||||||
|
// Focus capturing
|
||||||
|
var focusPredator;
|
||||||
|
|
||||||
|
// Maintains hidden state of elements
|
||||||
|
var wrapperSiblingsHidden = [];
|
||||||
|
var popupSiblingsHidden = [];
|
||||||
|
|
||||||
|
// Element with focus before dialog
|
||||||
|
var previouslyFocused;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append confirmation dialog
|
* Set parent of confirmation dialog
|
||||||
* @param {HTMLElement} wrapper
|
* @param {HTMLElement} wrapper
|
||||||
* @returns {H5P.ConfirmationDialog}
|
* @returns {H5P.ConfirmationDialog}
|
||||||
*/
|
*/
|
||||||
this.appendTo = function (wrapper) {
|
this.appendTo = function (wrapper) {
|
||||||
wrapper.appendChild(popupBackground);
|
|
||||||
wrapperElement = wrapper;
|
wrapperElement = wrapper;
|
||||||
|
|
||||||
return this;
|
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.
|
* Fit popup to container. Makes sure it doesn't overflow.
|
||||||
* @params {number} [offsetTop] Offset of popup
|
* @params {number} [offsetTop] Offset of popup
|
||||||
|
@ -182,6 +296,11 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
* @returns {H5P.ConfirmationDialog}
|
* @returns {H5P.ConfirmationDialog}
|
||||||
*/
|
*/
|
||||||
this.show = function (offsetTop) {
|
this.show = function (offsetTop) {
|
||||||
|
// Capture focused item
|
||||||
|
previouslyFocused = document.activeElement;
|
||||||
|
wrapperElement.appendChild(popupBackground);
|
||||||
|
startCapturingFocus();
|
||||||
|
disableUnderlay();
|
||||||
popupBackground.classList.remove('hidden');
|
popupBackground.classList.remove('hidden');
|
||||||
fitToContainer(offsetTop);
|
fitToContainer(offsetTop);
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
@ -213,8 +332,14 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
this.hide = function () {
|
this.hide = function () {
|
||||||
popupBackground.classList.add('hiding');
|
popupBackground.classList.add('hiding');
|
||||||
popup.classList.add('hidden');
|
popup.classList.add('hidden');
|
||||||
|
|
||||||
|
// Restore focus
|
||||||
|
stopCapturingFocus();
|
||||||
|
previouslyFocused.focus();
|
||||||
|
restoreUnderlay();
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
popupBackground.classList.add('hidden');
|
popupBackground.classList.add('hidden');
|
||||||
|
wrapperElement.removeChild(popupBackground);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -227,3 +352,5 @@ H5P.ConfirmationDialog = (function (EventDispatcher) {
|
||||||
return ConfirmationDialog;
|
return ConfirmationDialog;
|
||||||
|
|
||||||
}(H5P.EventDispatcher));
|
}(H5P.EventDispatcher));
|
||||||
|
|
||||||
|
H5P.ConfirmationDialog.uniqueId = -1;
|
||||||
|
|
|
@ -108,11 +108,11 @@ var H5PDataView = (function ($) {
|
||||||
else {
|
else {
|
||||||
// Update table data
|
// Update table data
|
||||||
self.updateTable(data.rows);
|
self.updateTable(data.rows);
|
||||||
|
|
||||||
// Update pagination widget
|
|
||||||
self.updatePagination(data.num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update pagination widget
|
||||||
|
self.updatePagination(data.num);
|
||||||
|
|
||||||
if (self.loaded !== undefined) {
|
if (self.loaded !== undefined) {
|
||||||
self.loaded();
|
self.loaded();
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,6 @@ var H5PDataView = (function ($) {
|
||||||
var remove = function () {
|
var remove = function () {
|
||||||
self.facets[col].$tag.remove();
|
self.facets[col].$tag.remove();
|
||||||
delete self.facets[col];
|
delete self.facets[col];
|
||||||
self.offset = 0; // Reset to page 1
|
|
||||||
self.loadData();
|
self.loadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -276,9 +275,6 @@ var H5PDataView = (function ($) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset to page 1
|
|
||||||
self.offset = 0;
|
|
||||||
|
|
||||||
// Load data with new filter
|
// Load data with new filter
|
||||||
self.loadData();
|
self.loadData();
|
||||||
};
|
};
|
||||||
|
@ -292,6 +288,11 @@ var H5PDataView = (function ($) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (self.pagination === undefined) {
|
if (self.pagination === undefined) {
|
||||||
|
if (self.table === undefined) {
|
||||||
|
// No table, no pagination
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create new widget
|
// Create new widget
|
||||||
var $pagerContainer = $('<div/>', {'class': 'h5p-pagination'});
|
var $pagerContainer = $('<div/>', {'class': 'h5p-pagination'});
|
||||||
self.pagination = new H5PUtils.Pagination(num, self.limit, function (offset) {
|
self.pagination = new H5PUtils.Pagination(num, self.limit, function (offset) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ H5P.XAPIEvent.prototype.constructor = H5P.XAPIEvent;
|
||||||
*/
|
*/
|
||||||
H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, completion, success) {
|
H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, completion, success) {
|
||||||
this.data.statement.result = {};
|
this.data.statement.result = {};
|
||||||
|
|
||||||
if (typeof score !== 'undefined') {
|
if (typeof score !== 'undefined') {
|
||||||
if (typeof maxScore === 'undefined') {
|
if (typeof maxScore === 'undefined') {
|
||||||
this.data.statement.result.score = {'raw': score};
|
this.data.statement.result.score = {'raw': score};
|
||||||
|
@ -40,22 +40,22 @@ H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof completion === 'undefined') {
|
if (typeof completion === 'undefined') {
|
||||||
this.data.statement.result.completion = (this.getVerb() === 'completed' || this.getVerb() === 'answered');
|
this.data.statement.result.completion = (this.getVerb() === 'completed' || this.getVerb() === 'answered');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.data.statement.result.completion = completion;
|
this.data.statement.result.completion = completion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof success !== 'undefined') {
|
if (typeof success !== 'undefined') {
|
||||||
this.data.statement.result.success = success;
|
this.data.statement.result.success = success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance && instance.activityStartTime) {
|
if (instance && instance.activityStartTime) {
|
||||||
var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100;
|
var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100;
|
||||||
// xAPI spec allows a precision of 0.01 seconds
|
// xAPI spec allows a precision of 0.01 seconds
|
||||||
|
|
||||||
this.data.statement.result.duration = 'PT' + duration + 'S';
|
this.data.statement.result.duration = 'PT' + duration + 'S';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -188,12 +188,18 @@ H5P.XAPIEvent.prototype.setActor = function () {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var uuid;
|
var uuid;
|
||||||
if (localStorage.H5PUserUUID) {
|
try {
|
||||||
uuid = localStorage.H5PUserUUID;
|
if (localStorage.H5PUserUUID) {
|
||||||
|
uuid = localStorage.H5PUserUUID;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uuid = H5P.createUUID();
|
||||||
|
localStorage.H5PUserUUID = uuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
catch (err) {
|
||||||
uuid = H5P.createUUID();
|
// LocalStorage and Cookies are probably disabled. Do not track the user.
|
||||||
localStorage.H5PUserUUID = uuid;
|
uuid = 'not-trackable-' + H5P.createUUID();
|
||||||
}
|
}
|
||||||
this.data.statement.actor = {
|
this.data.statement.actor = {
|
||||||
'account': {
|
'account': {
|
||||||
|
|
12
js/h5p.js
12
js/h5p.js
|
@ -122,13 +122,15 @@ H5P.init = function (target) {
|
||||||
delete contentData.contentUserData;
|
delete contentData.contentUserData;
|
||||||
var dialog = new H5P.Dialog('content-user-data-reset', 'Data Reset', '<p>' + H5P.t('contentChanged') + '</p><p>' + H5P.t('startingOver') + '</p><div class="h5p-dialog-ok-button" tabIndex="0" role="button">OK</div>', $container);
|
var dialog = new H5P.Dialog('content-user-data-reset', 'Data Reset', '<p>' + H5P.t('contentChanged') + '</p><p>' + H5P.t('startingOver') + '</p><div class="h5p-dialog-ok-button" tabIndex="0" role="button">OK</div>', $container);
|
||||||
H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) {
|
H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) {
|
||||||
$dialog.find('.h5p-dialog-ok-button').click(function () {
|
|
||||||
dialog.close();
|
var closeDialog = function (event) {
|
||||||
}).keypress(function (event) {
|
if (event.type === 'click' || event.which === 32) {
|
||||||
if (event.which === 32) {
|
|
||||||
dialog.close();
|
dialog.close();
|
||||||
|
H5P.deleteUserData(contentId, 'state', 0);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
$dialog.find('.h5p-dialog-ok-button').click(closeDialog).keypress(closeDialog);
|
||||||
});
|
});
|
||||||
dialog.open();
|
dialog.open();
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,9 +81,9 @@
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.h5p-confirmation-dialog-exit:visited,
|
button.h5p-confirmation-dialog-exit:visited,
|
||||||
a.h5p-confirmation-dialog-exit:link,
|
button.h5p-confirmation-dialog-exit:link,
|
||||||
a.h5p-confirmation-dialog-exit {
|
button.h5p-confirmation-dialog-exit {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -95,8 +95,8 @@ a.h5p-confirmation-dialog-exit {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.h5p-confirmation-dialog-exit:focus,
|
button.h5p-confirmation-dialog-exit:focus,
|
||||||
a.h5p-confirmation-dialog-exit:hover {
|
button.h5p-confirmation-dialog-exit:hover {
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
a.h5p-core-button:visited,
|
button.h5p-core-button:visited,
|
||||||
a.h5p-core-button:link,
|
button.h5p-core-button:link,
|
||||||
a.h5p-core-button {
|
button.h5p-core-button {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
padding: 0.5em 1.25em;
|
padding: 0.5em 1.25em;
|
||||||
|
@ -20,15 +20,15 @@ a.h5p-core-button {
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
a.h5p-core-button:hover,
|
button.h5p-core-button:hover,
|
||||||
a.h5p-core-button:focus {
|
button.h5p-core-button:focus {
|
||||||
background: #1356a3;
|
background: #1356a3;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
-webkit-transition: initial;
|
-webkit-transition: initial;
|
||||||
transition: initial;
|
transition: initial;
|
||||||
}
|
}
|
||||||
a.h5p-core-button:active {
|
button.h5p-core-button:active {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: #104888;
|
background: #104888;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ a.h5p-core-button:active {
|
||||||
box-shadow: inset 0 4px 0 #0e407a;
|
box-shadow: inset 0 4px 0 #0e407a;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.h5p-core-button:before {
|
button.h5p-core-button:before {
|
||||||
font-family: 'H5P';
|
font-family: 'H5P';
|
||||||
padding-right: 0.15em;
|
padding-right: 0.15em;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
@ -45,18 +45,20 @@ a.h5p-core-button:before {
|
||||||
line-height: 0.7;
|
line-height: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.h5p-core-cancel-button:visited,
|
button.h5p-core-cancel-button:visited,
|
||||||
a.h5p-core-cancel-button:link,
|
button.h5p-core-cancel-button:link,
|
||||||
a.h5p-core-cancel-button {
|
button.h5p-core-cancel-button {
|
||||||
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: #a00;
|
color: #a00;
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.h5p-core-cancel-button:hover,
|
button.h5p-core-cancel-button:hover,
|
||||||
a.h5p-core-cancel-button:focus {
|
button.h5p-core-cancel-button:focus {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
color: #e40000;
|
color: #e40000;
|
||||||
|
|
Loading…
Reference in New Issue