diff --git a/.gitignore b/.gitignore
index 9577d19..e8d34a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
vendor
*~
-
+.idea
\ No newline at end of file
diff --git a/fonts/h5p-core-14.eot b/fonts/h5p-core-14.eot
deleted file mode 100644
index 9a90816..0000000
Binary files a/fonts/h5p-core-14.eot and /dev/null differ
diff --git a/fonts/h5p-core-14.ttf b/fonts/h5p-core-14.ttf
deleted file mode 100644
index 77aa1c7..0000000
Binary files a/fonts/h5p-core-14.ttf and /dev/null differ
diff --git a/fonts/h5p-core-14.woff b/fonts/h5p-core-14.woff
deleted file mode 100644
index e11a5c7..0000000
Binary files a/fonts/h5p-core-14.woff and /dev/null differ
diff --git a/fonts/h5p-core-16.eot b/fonts/h5p-core-16.eot
new file mode 100644
index 0000000..239079b
Binary files /dev/null and b/fonts/h5p-core-16.eot differ
diff --git a/fonts/h5p-core-14.svg b/fonts/h5p-core-16.svg
similarity index 56%
rename from fonts/h5p-core-14.svg
rename to fonts/h5p-core-16.svg
index f66252d..d0bdb88 100644
--- a/fonts/h5p-core-14.svg
+++ b/fonts/h5p-core-16.svg
@@ -1,14 +1,34 @@
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/fonts/h5p-core-16.ttf b/fonts/h5p-core-16.ttf
new file mode 100644
index 0000000..daf1571
Binary files /dev/null and b/fonts/h5p-core-16.ttf differ
diff --git a/fonts/h5p-core-16.woff b/fonts/h5p-core-16.woff
new file mode 100644
index 0000000..d654df4
Binary files /dev/null and b/fonts/h5p-core-16.woff differ
diff --git a/h5p-default-storage.class.php b/h5p-default-storage.class.php
index 6e39670..1141bda 100644
--- a/h5p-default-storage.class.php
+++ b/h5p-default-storage.class.php
@@ -399,6 +399,8 @@ class H5PDefaultStorage implements \H5PFileStorage {
throw new \Exception('unabletocopy');
}
+ $ignoredFiles = self::getIgnoredFiles("{$source}/.h5pignore");
+
$dir = opendir($source);
if ($dir === FALSE) {
trigger_error('Unable to open directory ' . $source, E_USER_WARNING);
@@ -406,7 +408,7 @@ class H5PDefaultStorage implements \H5PFileStorage {
}
while (false !== ($file = readdir($dir))) {
- if (($file != '.') && ($file != '..') && $file != '.git' && $file != '.gitignore') {
+ if (($file != '.') && ($file != '..') && $file != '.git' && $file != '.gitignore' && !in_array($file, $ignoredFiles)) {
if (is_dir("{$source}/{$file}")) {
self::copyFileTree("{$source}/{$file}", "{$destination}/{$file}");
}
@@ -418,6 +420,25 @@ class H5PDefaultStorage implements \H5PFileStorage {
closedir($dir);
}
+ /**
+ * Retrieve array of file names from file.
+ *
+ * @param string $file
+ * @return array Array with files that should be ignored
+ */
+ private static function getIgnoredFiles($file) {
+ if (file_exists($file) === FALSE) {
+ return array();
+ }
+
+ $contents = file_get_contents($file);
+ if ($contents === FALSE) {
+ return array();
+ }
+
+ return preg_split('/\s+/', $contents);
+ }
+
/**
* Recursive function that makes sure the specified directory exists and
* is writable.
diff --git a/h5p.classes.php b/h5p.classes.php
index cafa043..473d641 100644
--- a/h5p.classes.php
+++ b/h5p.classes.php
@@ -558,6 +558,16 @@ interface H5PFrameworkInterface {
* Will trigger after the export file is created.
*/
public function afterExportCreated();
+
+ /**
+ * Check if user has permissions to an action
+ *
+ * @method hasPermission
+ * @param [H5PPermission] $permission Permission type, ref H5PPermission
+ * @param [int] $id Id need by platform to determine permission
+ * @return boolean
+ */
+ public function hasPermission($permission, $id = NULL);
}
/**
@@ -1669,6 +1679,20 @@ Class H5PExport {
}
}
+abstract class H5PPermission {
+ const DOWNLOAD_H5P = 0;
+ const EMBED_H5P = 1;
+}
+
+abstract class H5PDisplayOptionBehaviour {
+ const NEVER_SHOW = 0;
+ const CONTROLLED_BY_AUTHOR_DEFAULT_ON = 1;
+ const CONTROLLED_BY_AUTHOR_DEFAULT_OFF = 2;
+ const ALWAYS_SHOW = 3;
+ const CONTROLLED_BY_PERMISSIONS = 4;
+}
+
+
/**
* Functions and storage shared by the other H5P classes
*/
@@ -1676,7 +1700,7 @@ class H5PCore {
public static $coreApi = array(
'majorVersion' => 1,
- 'minorVersion' => 11
+ 'minorVersion' => 12
);
public static $styles = array(
'styles/h5p.css',
@@ -1690,7 +1714,8 @@ class H5PCore {
'js/h5p-x-api-event.js',
'js/h5p-x-api.js',
'js/h5p-content-type.js',
- 'js/h5p-confirmation-dialog.js'
+ 'js/h5p-confirmation-dialog.js',
+ 'js/h5p-action-bar.js'
);
public static $adminScripts = array(
'js/jquery.js',
@@ -1713,12 +1738,18 @@ class H5PCore {
const DISABLE_COPYRIGHT = 8;
const DISABLE_ABOUT = 16;
+ const DISPLAY_OPTION_FRAME = 'frame';
+ const DISPLAY_OPTION_DOWNLOAD = 'export';
+ const DISPLAY_OPTION_EMBED = 'embed';
+ const DISPLAY_OPTION_COPYRIGHT = 'copyright';
+ const DISPLAY_OPTION_ABOUT = 'icon';
+
// Map flags to string
public static $disable = array(
- self::DISABLE_FRAME => 'frame',
- self::DISABLE_DOWNLOAD => 'download',
- self::DISABLE_EMBED => 'embed',
- self::DISABLE_COPYRIGHT => 'copyright'
+ self::DISABLE_FRAME => self::DISPLAY_OPTION_FRAME,
+ self::DISABLE_DOWNLOAD => self::DISPLAY_OPTION_DOWNLOAD,
+ self::DISABLE_EMBED => self::DISPLAY_OPTION_EMBED,
+ self::DISABLE_COPYRIGHT => self::DISPLAY_OPTION_COPYRIGHT
);
/**
@@ -2423,7 +2454,9 @@ class H5PCore {
// Handle libraries metadata
if (isset($json->libraries)) {
foreach ($json->libraries as $machineName => $libInfo) {
- $this->h5pF->setLibraryTutorialUrl($machineName, $libInfo->tutorialUrl);
+ if (isset($libInfo->tutorialUrl)) {
+ $this->h5pF->setLibraryTutorialUrl($machineName, $libInfo->tutorialUrl);
+ }
}
}
@@ -2440,54 +2473,152 @@ class H5PCore {
}
/**
- *
- */
- public function getGlobalDisable() {
- $disable = self::DISABLE_NONE;
-
- // Allow global settings to override and disable options
- if (!$this->h5pF->getOption('frame', TRUE)) {
- $disable |= self::DISABLE_FRAME;
- }
- else {
- if (!$this->h5pF->getOption('export', TRUE)) {
- $disable |= self::DISABLE_DOWNLOAD;
- }
- if (!$this->h5pF->getOption('embed', TRUE)) {
- $disable |= self::DISABLE_EMBED;
- }
- if (!$this->h5pF->getOption('copyright', TRUE)) {
- $disable |= self::DISABLE_COPYRIGHT;
- }
- if (!$this->h5pF->getOption('icon', TRUE)) {
- $disable |= self::DISABLE_ABOUT;
- }
- }
-
- return $disable;
- }
-
- /**
- * Determine disable state from sources.
+ * Create representation of display options as int
*
* @param array $sources
* @param int $current
* @return int
*/
- public function getDisable(&$sources, $current) {
+ public function getStorableDisplayOptions(&$sources, $current) {
+ // Download - force setting it if always on or always off
+ $download = $this->h5pF->getOption(self::DISPLAY_OPTION_DOWNLOAD, H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ if ($download == H5PDisplayOptionBehaviour::ALWAYS_SHOW ||
+ $download == H5PDisplayOptionBehaviour::NEVER_SHOW) {
+ $sources[self::DISPLAY_OPTION_DOWNLOAD] = ($download == H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ }
+
+ // Embed - force setting it if always on or always off
+ $embed = $this->h5pF->getOption(self::DISPLAY_OPTION_EMBED, H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ if ($embed == H5PDisplayOptionBehaviour::ALWAYS_SHOW ||
+ $embed == H5PDisplayOptionBehaviour::NEVER_SHOW) {
+ $sources[self::DISPLAY_OPTION_EMBED] = ($embed == H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ }
+
foreach (H5PCore::$disable as $bit => $option) {
- if ($this->h5pF->getOption(($bit & H5PCore::DISABLE_DOWNLOAD ? 'export' : $option), TRUE)) {
- if (!isset($sources[$option]) || !$sources[$option]) {
- $current |= $bit; // Disable
- }
- else {
- $current &= ~$bit; // Enable
- }
+ if (!isset($sources[$option]) || !$sources[$option]) {
+ $current |= $bit; // Disable
+ }
+ else {
+ $current &= ~$bit; // Enable
}
}
return $current;
}
+ /**
+ * Determine display options visibility and value on edit
+ *
+ * @param int $disable
+ * @return array
+ */
+ public function getDisplayOptionsForEdit($disable = NULL) {
+ $display_options = [];
+
+ $current_display_options = $disable === NULL ? [] : $this->getDisplayOptionsAsArray($disable);
+
+ if ($this->h5pF->getOption(self::DISPLAY_OPTION_FRAME, TRUE)) {
+ $display_options[self::DISPLAY_OPTION_FRAME] =
+ isset($current_display_options[self::DISPLAY_OPTION_FRAME]) ?
+ $current_display_options[self::DISPLAY_OPTION_FRAME] :
+ TRUE;
+
+ // Download
+ $export = $this->h5pF->getOption(self::DISPLAY_OPTION_DOWNLOAD, H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ if ($export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON ||
+ $export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF) {
+ $display_options[self::DISPLAY_OPTION_DOWNLOAD] =
+ isset($current_display_options[self::DISPLAY_OPTION_DOWNLOAD]) ?
+ $current_display_options[self::DISPLAY_OPTION_DOWNLOAD] :
+ ($export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON);
+ }
+
+ // Embed
+ $embed = $this->h5pF->getOption(self::DISPLAY_OPTION_EMBED, H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ if ($embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON ||
+ $embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF) {
+ $display_options[self::DISPLAY_OPTION_EMBED] =
+ isset($current_display_options[self::DISPLAY_OPTION_EMBED]) ?
+ $current_display_options[self::DISPLAY_OPTION_EMBED] :
+ ($embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON);
+ }
+
+ // Copyright
+ if ($this->h5pF->getOption(self::DISPLAY_OPTION_COPYRIGHT, TRUE)) {
+ $display_options[self::DISPLAY_OPTION_COPYRIGHT] =
+ isset($current_display_options[self::DISPLAY_OPTION_COPYRIGHT]) ?
+ $current_display_options[self::DISPLAY_OPTION_COPYRIGHT] :
+ TRUE;
+ }
+ }
+
+ return $display_options;
+ }
+
+ /**
+ * Helper function used to figure out embed & download behaviour
+ *
+ * @param string $option_name
+ * @param H5PPermission $permission
+ * @param int $id
+ * @param bool &$value
+ */
+ private function setDisplayOptionOverrides($option_name, $permission, $id, &$value) {
+ $behaviour = $this->h5pF->getOption($option_name, H5PDisplayOptionBehaviour::ALWAYS_SHOW);
+ // If never show globally, force hide
+ if ($behaviour == H5PDisplayOptionBehaviour::NEVER_SHOW) {
+ $value = false;
+ }
+ elseif ($behaviour == H5PDisplayOptionBehaviour::ALWAYS_SHOW) {
+ // If always show or permissions say so, force show
+ $value = true;
+ }
+ elseif ($behaviour == H5PDisplayOptionBehaviour::CONTROLLED_BY_PERMISSIONS) {
+ $value = $this->h5pF->hasPermission($permission, $id);
+ }
+ }
+
+ /**
+ * Determine display option visibility when viewing H5P
+ *
+ * @param int $display_options
+ * @param int $id Might be content id or user id.
+ * Depends on what the platform needs to be able to determine permissions.
+ * @return array
+ */
+ public function getDisplayOptionsForView($disable, $id) {
+ $display_options = $this->getDisplayOptionsAsArray($disable);
+
+ if ($this->h5pF->getOption(self::DISPLAY_OPTION_FRAME, TRUE) == FALSE) {
+ $display_options[self::DISPLAY_OPTION_FRAME] = false;
+ }
+ else {
+ $this->setDisplayOptionOverrides(self::DISPLAY_OPTION_DOWNLOAD, H5PPermission::DOWNLOAD_H5P, $id, $display_options[self::DISPLAY_OPTION_DOWNLOAD]);
+ $this->setDisplayOptionOverrides(self::DISPLAY_OPTION_EMBED, H5PPermission::EMBED_H5P, $id, $display_options[self::DISPLAY_OPTION_EMBED]);
+
+ if ($this->h5pF->getOption(self::DISPLAY_OPTION_COPYRIGHT, TRUE) == FALSE) {
+ $display_options[self::DISPLAY_OPTION_COPYRIGHT] = false;
+ }
+ }
+
+ return $display_options;
+ }
+
+ /**
+ * Convert display options as single byte to array
+ *
+ * @param int $disable
+ * @return array
+ */
+ private function getDisplayOptionsAsArray($disable) {
+ return array(
+ self::DISPLAY_OPTION_FRAME => !($disable & H5PCore::DISABLE_FRAME),
+ self::DISPLAY_OPTION_DOWNLOAD => !($disable & H5PCore::DISABLE_DOWNLOAD),
+ self::DISPLAY_OPTION_EMBED => !($disable & H5PCore::DISABLE_EMBED),
+ self::DISPLAY_OPTION_COPYRIGHT => !($disable & H5PCore::DISABLE_COPYRIGHT),
+ self::DISPLAY_OPTION_ABOUT => $this->h5pF->getOption(self::DISPLAY_OPTION_ABOUT, TRUE),
+ );
+ }
+
/**
* Small helper for getting the library's ID.
*
@@ -3134,7 +3265,29 @@ class H5PContentValidator {
return;
}
if (!in_array($value->library, $semantics->options)) {
- $this->h5pF->setErrorMessage($this->h5pF->t('Library used in content is not a valid library according to semantics'));
+ $message = NULL;
+ // Create an understandable error message:
+ $machineName = explode(' ', $value->library)[0];
+ foreach ($semantics->options as $semanticsLibrary) {
+ $semanticsMachineName = explode(' ', $semanticsLibrary)[0];
+ if ($machineName === $semanticsMachineName) {
+ // Using the wrong version of the library in the content
+ $message = $this->h5pF->t('The version of the H5P library %machineName used in this content is not valid. Content contains %contentLibrary, but it should be %semanticsLibrary.', array(
+ '%machineName' => $machineName,
+ '%contentLibrary' => $value->library,
+ '%semanticsLibrary' => $semanticsLibrary
+ ));
+ break;
+ }
+ }
+ // Using a library in content that is not present at all in semantics
+ if ($message === NULL) {
+ $message = $this->h5pF->t('The H5P library %library used in the content is not valid', array(
+ '%library' => $value->library
+ ));
+ }
+
+ $this->h5pF->setErrorMessage($message);
$value = NULL;
return;
}
diff --git a/js/disable.js b/js/disable.js
deleted file mode 100644
index 0bfbb07..0000000
--- a/js/disable.js
+++ /dev/null
@@ -1,19 +0,0 @@
-(function ($) {
- $(document).ready(function () {
- var $inputs = $('.h5p-action-bar-settings input');
- var $frame = $inputs.filter('input[name="frame"], input[name="h5p_frame"]');
- var $others = $inputs.filter(':not(input[name="frame"], input[name="h5p_frame"])');
-
- var toggle = function () {
- if ($frame.is(':checked')) {
- $others.attr('disabled', false);
- }
- else {
- $others.attr('disabled', true);
- }
- };
-
- $frame.change(toggle);
- toggle();
- });
-})(H5P.jQuery);
diff --git a/js/h5p-action-bar.js b/js/h5p-action-bar.js
new file mode 100644
index 0000000..8e34eb7
--- /dev/null
+++ b/js/h5p-action-bar.js
@@ -0,0 +1,89 @@
+H5P.ActionBar = (function ($, EventDispatcher) {
+ "use strict";
+
+ function ActionBar(displayOptions) {
+ EventDispatcher.call(this);
+
+ var self = this;
+
+ var hasActions = false;
+
+ // Create action bar
+ var $actions = H5P.jQuery('
');
+
+ /**
+ * Helper for creating action bar buttons.
+ *
+ * @private
+ * @param {string} type
+ * @param {string} customClass Instead of type class
+ */
+ var addActionButton = function (type, customClass) {
+ var handler = function () {
+ self.trigger(type);
+ };
+ H5P.jQuery('', {
+ 'class': 'h5p-button h5p-' + (customClass ? customClass : type),
+ role: 'button',
+ tabindex: 0,
+ title: 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: $actions
+ });
+
+ hasActions = true;
+ };
+
+ // Register action bar buttons
+ if (displayOptions.export) {
+ // Add export button
+ addActionButton('download', 'export');
+ }
+ if (displayOptions.copyright) {
+ addActionButton('copyrights');
+ }
+ if (displayOptions.embed) {
+ addActionButton('embed');
+ }
+ if (displayOptions.icon) {
+ // Add about H5P button icon
+ H5P.jQuery('').appendTo($actions);
+ hasActions = true;
+ }
+
+ /**
+ * Returns a reference to the dom element
+ *
+ * @method getDOMElement
+ * @return {H5P.jQuery}
+ */
+ self.getDOMElement = function () {
+ return $actions;
+ };
+
+ /**
+ * Does the actionbar contain actions?
+ *
+ * @method hasActions
+ * @return {Boolean}
+ */
+ self.hasActions = function () {
+ return hasActions;
+ }
+ };
+
+ ActionBar.prototype = Object.create(EventDispatcher.prototype);
+ ActionBar.prototype.constructor = ActionBar;
+
+ return ActionBar;
+
+})(H5P.jQuery, H5P.EventDispatcher);
diff --git a/js/h5p-display-options.js b/js/h5p-display-options.js
new file mode 100644
index 0000000..9c8f664
--- /dev/null
+++ b/js/h5p-display-options.js
@@ -0,0 +1,23 @@
+/**
+ * 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();
+ }
+
+ $(document).ready(function () {
+ // Get the checkboxes making other fields being hidden:
+ $('.h5p-visibility-toggler').each(setupHiding);
+ });
+})(H5P.jQuery);
diff --git a/js/h5p.js b/js/h5p.js
index b639868..e4d0138 100644
--- a/js/h5p.js
+++ b/js/h5p.js
@@ -32,7 +32,7 @@ if (document.documentElement.requestFullScreen) {
H5P.fullScreenBrowserPrefix = '';
}
else if (document.documentElement.webkitRequestFullScreen) {
- H5P.safariBrowser = navigator.userAgent.match(/Version\/(\d)/);
+ H5P.safariBrowser = navigator.userAgent.match(/version\/([.\d]+)/i);
H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1]));
// Do not allow fullscreen for safari < 7.
@@ -47,24 +47,6 @@ else if (document.documentElement.msRequestFullscreen) {
H5P.fullScreenBrowserPrefix = 'ms';
}
-/** @const {number} */
-H5P.DISABLE_NONE = 0;
-
-/** @const {number} */
-H5P.DISABLE_FRAME = 1;
-
-/** @const {number} */
-H5P.DISABLE_DOWNLOAD = 2;
-
-/** @const {number} */
-H5P.DISABLE_EMBED = 4;
-
-/** @const {number} */
-H5P.DISABLE_COPYRIGHT = 8;
-
-/** @const {number} */
-H5P.DISABLE_ABOUT = 16;
-
/**
* Keep track of when the H5Ps where started.
*
@@ -85,18 +67,27 @@ H5P.init = function (target) {
}
// Determine if we can use full screen
- if (H5P.canHasFullScreen === undefined) {
+ if (H5P.fullscreenSupported === undefined) {
/**
* Use this variable to check if fullscreen is supported. Fullscreen can be
* restricted when embedding since not all browsers support the native
* fullscreen, and the semi-fullscreen solution doesn't work when embedded.
* @type {boolean}
*/
- H5P.canHasFullScreen = (H5P.isFramed && H5P.externalEmbed !== false) ? ((document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled) ? true : false) : true;
+ H5P.fullscreenSupported = !(H5P.isFramed && H5P.externalEmbed !== false) || !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled);
// We should consider document.msFullscreenEnabled when they get their
// element sizing corrected. Ref. https://connect.microsoft.com/IE/feedback/details/838286/ie-11-incorrectly-reports-dom-element-sizes-in-fullscreen-mode-when-fullscreened-element-is-within-an-iframe
}
+ // Deprecated variable, kept to maintain backwards compatability
+ if (H5P.canHasFullScreen === undefined) {
+ /**
+ * @deprecated since version 1.11
+ * @type {boolean}
+ */
+ H5P.canHasFullScreen = H5P.fullscreenSupported;
+ }
+
// H5Ps added in normal DIV.
var $containers = H5P.jQuery('.h5p-content:not(.h5p-initialized)', target).each(function () {
var $element = H5P.jQuery(this).addClass('h5p-initialized');
@@ -141,87 +132,51 @@ H5P.init = function (target) {
var instance = H5P.newRunnable(library, contentId, $container, true, {standalone: true});
// Check if we should add and display a fullscreen button for this H5P.
- if (contentData.fullScreen == 1 && H5P.canHasFullScreen) {
+ if (contentData.fullScreen == 1 && H5P.fullscreenSupported) {
H5P.jQuery('').prependTo($container).children().click(function () {
H5P.fullScreen($container, instance);
});
}
- // Create action bar
- var $actions = H5P.jQuery('');
-
/**
- * Helper for creating action bar buttons.
- *
- * @private
- * @param {string} type
- * @param {function} handler
- * @param {string} customClass Instead of type class
+ * Create action bar
*/
- var addActionButton = function (type, handler, customClass) {
- H5P.jQuery('', {
- 'class': 'h5p-button h5p-' + (customClass ? customClass : type),
- role: 'button',
- tabindex: 0,
- title: 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: $actions
- });
- };
-
- // Register action bar buttons
- if (!(contentData.disable & H5P.DISABLE_DOWNLOAD)) {
- // Add export button
- addActionButton('download', function () {
- // Use button for download to avoid people linking directly to the .h5p
- window.location.href = contentData.exportUrl;
- }, 'export');
- }
- if (!(contentData.disable & H5P.DISABLE_COPYRIGHT)) {
- var copyright = H5P.getCopyrights(instance, library.params, contentId);
-
- if (copyright) {
- // Add copyright dialog button
- addActionButton('copyrights', function () {
- // Open dialog with copyright information
- var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyright, $container);
- dialog.open();
- });
+ var displayOptions = contentData.displayOptions;
+ var displayFrame = false;
+ if (displayOptions.frame) {
+ // Special handling of copyrights
+ if (displayOptions.copyright) {
+ var copyrights = H5P.getCopyrights(instance, library.params, contentId);
+ if (!copyrights) {
+ displayOptions.copyright = false;
+ }
}
- }
- if (!(contentData.disable & H5P.DISABLE_EMBED)) {
- // Add embed button
- addActionButton('embed', function () {
- // Open dialog with embed information
+
+ // Create action bar
+ var actionBar = new H5P.ActionBar(displayOptions);
+ var $actions = actionBar.getDOMElement();
+
+ actionBar.on('download', function () {
+ window.location.href = contentData.exportUrl;
+ });
+ actionBar.on('copyrights', function () {
+ var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $container);
+ dialog.open();
+ });
+ actionBar.on('embed', function () {
H5P.openEmbedDialog($actions, contentData.embedCode, contentData.resizeCode, {
width: $element.width(),
height: $element.height()
});
});
+
+ if (actionBar.hasActions()) {
+ displayFrame = true;
+ $actions.insertAfter($container);
+ }
}
- if (!(contentData.disable & H5P.DISABLE_ABOUT)) {
- // Add about H5P button icon
- H5P.jQuery('').appendTo($actions);
- }
-
- // Insert action bar if it has any content
- if (!(contentData.disable & H5P.DISABLE_FRAME) && $actions.children().length) {
- $actions.insertAfter($container);
- $element.addClass('h5p-frame');
- }
- else {
- $element.addClass('h5p-no-frame');
- }
+ $element.addClass(displayFrame ? 'h5p-frame' : 'h5p-no-frame');
// Keep track of when we started
H5P.opened[contentId] = new Date();
@@ -497,7 +452,7 @@ H5P.semiFullScreen = function ($element, instance, exitCallback, body) {
* @param {Object} instance
* @param {function} exitCallback Callback function called when user exits fullscreen.
* @param {H5P.jQuery} $body For internal use. Gives the body of the iframe.
- * @param {Boolean} forceSemiFullScreen
+ * @param {Boolean} forceSemiFullScreen
*/
H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFullScreen) {
if (H5P.exitFullScreen !== undefined) {
@@ -1034,6 +989,28 @@ H5P.findCopyrights = function (info, parameters, contentId) {
if (!parameters.hasOwnProperty(field)) {
continue; // Do not check
}
+
+ /*
+ * TODO: Make parameters clean again
+ * Some content types adds jQuery or other objects to parameters
+ * in order to determine override settings for sub-content-types.
+ * For instance Question Set tells Multiple Choice that it should
+ * attach Multi Choice's confirmation dialog to a Question Set
+ * jQuery element, so that the confirmation dialog will not be restricted
+ * to the space confined by Multi Choice.
+ * Ideally this should not be added to parameters, we must make a better
+ * solution. We should likely be adding these to sub-content through
+ * functions/setters instead of passing them down as params.
+ *
+ * This solution is implemented as a hack that will ignore all parameters
+ * inside a "overrideSettings" field, this should suffice for now since
+ * all overridden objects are added to this field, however this is not very
+ * robust solution and will very likely lead to problems in the future.
+ */
+ if (field === 'overrideSettings') {
+ continue;
+ }
+
var value = parameters[field];
if (value instanceof Array) {
@@ -1059,8 +1036,6 @@ H5P.findCopyrights = function (info, parameters, contentId) {
info.addMedia(copyrights);
}
}
- else {
- }
}
};
@@ -1657,7 +1632,8 @@ H5P.shuffleArray = function (array) {
* Reported time consumption/usage
*/
H5P.setFinished = function (contentId, score, maxScore, time) {
- if (typeof score === 'number' && H5PIntegration.postUserStatistics === true) {
+ var validScore = typeof score === 'number' || score instanceof Number;
+ if (validScore && H5PIntegration.postUserStatistics === true) {
/**
* Return unix timestamp for the given JS Date.
*
@@ -2002,6 +1978,20 @@ H5P.createTitle = function (rawTitle, maxLength) {
// Init H5P when page is fully loadded
$(document).ready(function () {
+
+ /**
+ * Indicates if H5P is embedded on an external page using iframe.
+ * @member {boolean} H5P.externalEmbed
+ */
+
+ // Relay events to top window. This must be done before H5P.init
+ // since events may be fired on initialization.
+ if (H5P.isFramed && H5P.externalEmbed === false) {
+ H5P.externalDispatcher.on('*', function (event) {
+ window.parent.H5P.externalDispatcher.trigger.call(this, event);
+ });
+ }
+
/**
* Prevent H5P Core from initializing. Must be overriden before document ready.
* @member {boolean} H5P.preventInit
@@ -2043,18 +2033,6 @@ H5P.createTitle = function (rawTitle, maxLength) {
// pagehide is used on iPad when tabs are switched
H5P.$window.on('pagehide', storeCurrentState);
}
-
- /**
- * Indicates if H5P is embedded on an external page using iframe.
- * @member {boolean} H5P.externalEmbed
- */
-
- // Relay events to top window.
- if (H5P.isFramed && H5P.externalEmbed === false) {
- H5P.externalDispatcher.on('*', function (event) {
- window.parent.H5P.externalDispatcher.trigger.call(this, event);
- });
- }
});
})(H5P.jQuery);
diff --git a/styles/h5p-confirmation-dialog.css b/styles/h5p-confirmation-dialog.css
index 2923b17..4fd45c0 100644
--- a/styles/h5p-confirmation-dialog.css
+++ b/styles/h5p-confirmation-dialog.css
@@ -5,7 +5,7 @@
left: 0;
top: 0;
- background: rgba(255, 255, 255, 0.85);
+ background: rgba(28, 34, 41, 0.9);
opacity: 1;
visibility: visible;
-webkit-transition: opacity 0.1s, linear 0s, visibility 0s linear 0s;
@@ -46,7 +46,7 @@
transform: translate(-50%, 0%);
color: #555;
- box-shadow: 0 0 6px 1px #ddd;
+ box-shadow: 0 0 6px 6px rgba(10,10,10,0.3);
-webkit-transition: transform 0.1s ease-in;
transition: transform 0.1s ease-in;
@@ -61,7 +61,7 @@
.h5p-confirmation-dialog-header {
padding: 1.5em;
background: #fff;
- color: #1a73d9;
+ color: #356593;
}
.h5p-confirmation-dialog-header-text {
@@ -69,8 +69,9 @@
}
.h5p-confirmation-dialog-body {
+ background: #fafbfc;
+ border-top: solid 1px #dde0e9;
padding: 1.25em 1.5em;
- background: #fafafa;
}
.h5p-confirmation-dialog-text {
@@ -90,14 +91,14 @@ button.h5p-confirmation-dialog-exit {
font-size: 2.5em;
top: -0.9em;
right: -1.15em;
- color: #777;
+ color: #fff;
cursor: pointer;
text-decoration: none;
}
button.h5p-confirmation-dialog-exit:focus,
button.h5p-confirmation-dialog-exit:hover {
- color: #555;
+ color: #E4ECF5;
}
.h5p-confirmation-dialog-exit:before {
diff --git a/styles/h5p-core-button.css b/styles/h5p-core-button.css
index 3ba392e..eb4e08d 100644
--- a/styles/h5p-core-button.css
+++ b/styles/h5p-core-button.css
@@ -1,13 +1,15 @@
button.h5p-core-button:visited,
button.h5p-core-button:link,
button.h5p-core-button {
+ font-family: "Open Sans", sans-serif;
+ font-weight: 600;
font-size: 1em;
line-height: 1.2;
padding: 0.5em 1.25em;
border-radius: 2em;
- background: #1a73d9;
- color: #ffffff;
+ background: #488ac9;
+ color: #fff;
cursor: pointer;
border: none;
@@ -22,7 +24,7 @@ button.h5p-core-button {
}
button.h5p-core-button:hover,
button.h5p-core-button:focus {
- background: #1356a3;
+ background: #3b71a5;
color: #fff;
text-decoration: none;
-webkit-transition: initial;
diff --git a/styles/h5p.css b/styles/h5p.css
index b0e7ee2..2e5842e 100644
--- a/styles/h5p.css
+++ b/styles/h5p.css
@@ -3,11 +3,11 @@
/* Custom H5P font to use for icons. */
@font-face {
font-family: 'h5p';
- src: url('../fonts/h5p-core-14.eot?inh2er');
- src: url('../fonts/h5p-core-14.eot?inh2er#iefix') format('embedded-opentype'),
- url('../fonts/h5p-core-14.ttf?inh2er') format('truetype'),
- url('../fonts/h5p-core-14.woff?inh2er') format('woff'),
- url('../fonts/h5p-core-14.svg?inh2er#h5p-core-14') format('svg');
+ src: url('../fonts/h5p-core-16.eot?80e76o');
+ src: url('../fonts/h5p-core-16.eot?80e76o#iefix') format('embedded-opentype'),
+ url('../fonts/h5p-core-16.ttf?80e76o') format('truetype'),
+ url('../fonts/h5p-core-16.woff?80e76o') format('woff'),
+ url('../fonts/h5p-core-16.svg?80e76o#h5p-core-15') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -235,6 +235,7 @@ div.h5p-fullscreen {
}
.h5p-actions > li {
margin: 0;
+ list-style: none;
}
.h5p-popup-dialog {
position: absolute;