Merge branch 'without-pal'

Conflicts:
	h5p.classes.php
	js/h5p-library-list.js
namespaces
Frode Petterson 2014-10-23 15:18:03 +02:00
commit 2737f3c721
10 changed files with 366 additions and 360 deletions

View File

@ -30,7 +30,7 @@ class H5PDevelopment {
$this->findLibraries($filesPath . '/development'); $this->findLibraries($filesPath . '/development');
} }
} }
/** /**
* Get contents of file. * Get contents of file.
* *
@ -41,15 +41,15 @@ class H5PDevelopment {
if (file_exists($file) === FALSE) { if (file_exists($file) === FALSE) {
return NULL; return NULL;
} }
$contents = file_get_contents($file); $contents = file_get_contents($file);
if ($contents === FALSE) { if ($contents === FALSE) {
return NULL; return NULL;
} }
return $contents; return $contents;
} }
/** /**
* Scans development directory and find all libraries. * Scans development directory and find all libraries.
* *
@ -57,39 +57,39 @@ class H5PDevelopment {
*/ */
private function findLibraries($path) { private function findLibraries($path) {
$this->libraries = array(); $this->libraries = array();
if (is_dir($path) === FALSE) { if (is_dir($path) === FALSE) {
return; return;
} }
$contents = scandir($path); $contents = scandir($path);
for ($i = 0, $s = count($contents); $i < $s; $i++) { for ($i = 0, $s = count($contents); $i < $s; $i++) {
if ($contents[$i]{0} === '.') { if ($contents[$i]{0} === '.') {
continue; // Skip hidden stuff. continue; // Skip hidden stuff.
} }
$libraryPath = $path . '/' . $contents[$i]; $libraryPath = $path . '/' . $contents[$i];
$libraryJSON = $this->getFileContents($libraryPath . '/library.json'); $libraryJSON = $this->getFileContents($libraryPath . '/library.json');
if ($libraryJSON === NULL) { if ($libraryJSON === NULL) {
continue; // No JSON file, skip. continue; // No JSON file, skip.
} }
$library = json_decode($libraryJSON, TRUE); $library = json_decode($libraryJSON, TRUE);
if ($library === FALSE) { if ($library === FALSE) {
continue; // Invalid JSON. continue; // Invalid JSON.
} }
// TODO: Validate props? Not really needed, is it? this is a dev site. // TODO: Validate props? Not really needed, is it? this is a dev site.
// Save/update library. // Save/update library.
$library['libraryId'] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']); $library['libraryId'] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']);
$this->h5pF->saveLibraryData($library, $library['libraryId'] === FALSE); $this->h5pF->saveLibraryData($library, $library['libraryId'] === FALSE);
$library['path'] = $libraryPath; $library['path'] = $libraryPath;
$this->libraries[H5PDevelopment::libraryToString($library['machineName'], $library['majorVersion'], $library['minorVersion'])] = $library; $this->libraries[H5PDevelopment::libraryToString($library['machineName'], $library['majorVersion'], $library['minorVersion'])] = $library;
} }
// TODO: Should we remove libraries without files? Not really needed, but must be cleaned up some time, right? // TODO: Should we remove libraries without files? Not really needed, but must be cleaned up some time, right?
// Go trough libraries and insert dependencies. Missing deps. will just be ignored and not available. (I guess?!) // Go trough libraries and insert dependencies. Missing deps. will just be ignored and not available. (I guess?!)
@ -106,17 +106,17 @@ class H5PDevelopment {
} }
// TODO: Deps must be inserted into h5p_nodes_libraries as well... ? But only if they are used?! // TODO: Deps must be inserted into h5p_nodes_libraries as well... ? But only if they are used?!
} }
/** /**
* @return array Libraris in development folder. * @return array Libraris in development folder.
*/ */
public function getLibraries() { public function getLibraries() {
return $this->libraries; return $this->libraries;
} }
/** /**
* Get library * Get library
* *
* @param string $name of the library. * @param string $name of the library.
* @param int $majorVersion of the library. * @param int $majorVersion of the library.
* @param int $minorVersion of the library. * @param int $minorVersion of the library.
@ -126,10 +126,10 @@ class H5PDevelopment {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
return isset($this->libraries[$library]) === TRUE ? $this->libraries[$library] : NULL; return isset($this->libraries[$library]) === TRUE ? $this->libraries[$library] : NULL;
} }
/** /**
* Get semantics for the given library. * Get semantics for the given library.
* *
* @param string $name of the library. * @param string $name of the library.
* @param int $majorVersion of the library. * @param int $majorVersion of the library.
* @param int $minorVersion of the library. * @param int $minorVersion of the library.
@ -137,32 +137,32 @@ class H5PDevelopment {
*/ */
public function getSemantics($name, $majorVersion, $minorVersion) { public function getSemantics($name, $majorVersion, $minorVersion) {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
if (isset($this->libraries[$library]) === FALSE) { if (isset($this->libraries[$library]) === FALSE) {
return NULL; return NULL;
} }
return $this->getFileContents($this->libraries[$library]['path'] . '/semantics.json'); return $this->getFileContents($this->libraries[$library]['path'] . '/semantics.json');
} }
/** /**
* Get translations for the given library. * Get translations for the given library.
* *
* @param string $name of the library. * @param string $name of the library.
* @param int $majorVersion of the library. * @param int $majorVersion of the library.
* @param int $minorVersion of the library. * @param int $minorVersion of the library.
* @return string Translation * @return string Translation
*/ */
public function getLanguage($name, $majorVersion, $minorVersion) { public function getLanguage($name, $majorVersion, $minorVersion, $language) {
$library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion);
if (isset($this->libraries[$library]) === FALSE) { if (isset($this->libraries[$library]) === FALSE) {
return NULL; return NULL;
} }
return $this->getFileContents($this->libraries[$library]['path'] . '/language/' . $this->language . '.json'); return $this->getFileContents($this->libraries[$library]['path'] . '/language/' . $language . '.json');
} }
/** /**
* Writes library as string on the form "name majorVersion.minorVersion" * Writes library as string on the form "name majorVersion.minorVersion"
* *
@ -175,4 +175,3 @@ class H5PDevelopment {
return $name . ' ' . $majorVersion . '.' . $minorVersion; return $name . ' ' . $majorVersion . '.' . $minorVersion;
} }
} }

View File

@ -394,10 +394,10 @@ interface H5PFrameworkInterface {
/** /**
* Delete a library from database and file system * Delete a library from database and file system
* *
* @param int $libraryId * @param stdClass $library
* Library identifier * Library object with id, name, major version and minor version.
*/ */
public function deleteLibrary($libraryId); public function deleteLibrary($library);
/** /**
* Load content. * Load content.
@ -444,57 +444,58 @@ interface H5PFrameworkInterface {
public function loadContentDependencies($id, $type = NULL); public function loadContentDependencies($id, $type = NULL);
/** /**
* Get data from cache. * Get stored setting.
* *
* @param string $group * @param string $name
* Identifier for the cache group * Identifier for the setting
* @param string $key * @param string $default
* Unique identifier within the group * Optional default value if settings is not set
* @return mixed * @return mixed
* Whatever has been stored in the cache. NULL if the entry doesn't exist * Whatever has been stored as the setting
*/ */
public function cacheGet($group, $key); public function getOption($name, $default = NULL);
/** /**
* Store data in cache. * Stores the given setting.
* For example when did we last check h5p.org for updates to our libraries.
* *
* @param string $group * @param string $name
* The cache group where the data should be stored * Identifier for the setting
* @param string $key * @param mixed $value Data
* A unique key identifying where the data should be stored * Whatever we want to store as the setting
* @param mixed $data
* The data you want to cache
*/ */
public function cacheSet($group, $key, $data); public function setOption($name, $value);
/** /**
* Delete data from cache. * This will set the filtered parameters for the given content.
* *
* @param string $group * @param int $content_id
* Identifier for the cache group * @param string $parameters filtered
* @param string $key
* Unique identifier within the group
*/ */
public function cacheDel($group, $key = NULL); public function setFilteredParameters($content_id, $parameters = '');
/** /**
* Will invalidate the cache for the content that uses the specified library. * Will clear filtered params for all the content that uses the specified
* This means that the content dependencies has to be rebuilt, and the parameters refiltered. * library. This means that the content dependencies will have to be rebuilt,
* and the parameters refiltered.
* *
* @param int $libraryId * @param int $library_id
*/ */
public function invalidateContentCache($libraryId); public function clearFilteredParameters($library_id);
/** /**
* Get number of content that hasn't been cached * Get number of contents that has to get their content dependencies rebuilt
* and parameters refiltered.
*
* @return int
*/ */
public function getNotCached(); public function getNumNotFiltered();
/** /**
* Get number of contents using library as main library. * Get number of contents using library as main library.
* *
* @param int $libraryId * @param int $libraryId
* Identifier for a library * @return int
*/ */
public function getNumContent($libraryId); public function getNumContent($libraryId);
} }
@ -1265,7 +1266,7 @@ class H5PStorage {
} }
// Make sure libraries dependencies, parameter filtering and export files gets regenerated for all content who uses this library. // Make sure libraries dependencies, parameter filtering and export files gets regenerated for all content who uses this library.
$this->h5pF->invalidateContentCache($library['libraryId']); $this->h5pF->clearFilteredParameters($library['libraryId']);
$upgradedLibsCount++; $upgradedLibsCount++;
} }
@ -1567,11 +1568,6 @@ class H5PCore {
$content['id'] = $this->h5pF->insertContent($content, $contentMainId); $content['id'] = $this->h5pF->insertContent($content, $contentMainId);
} }
if (!isset($content['filtered'])) {
// TODO: Add filtered to all impl. and remove
$this->h5pF->cacheDel('parameters', $content['id']);
}
return $content['id']; return $content['id'];
} }
@ -1619,16 +1615,8 @@ class H5PCore {
* @return Object NULL on failure. * @return Object NULL on failure.
*/ */
public function filterParameters($content) { public function filterParameters($content) {
if (isset($content['filtered'])) { if (isset($content['filtered']) && $content['filtered'] !== '') {
$params = ($content['filtered'] === '' ? NULL : $content['filtered']); return $content['filtered'];
}
else {
// TODO: Add filtered to all impl. and remove
$params = $this->h5pF->cacheGet('parameters', $content['id']);
}
if ($params !== NULL) {
return $params;
} }
// Validate and filter against main library semantics. // Validate and filter against main library semantics.
@ -1655,7 +1643,7 @@ class H5PCore {
} }
// Cache. // Cache.
$this->h5pF->cacheSet('parameters', $content['id'], $params); $this->h5pF->setFilteredParameters($content['id'], $params);
return $params; return $params;
} }
@ -2598,7 +2586,7 @@ class H5PContentValidator {
if (!isset($this->libraries[$value->library])) { if (!isset($this->libraries[$value->library])) {
$libspec = H5PCore::libraryFromString($value->library); $libspec = H5PCore::libraryFromString($value->library);
$library = $this->h5pC->loadLibrary($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']); $library = $this->h5pC->loadLibrary($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
$library['semantics'] = json_decode($library['semantics']); $library['semantics'] = $this->h5pC->loadLibrarySemantics($libspec['machineName'], $libspec['majorVersion'], $libspec['minorVersion']);
$this->libraries[$value->library] = $library; $this->libraries[$value->library] = $library;
// Find all dependencies for this library // Find all dependencies for this library

View File

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

View File

@ -1,3 +1,5 @@
/*jshint multistr: true */
/** /**
* *
*/ */
@ -5,7 +7,7 @@ var H5P = H5P || (function () {
var head = document.getElementsByTagName('head')[0]; var head = document.getElementsByTagName('head')[0];
var contentId = 0; var contentId = 0;
var contents = {}; var contents = {};
/** /**
* Wraps multiple content between a prefix and a suffix. * Wraps multiple content between a prefix and a suffix.
*/ */
@ -16,25 +18,25 @@ var H5P = H5P || (function () {
} }
return result; return result;
}; };
/** /**
* *
*/ */
var loadContent = function (id, script) { var loadContent = function (id, script) {
var url = script.getAttribute('data-h5p'); var url = script.getAttribute('data-h5p');
var data, callback = 'H5P' + id; var data, callback = 'H5P' + id;
// Prevent duplicate loading. // Prevent duplicate loading.
script.removeAttribute('data-h5p'); script.removeAttribute('data-h5p');
// Callback for when content data is loaded. // Callback for when content data is loaded.
window[callback] = function (content) { window[callback] = function (content) {
contents[id] = content; contents[id] = content;
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
var parent = script.parentNode; var parent = script.parentNode;
parent.insertBefore(iframe, script); parent.insertBefore(iframe, script);
iframe.id = 'h5p-iframe-' + id; iframe.id = 'h5p-iframe-' + id;
iframe.style.display = 'block'; iframe.style.display = 'block';
iframe.style.width = '100%'; iframe.style.width = '100%';
@ -59,19 +61,19 @@ var H5P = H5P || (function () {
</body></html>'); </body></html>');
iframe.contentDocument.close(); iframe.contentDocument.close();
iframe.contentDocument.documentElement.style.overflow = 'hidden'; iframe.contentDocument.documentElement.style.overflow = 'hidden';
// Clean up // Clean up
parent.removeChild(script); parent.removeChild(script);
head.removeChild(data); head.removeChild(data);
delete window[callback]; delete window[callback];
}; };
// Create data script // Create data script
data = document.createElement('script'); data = document.createElement('script');
data.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback; data.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback;
head.appendChild(data); head.appendChild(data);
}; };
/** /**
* Go throught all script tags with the data-h5p attribute and load content. * Go throught all script tags with the data-h5p attribute and load content.
*/ */
@ -89,7 +91,7 @@ var H5P = H5P || (function () {
contentId++; contentId++;
} }
}; };
/** /**
* Return integration object * Return integration object
*/ */
@ -124,14 +126,14 @@ var H5P = H5P || (function () {
} }
}; };
}; };
// Detect if we support fullscreen, and what prefix to use. // Detect if we support fullscreen, and what prefix to use.
var fullScreenBrowserPrefix, safariBrowser; var fullScreenBrowserPrefix, safariBrowser;
if (document.documentElement.requestFullScreen) { if (document.documentElement.requestFullScreen) {
fullScreenBrowserPrefix = ''; fullScreenBrowserPrefix = '';
} }
else if (document.documentElement.webkitRequestFullScreen else if (document.documentElement.webkitRequestFullScreen &&
&& navigator.userAgent.indexOf('Android') === -1 // Skip Android navigator.userAgent.indexOf('Android') === -1 // Skip Android
) { ) {
safariBrowser = navigator.userAgent.match(/Version\/(\d)/); safariBrowser = navigator.userAgent.match(/Version\/(\d)/);
safariBrowser = (safariBrowser === null ? 0 : parseInt(safariBrowser[1])); safariBrowser = (safariBrowser === null ? 0 : parseInt(safariBrowser[1]));
@ -155,10 +157,10 @@ var H5P = H5P || (function () {
var iframe = document.getElementById('h5p-iframe-' + $element.parent().data('content-id')); var iframe = document.getElementById('h5p-iframe-' + $element.parent().data('content-id'));
var $classes = $element.add(body); var $classes = $element.add(body);
var $body = $classes.eq(1); var $body = $classes.eq(1);
/** /**
* Prepare for resize by setting the correct styles. * Prepare for resize by setting the correct styles.
* *
* @param {String} classes CSS * @param {String} classes CSS
*/ */
var before = function (classes) { var before = function (classes) {
@ -179,7 +181,7 @@ var H5P = H5P || (function () {
/** /**
* Gets called when fullscreen mode has been exited. * Gets called when fullscreen mode has been exited.
* Resizes and sets focus on content. * Resizes and sets focus on content.
* *
* @param {String} classes CSS * @param {String} classes CSS
*/ */
var done = function (classes) { var done = function (classes) {
@ -201,10 +203,10 @@ var H5P = H5P || (function () {
before('h5p-semi-fullscreen'); before('h5p-semi-fullscreen');
iframe.style.position = 'fixed'; iframe.style.position = 'fixed';
var $disable = $element.prepend('<a href="#" class="h5p-disable-fullscreen" title="Disable fullscreen"></a>').children(':first'); var $disable = $element.prepend('<a href="#" class="h5p-disable-fullscreen" title="Disable fullscreen"></a>').children(':first');
var keyup, disableSemiFullscreen = function () { var keyup, disableSemiFullscreen = function () {
$disable.remove(); $disable.remove();
$body.unbind('keyup', keyup); $body.unbind('keyup', keyup);
iframe.style.position = 'static'; iframe.style.position = 'static';
done('h5p-semi-fullscreen'); done('h5p-semi-fullscreen');
@ -247,7 +249,7 @@ var H5P = H5P || (function () {
} }
} }
}; };
return H5P; return H5P;
})(); })();

View File

@ -9,47 +9,47 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.init = function () { H5PLibraryDetails.init = function () {
H5PLibraryDetails.$adminContainer = H5PIntegration.getAdminContainer(); H5PLibraryDetails.$adminContainer = H5PIntegration.getAdminContainer();
H5PLibraryDetails.library = H5PIntegration.getLibraryInfo(); H5PLibraryDetails.library = H5PIntegration.getLibraryInfo();
// currentContent holds the current list if data (relevant for filtering) // currentContent holds the current list if data (relevant for filtering)
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content; H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
// The current page index (for pager) // The current page index (for pager)
H5PLibraryDetails.currentPage = 0; H5PLibraryDetails.currentPage = 0;
// The current filter // The current filter
H5PLibraryDetails.currentFilter = ''; H5PLibraryDetails.currentFilter = '';
// We cache the filtered results, so we don't have to do unneccessary searches // We cache the filtered results, so we don't have to do unneccessary searches
H5PLibraryDetails.filterCache = []; H5PLibraryDetails.filterCache = [];
// Append library info // Append library info
H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createLibraryInfo()); H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createLibraryInfo());
// Append node list // Append node list
H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createContentElement()); H5PLibraryDetails.$adminContainer.append(H5PLibraryDetails.createContentElement());
}; };
/** /**
* Create the library details view * Create the library details view
*/ */
H5PLibraryDetails.createLibraryInfo = function () { H5PLibraryDetails.createLibraryInfo = function () {
var $libraryInfo = $('<div class="h5p-library-info"></div>'); var $libraryInfo = $('<div class="h5p-library-info"></div>');
$.each(H5PLibraryDetails.library.info, function (title, value) { $.each(H5PLibraryDetails.library.info, function (title, value) {
$libraryInfo.append(H5PUtils.createLabeledField(title, value)); $libraryInfo.append(H5PUtils.createLabeledField(title, value));
}); });
return $libraryInfo; return $libraryInfo;
}; };
/** /**
* Create the content list with searching and paging * Create the content list with searching and paging
*/ */
H5PLibraryDetails.createContentElement = function () { H5PLibraryDetails.createContentElement = function () {
if (H5PLibraryDetails.library.notCached !== undefined) { if (H5PLibraryDetails.library.notCached !== undefined) {
return H5PUtils.getRebuildCache(H5PLibraryDetails.library.notCached); return H5PUtils.getRebuildCache(H5PLibraryDetails.library.notCached);
} }
if (H5PLibraryDetails.currentContent === undefined) { if (H5PLibraryDetails.currentContent === undefined) {
H5PLibraryDetails.$content = $('<div class="h5p-content empty">' + H5PLibraryDetails.library.translations.noContent + '</div>'); H5PLibraryDetails.$content = $('<div class="h5p-content empty">' + H5PLibraryDetails.library.translations.noContent + '</div>');
} }
@ -62,7 +62,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
return H5PLibraryDetails.$content; return H5PLibraryDetails.$content;
} }
}; };
/** /**
* Creates the content list * Creates the content list
*/ */
@ -71,12 +71,12 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
if(H5PLibraryDetails.$contentTable) { if(H5PLibraryDetails.$contentTable) {
H5PLibraryDetails.$contentTable.remove(); H5PLibraryDetails.$contentTable.remove();
} }
H5PLibraryDetails.$contentTable = H5PUtils.createTable(); H5PLibraryDetails.$contentTable = H5PUtils.createTable();
var i = (H5PLibraryDetails.currentPage*H5PLibraryDetails.PAGER_SIZE); var i = (H5PLibraryDetails.currentPage*H5PLibraryDetails.PAGER_SIZE);
var lastIndex = (i+H5PLibraryDetails.PAGER_SIZE); var lastIndex = (i+H5PLibraryDetails.PAGER_SIZE);
if(lastIndex > H5PLibraryDetails.currentContent.length) { if(lastIndex > H5PLibraryDetails.currentContent.length) {
lastIndex = H5PLibraryDetails.currentContent.length; lastIndex = H5PLibraryDetails.currentContent.length;
} }
@ -84,48 +84,48 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
var content = H5PLibraryDetails.currentContent[i]; var content = H5PLibraryDetails.currentContent[i];
H5PLibraryDetails.$contentTable.append(H5PUtils.createTableRow(['<a href="' + content.url + '">' + content.title + '</a>'])); H5PLibraryDetails.$contentTable.append(H5PUtils.createTableRow(['<a href="' + content.url + '">' + content.title + '</a>']));
} }
// Appends it to the browser DOM // Appends it to the browser DOM
H5PLibraryDetails.$contentTable.insertAfter(H5PLibraryDetails.$search); H5PLibraryDetails.$contentTable.insertAfter(H5PLibraryDetails.$search);
}; };
/** /**
* Creates the pager element on the bottom of the list * Creates the pager element on the bottom of the list
*/ */
H5PLibraryDetails.createPagerElement = function () { H5PLibraryDetails.createPagerElement = function () {
// Only create pager if needed: // Only create pager if needed:
if(H5PLibraryDetails.currentContent.length > H5PLibraryDetails.PAGER_SIZE) { if(H5PLibraryDetails.currentContent.length > H5PLibraryDetails.PAGER_SIZE) {
H5PLibraryDetails.$previous = $('<button type="button" class="previous h5p-admin"><</button>'); H5PLibraryDetails.$previous = $('<button type="button" class="previous h5p-admin"><</button>');
H5PLibraryDetails.$next = $('<button type="button" class="next h5p-admin">></button>'); H5PLibraryDetails.$next = $('<button type="button" class="next h5p-admin">></button>');
H5PLibraryDetails.$previous.on('click', function () { H5PLibraryDetails.$previous.on('click', function () {
if(H5PLibraryDetails.$previous.hasClass('disabled')) { if(H5PLibraryDetails.$previous.hasClass('disabled')) {
return; return;
} }
H5PLibraryDetails.currentPage--; H5PLibraryDetails.currentPage--;
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable(); H5PLibraryDetails.createContentTable();
}); });
H5PLibraryDetails.$next.on('click', function () { H5PLibraryDetails.$next.on('click', function () {
if(H5PLibraryDetails.$next.hasClass('disabled')) { if(H5PLibraryDetails.$next.hasClass('disabled')) {
return; return;
} }
H5PLibraryDetails.currentPage++; H5PLibraryDetails.currentPage++;
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable(); H5PLibraryDetails.createContentTable();
}); });
// This is the Page x of y widget: // This is the Page x of y widget:
H5PLibraryDetails.$pagerInfo = $('<span class="pager-info"></span>'); H5PLibraryDetails.$pagerInfo = $('<span class="pager-info"></span>');
H5PLibraryDetails.$pager = $('<div class="h5p-content-pager"></div>').append(H5PLibraryDetails.$previous, H5PLibraryDetails.$pagerInfo, H5PLibraryDetails.$next); H5PLibraryDetails.$pager = $('<div class="h5p-content-pager"></div>').append(H5PLibraryDetails.$previous, H5PLibraryDetails.$pagerInfo, H5PLibraryDetails.$next);
H5PLibraryDetails.$content.append(H5PLibraryDetails.$pager); H5PLibraryDetails.$content.append(H5PLibraryDetails.$pager);
H5PLibraryDetails.$pagerInfo.on('click', function () { H5PLibraryDetails.$pagerInfo.on('click', function () {
var width = H5PLibraryDetails.$pagerInfo.innerWidth(); var width = H5PLibraryDetails.$pagerInfo.innerWidth();
H5PLibraryDetails.$pagerInfo.hide(); H5PLibraryDetails.$pagerInfo.hide();
@ -134,24 +134,24 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
var pageNumerUpdated = function() { var pageNumerUpdated = function() {
var newPageNum = $gotoInput.val()-1; var newPageNum = $gotoInput.val()-1;
var intRegex = /^\d+$/; var intRegex = /^\d+$/;
$goto.remove(); $goto.remove();
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'}); H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
// Check if input value is valid, and that it has actually changed // Check if input value is valid, and that it has actually changed
if(!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) { if(!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) {
return; return;
} }
H5PLibraryDetails.currentPage = newPageNum; H5PLibraryDetails.currentPage = newPageNum;
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
H5PLibraryDetails.createContentTable(); H5PLibraryDetails.createContentTable();
}; };
// We create an input box where the user may type in the page number // We create an input box where the user may type in the page number
// he wants to be displayed. // he wants to be displayed.
// Reson for doing this is when user has ten-thousands of elements in list, // 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 // this is the easiest way of getting to a specified page
var $gotoInput = $('<input/>', { var $gotoInput = $('<input/>', {
type: 'number', type: 'number',
min : 1, min : 1,
@ -166,30 +166,30 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
} }
} }
}).css({width: width}); }).css({width: width});
var $goto = $('<span/>', { var $goto = $('<span/>', {
'class': 'h5p-pager-goto' 'class': 'h5p-pager-goto'
}).css({width: width}).append($gotoInput).insertAfter(H5PLibraryDetails.$pagerInfo); }).css({width: width}).append($gotoInput).insertAfter(H5PLibraryDetails.$pagerInfo);
$gotoInput.focus(); $gotoInput.focus();
}); });
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
} }
}; };
/** /**
* Calculates number of pages * Calculates number of pages
*/ */
H5PLibraryDetails.getNumPages = function () { H5PLibraryDetails.getNumPages = function () {
return Math.ceil(H5PLibraryDetails.currentContent.length / H5PLibraryDetails.PAGER_SIZE); return Math.ceil(H5PLibraryDetails.currentContent.length / H5PLibraryDetails.PAGER_SIZE);
}; };
/** /**
* Update the pager text, and enables/disables the next and previous buttons as needed * Update the pager text, and enables/disables the next and previous buttons as needed
*/ */
H5PLibraryDetails.updatePager = function () { H5PLibraryDetails.updatePager = function () {
H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'}); H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'});
if(H5PLibraryDetails.getNumPages() > 0) { if(H5PLibraryDetails.getNumPages() > 0) {
var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, { var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, {
'$x': (H5PLibraryDetails.currentPage+1), '$x': (H5PLibraryDetails.currentPage+1),
@ -200,26 +200,26 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
else { else {
H5PLibraryDetails.$pagerInfo.html(''); H5PLibraryDetails.$pagerInfo.html('');
} }
H5PLibraryDetails.$previous.toggleClass('disabled', H5PLibraryDetails.currentPage <= 0); H5PLibraryDetails.$previous.toggleClass('disabled', H5PLibraryDetails.currentPage <= 0);
H5PLibraryDetails.$next.toggleClass('disabled', H5PLibraryDetails.currentContent.length < (H5PLibraryDetails.currentPage+1)*H5PLibraryDetails.PAGER_SIZE); H5PLibraryDetails.$next.toggleClass('disabled', H5PLibraryDetails.currentContent.length < (H5PLibraryDetails.currentPage+1)*H5PLibraryDetails.PAGER_SIZE);
}; };
/** /**
* Creates the search element * Creates the search element
*/ */
H5PLibraryDetails.createSearchElement = function () { H5PLibraryDetails.createSearchElement = function () {
H5PLibraryDetails.$search = $('<div class="h5p-content-search"><input placeholder="' + H5PLibraryDetails.library.translations.filterPlaceholder + '" type="search"></div>'); H5PLibraryDetails.$search = $('<div class="h5p-content-search"><input placeholder="' + H5PLibraryDetails.library.translations.filterPlaceholder + '" type="search"></div>');
var performSeach = function () { var performSeach = function () {
var searchString = $('.h5p-content-search > input').val(); var searchString = $('.h5p-content-search > input').val();
// If search string same as previous, just do nothing // If search string same as previous, just do nothing
if(H5PLibraryDetails.currentFilter === searchString) { if(H5PLibraryDetails.currentFilter === searchString) {
return; return;
} }
if (searchString.trim().length === 0) { if (searchString.trim().length === 0) {
// If empty search, use the complete list // If empty search, use the complete list
H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content; H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content;
@ -230,7 +230,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
} }
else { else {
var listToFilter = H5PLibraryDetails.library.content; var listToFilter = H5PLibraryDetails.library.content;
// Check if we can filter the already filtered results (for performance) // Check if we can filter the already filtered results (for performance)
if(searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) { if(searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) {
listToFilter = H5PLibraryDetails.currentContent; listToFilter = H5PLibraryDetails.currentContent;
@ -239,47 +239,47 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
return content.title && content.title.match(new RegExp(searchString, 'i')); return content.title && content.title.match(new RegExp(searchString, 'i'));
}); });
} }
H5PLibraryDetails.currentFilter = searchString; H5PLibraryDetails.currentFilter = searchString;
// Cache the current result // Cache the current result
H5PLibraryDetails.filterCache[searchString] = H5PLibraryDetails.currentContent; H5PLibraryDetails.filterCache[searchString] = H5PLibraryDetails.currentContent;
H5PLibraryDetails.currentPage = 0; H5PLibraryDetails.currentPage = 0;
H5PLibraryDetails.createContentTable(); H5PLibraryDetails.createContentTable();
// Display search results: // Display search results:
if (H5PLibraryDetails.$searchResults) { if (H5PLibraryDetails.$searchResults) {
H5PLibraryDetails.$searchResults.remove(); H5PLibraryDetails.$searchResults.remove();
} }
if (searchString.trim().length > 0) { if (searchString.trim().length > 0) {
H5PLibraryDetails.$searchResults = $('<span class="h5p-admin-search-results">' + H5PLibraryDetails.currentContent.length + ' hits on ' + H5PLibraryDetails.currentFilter + '</span>'); H5PLibraryDetails.$searchResults = $('<span class="h5p-admin-search-results">' + H5PLibraryDetails.currentContent.length + ' hits on ' + H5PLibraryDetails.currentFilter + '</span>');
H5PLibraryDetails.$search.append(H5PLibraryDetails.$searchResults); H5PLibraryDetails.$search.append(H5PLibraryDetails.$searchResults);
} }
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
}; };
var inputTimer = undefined; var inputTimer;
$('input', H5PLibraryDetails.$search).on('change keypress paste input', function () { $('input', H5PLibraryDetails.$search).on('change keypress paste input', function () {
// Here we start the filtering // Here we start the filtering
// We wait at least 500 ms after last input to perform search // We wait at least 500 ms after last input to perform search
if(inputTimer) { if(inputTimer) {
clearTimeout(inputTimer); clearTimeout(inputTimer);
} }
inputTimer = setTimeout( function () { inputTimer = setTimeout( function () {
performSeach(); performSeach();
}, 500); }, 500);
}); });
H5PLibraryDetails.$content.append(H5PLibraryDetails.$search); H5PLibraryDetails.$content.append(H5PLibraryDetails.$search);
}; };
/** /**
* Creates the page size selector * Creates the page size selector
*/ */
H5PLibraryDetails.createPageSizeSelector = function () { 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>'); 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: // Listen to clicks on the page size selector:
$('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).on('click', function () { $('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).on('click', function () {
H5PLibraryDetails.PAGER_SIZE = $(this).data('page-size'); H5PLibraryDetails.PAGER_SIZE = $(this).data('page-size');
$('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).removeClass('selected'); $('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).removeClass('selected');
@ -289,7 +289,7 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.updatePager(); H5PLibraryDetails.updatePager();
}); });
}; };
// Initialize me: // Initialize me:
$(document).ready(function () { $(document).ready(function () {
if (!H5PLibraryDetails.initialized) { if (!H5PLibraryDetails.initialized) {
@ -297,5 +297,5 @@ var H5PLibraryDetails= H5PLibraryDetails || {};
H5PLibraryDetails.init(); H5PLibraryDetails.init();
} }
}); });
})(H5P.jQuery); })(H5P.jQuery);

View File

@ -1,4 +1,5 @@
var H5PLibraryList= H5PLibraryList || {}; /*jshint multistr: true */
var H5PLibraryList = H5PLibraryList || {};
(function ($) { (function ($) {
@ -7,19 +8,19 @@ var H5PLibraryList= H5PLibraryList || {};
*/ */
H5PLibraryList.init = function () { H5PLibraryList.init = function () {
var $adminContainer = H5PIntegration.getAdminContainer(); var $adminContainer = H5PIntegration.getAdminContainer();
var libraryList = H5PIntegration.getLibraryList(); var libraryList = H5PIntegration.getLibraryList();
if (libraryList.notCached) { if (libraryList.notCached) {
$adminContainer.append(H5PUtils.getRebuildCache(libraryList.notCached)); $adminContainer.append(H5PUtils.getRebuildCache(libraryList.notCached));
} }
// Create library list // Create library list
$adminContainer.append(H5PLibraryList.createLibraryList(H5PIntegration.getLibraryList())); $adminContainer.append(H5PLibraryList.createLibraryList(H5PIntegration.getLibraryList()));
}; };
/** /**
* Create the library list * Create the library list
* *
* @param {object} libraries List of libraries and headers * @param {object} libraries List of libraries and headers
*/ */
H5PLibraryList.createLibraryList = function (libraries) { H5PLibraryList.createLibraryList = function (libraries) {
@ -27,11 +28,11 @@ var H5PLibraryList= H5PLibraryList || {};
if(libraries.listData === undefined || libraries.listData.length === 0) { if(libraries.listData === undefined || libraries.listData.length === 0) {
return $('<div>' + t.NA + '</div>'); return $('<div>' + t.NA + '</div>');
} }
// Create table // Create table
var $table = H5PUtils.createTable(libraries.listHeaders); var $table = H5PUtils.createTable(libraries.listHeaders);
$table.addClass('libraries'); $table.addClass('libraries');
// Add libraries // Add libraries
$.each (libraries.listData, function (index, library) { $.each (libraries.listData, function (index, library) {
var $libraryRow = H5PUtils.createTableRow([ var $libraryRow = H5PUtils.createTableRow([
@ -55,7 +56,7 @@ var H5PLibraryList= H5PLibraryList || {};
<button class="h5p-admin-delete-library"></button>\ <button class="h5p-admin-delete-library"></button>\
</div>' </div>'
]); ]);
H5PLibraryList.addRestricted($('.h5p-admin-restricted', $libraryRow), library.restrictedUrl, library.restricted); H5PLibraryList.addRestricted($('.h5p-admin-restricted', $libraryRow), library.restrictedUrl, library.restricted);
var hasContent = !(library.numContent === '' || library.numContent === 0); var hasContent = !(library.numContent === '' || library.numContent === 0);
@ -70,12 +71,12 @@ var H5PLibraryList= H5PLibraryList || {};
window.location.href = library.upgradeUrl; window.location.href = library.upgradeUrl;
}); });
} }
// Open details view when clicked // Open details view when clicked
$('.h5p-admin-view-library', $libraryRow).on('click', function () { $('.h5p-admin-view-library', $libraryRow).on('click', function () {
window.location.href = library.detailsUrl; window.location.href = library.detailsUrl;
}); });
var $deleteButton = $('.h5p-admin-delete-library', $libraryRow); var $deleteButton = $('.h5p-admin-delete-library', $libraryRow);
if (libraries.notCached !== undefined || hasContent || (library.numContentDependencies !== '' && library.numContentDependencies !== 0) || (library.numLibraryDependencies !== '' && library.numLibraryDependencies !== 0)) { if (libraries.notCached !== undefined || hasContent || (library.numContentDependencies !== '' && library.numContentDependencies !== 0) || (library.numLibraryDependencies !== '' && library.numLibraryDependencies !== 0)) {
// Disabled delete if content. // Disabled delete if content.
@ -90,10 +91,10 @@ var H5PLibraryList= H5PLibraryList || {};
$table.append($libraryRow); $table.append($libraryRow);
}); });
return $table; return $table;
}; };
H5PLibraryList.addRestricted = function ($checkbox, url, selected) { H5PLibraryList.addRestricted = function ($checkbox, url, selected) {
if (selected === null) { if (selected === null) {
$checkbox.remove(); $checkbox.remove();
@ -130,5 +131,5 @@ var H5PLibraryList= H5PLibraryList || {};
H5PLibraryList.init(); H5PLibraryList.init();
} }
}); });
})(H5P.jQuery); })(H5P.jQuery);

View File

@ -3,7 +3,7 @@ var H5PUtils = H5PUtils || {};
(function ($) { (function ($) {
/** /**
* Generic function for creating a table including the headers * Generic function for creating a table including the headers
* *
* @param {array} headers List of headers * @param {array} headers List of headers
*/ */
H5PUtils.createTable = function (headers) { H5PUtils.createTable = function (headers) {
@ -12,62 +12,62 @@ var H5PUtils = H5PUtils || {};
if(headers) { if(headers) {
var $thead = $('<thead></thead>'); var $thead = $('<thead></thead>');
var $tr = $('<tr></tr>'); var $tr = $('<tr></tr>');
$.each(headers, function (index, value) { $.each(headers, function (index, value) {
if (!(value instanceof Object)) { if (!(value instanceof Object)) {
value = { value = {
html: value html: value
}; };
} }
$('<th/>', value).appendTo($tr); $('<th/>', value).appendTo($tr);
}); });
$table.append($thead.append($tr)); $table.append($thead.append($tr));
} }
return $table; return $table;
}; };
/** /**
* Generic function for creating a table row * Generic function for creating a table row
* *
* @param {array} rows Value list. Object name is used as class name in <TD> * @param {array} rows Value list. Object name is used as class name in <TD>
*/ */
H5PUtils.createTableRow = function (rows) { H5PUtils.createTableRow = function (rows) {
var $tr = $('<tr></tr>'); var $tr = $('<tr></tr>');
$.each(rows, function (index, value) { $.each(rows, function (index, value) {
if (!(value instanceof Object)) { if (!(value instanceof Object)) {
value = { value = {
html: value html: value
}; };
} }
$('<td/>', value).appendTo($tr); $('<td/>', value).appendTo($tr);
}); });
return $tr; return $tr;
}; };
/** /**
* Generic function for creating a field containing label and value * Generic function for creating a field containing label and value
* *
* @param {string} label The label displayed in front of the value * @param {string} label The label displayed in front of the value
* @param {string} value The value * @param {string} value The value
*/ */
H5PUtils.createLabeledField = function (label, value) { H5PUtils.createLabeledField = function (label, value) {
var $field = $('<div class="h5p-labeled-field"></div>'); var $field = $('<div class="h5p-labeled-field"></div>');
$field.append('<div class="h5p-label">' + label + '</div>'); $field.append('<div class="h5p-label">' + label + '</div>');
$field.append('<div class="h5p-value">' + value + '</div>'); $field.append('<div class="h5p-value">' + value + '</div>');
return $field; return $field;
}; };
/** /**
* Replaces placeholder fields in translation strings * Replaces placeholder fields in translation strings
* *
* @param {string} template The translation template string in the following format: "$name is a $sex" * @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'} * @param {array} replacors An js object with key and values. Eg: {'$name': 'Frode', '$sex': 'male'}
*/ */
@ -77,10 +77,10 @@ var H5PUtils = H5PUtils || {};
}); });
return template; return template;
}; };
/** /**
* Get throbber with given text. * Get throbber with given text.
* *
* @param {String} text * @param {String} text
* @returns {$} * @returns {$}
*/ */
@ -90,7 +90,7 @@ var H5PUtils = H5PUtils || {};
text: text text: text
}); });
}; };
/** /**
* Makes it possbile to rebuild all content caches from admin UI. * Makes it possbile to rebuild all content caches from admin UI.
* @param {Object} notCached * @param {Object} notCached
@ -107,7 +107,7 @@ var H5PUtils = H5PUtils || {};
current++; current++;
if (current === parts.length) current = 0; if (current === parts.length) current = 0;
}, 100); }, 100);
var $counter = $container.find('.progress'); var $counter = $container.find('.progress');
var build = function () { var build = function () {
$.post(notCached.url, function (left) { $.post(notCached.url, function (left) {
@ -126,8 +126,8 @@ var H5PUtils = H5PUtils || {};
}; };
build(); build();
}); });
return $container; return $container;
}; };
})(H5P.jQuery); })(H5P.jQuery);

179
js/h5p.js
View File

@ -1,3 +1,4 @@
/*jshint multistr: true */
// TODO: Should we split up the generic parts needed by the editor(and others), and the parts needed to "run" H5Ps? // TODO: Should we split up the generic parts needed by the editor(and others), and the parts needed to "run" H5Ps?
var H5P = H5P || {}; var H5P = H5P || {};
@ -11,12 +12,10 @@ H5P.$window = H5P.jQuery(window);
if (document.documentElement.requestFullScreen) { if (document.documentElement.requestFullScreen) {
H5P.fullScreenBrowserPrefix = ''; H5P.fullScreenBrowserPrefix = '';
} }
else if (document.documentElement.webkitRequestFullScreen else if (document.documentElement.webkitRequestFullScreen) {
&& navigator.userAgent.indexOf('Android') === -1 // Skip Android
) {
H5P.safariBrowser = navigator.userAgent.match(/Version\/(\d)/); H5P.safariBrowser = navigator.userAgent.match(/Version\/(\d)/);
H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1])); H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1]));
// Do not allow fullscreen for safari < 7. // Do not allow fullscreen for safari < 7.
if (H5P.safariBrowser === 0 || H5P.safariBrowser > 6) { if (H5P.safariBrowser === 0 || H5P.safariBrowser > 6) {
H5P.fullScreenBrowserPrefix = 'webkit'; H5P.fullScreenBrowserPrefix = 'webkit';
@ -56,14 +55,14 @@ H5P.init = function () {
// Create new instance. // Create new instance.
var instance = H5P.newRunnable(library, contentId, $container, true); var instance = H5P.newRunnable(library, contentId, $container, true);
// Check if we should add and display a fullscreen button for this H5P. // Check if we should add and display a fullscreen button for this H5P.
if (contentData.fullScreen == 1) { if (contentData.fullScreen == 1) {
H5P.jQuery('<div class="h5p-content-controls"><div role="button" tabindex="1" class="h5p-enable-fullscreen" title="' + H5P.t('fullscreen') + '"></div></div>').prependTo($container).children().click(function () { H5P.jQuery('<div class="h5p-content-controls"><div role="button" tabindex="1" class="h5p-enable-fullscreen" title="' + H5P.t('fullscreen') + '"></div></div>').prependTo($container).children().click(function () {
H5P.fullScreen($container, instance); H5P.fullScreen($container, instance);
}); });
}; }
var $actions = H5P.jQuery('<ul class="h5p-actions"></ul>'); var $actions = H5P.jQuery('<ul class="h5p-actions"></ul>');
if (contentData.exportUrl !== '') { if (contentData.exportUrl !== '') {
// Display export button // Display export button
@ -87,7 +86,7 @@ H5P.init = function () {
H5P.jQuery('<li><a class="h5p-link" href="http://h5p.org" target="_blank" title="' + H5P.t('h5pDescription') + '"></a></li>').appendTo($actions); H5P.jQuery('<li><a class="h5p-link" href="http://h5p.org" target="_blank" title="' + H5P.t('h5pDescription') + '"></a></li>').appendTo($actions);
} }
$actions.insertAfter($container); $actions.insertAfter($container);
if (H5P.isFramed) { if (H5P.isFramed) {
// Make it possible to resize the iframe when the content changes size. This way we get no scrollbars. // Make it possible to resize the iframe when the content changes size. This way we get no scrollbars.
var iframe = window.parent.document.getElementById('h5p-iframe-' + contentId); var iframe = window.parent.document.getElementById('h5p-iframe-' + contentId);
@ -95,10 +94,10 @@ H5P.init = function () {
if (window.parent.H5P.isFullscreen) { if (window.parent.H5P.isFullscreen) {
return; // Skip if full screen. return; // Skip if full screen.
} }
// Retain parent size to avoid jumping/scrolling // Retain parent size to avoid jumping/scrolling
var parentHeight = iframe.parentElement.style.height; var parentHeight = iframe.parentElement.style.height;
iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px'; iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px';
// Reset iframe height, in case content has shrinked. // Reset iframe height, in case content has shrinked.
iframe.style.height = '1px'; iframe.style.height = '1px';
@ -109,7 +108,7 @@ H5P.init = function () {
// Free parent // Free parent
iframe.parentElement.style.height = parentHeight; iframe.parentElement.style.height = parentHeight;
}; };
var resizeDelay; var resizeDelay;
instance.$.on('resize', function () { instance.$.on('resize', function () {
// Use a delay to make sure iframe is resized to the correct size. // Use a delay to make sure iframe is resized to the correct size.
@ -119,7 +118,7 @@ H5P.init = function () {
}, 1); }, 1);
}); });
} }
// Resize everything when window is resized. // Resize everything when window is resized.
$window.resize(function () { $window.resize(function () {
if (window.parent.H5P.isFullscreen) { if (window.parent.H5P.isFullscreen) {
@ -130,7 +129,7 @@ H5P.init = function () {
instance.$.trigger('resize'); instance.$.trigger('resize');
} }
}); });
// Resize content. // Resize content.
instance.$.trigger('resize'); instance.$.trigger('resize');
}); });
@ -159,7 +158,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
window.parent.H5P.fullScreen($element, instance, exitCallback, H5P.$body.get()); window.parent.H5P.fullScreen($element, instance, exitCallback, H5P.$body.get());
return; return;
} }
var $container = $element; var $container = $element;
var $classes, $iframe; var $classes, $iframe;
if (body === undefined) { if (body === undefined) {
@ -173,23 +172,23 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
$iframe = H5P.jQuery(iframeSelector); $iframe = H5P.jQuery(iframeSelector);
$element = $iframe.parent(); // Put iframe wrapper in fullscreen, not container. $element = $iframe.parent(); // Put iframe wrapper in fullscreen, not container.
} }
$classes = $element.add(H5P.$body).add($classes); $classes = $element.add(H5P.$body).add($classes);
/** /**
* Prepare for resize by setting the correct styles. * Prepare for resize by setting the correct styles.
* *
* @param {String} classes CSS * @param {String} classes CSS
*/ */
var before = function (classes) { var before = function (classes) {
$classes.addClass(classes); $classes.addClass(classes);
if ($iframe !== undefined) { if ($iframe !== undefined) {
// Set iframe to its default size(100%). // Set iframe to its default size(100%).
$iframe.css('height', ''); $iframe.css('height', '');
} }
}; };
/** /**
* Gets called when fullscreen mode has been entered. * Gets called when fullscreen mode has been entered.
* Resizes and sets focus on content. * Resizes and sets focus on content.
@ -199,17 +198,17 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
instance.$.trigger('resize'); instance.$.trigger('resize');
instance.$.trigger('focus'); instance.$.trigger('focus');
}; };
/** /**
* Gets called when fullscreen mode has been exited. * Gets called when fullscreen mode has been exited.
* Resizes and sets focus on content. * Resizes and sets focus on content.
* *
* @param {String} classes CSS * @param {String} classes CSS
*/ */
var done = function (classes) { var done = function (classes) {
H5P.isFullscreen = false; H5P.isFullscreen = false;
$classes.removeClass(classes); $classes.removeClass(classes);
// Do not rely on window resize events. // Do not rely on window resize events.
instance.$.trigger('resize'); instance.$.trigger('resize');
instance.$.trigger('focus'); instance.$.trigger('focus');
@ -222,11 +221,11 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
H5P.isFullscreen = true; H5P.isFullscreen = true;
if (H5P.fullScreenBrowserPrefix === undefined) { if (H5P.fullScreenBrowserPrefix === undefined) {
// Create semi fullscreen. // Create semi fullscreen.
before('h5p-semi-fullscreen'); before('h5p-semi-fullscreen');
var $disable = H5P.jQuery('<div role="button" tabindex="1" class="h5p-disable-fullscreen" title="' + H5P.t('disableFullscreen') + '"></div>').appendTo($container.find('.h5p-content-controls')); var $disable = H5P.jQuery('<div role="button" tabindex="1" class="h5p-disable-fullscreen" title="' + H5P.t('disableFullscreen') + '"></div>').appendTo($container.find('.h5p-content-controls'));
var keyup, disableSemiFullscreen = function () { var keyup, disableSemiFullscreen = function () {
$disable.remove(); $disable.remove();
$body.unbind('keyup', keyup); $body.unbind('keyup', keyup);
done('h5p-semi-fullscreen'); done('h5p-semi-fullscreen');
}; };
@ -241,7 +240,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
} }
else { else {
// Create real fullscreen. // Create real fullscreen.
before('h5p-fullscreen'); before('h5p-fullscreen');
var first, eventName = (H5P.fullScreenBrowserPrefix === 'ms' ? 'MSFullscreenChange' : H5P.fullScreenBrowserPrefix + 'fullscreenchange'); var first, eventName = (H5P.fullScreenBrowserPrefix === 'ms' ? 'MSFullscreenChange' : H5P.fullScreenBrowserPrefix + 'fullscreenchange');
document.addEventListener(eventName, function () { document.addEventListener(eventName, function () {
@ -251,7 +250,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body) {
entered(); entered();
return; return;
} }
// We are exiting fullscreen // We are exiting fullscreen
done('h5p-fullscreen'); done('h5p-fullscreen');
document.removeEventListener(eventName, arguments.callee, false); document.removeEventListener(eventName, arguments.callee, false);
@ -282,26 +281,26 @@ H5P.getPath = function (path, contentId) {
var hasProtocol = function (path) { var hasProtocol = function (path) {
return path.match(/^[a-z0-9]+:\/\//i); return path.match(/^[a-z0-9]+:\/\//i);
}; };
if (hasProtocol(path)) { if (hasProtocol(path)) {
return path; return path;
} }
if (contentId !== undefined) { if (contentId !== undefined) {
prefix = H5PIntegration.getContentPath(contentId); prefix = H5PIntegration.getContentPath(contentId);
} }
else if (window['H5PEditor'] !== undefined) { else if (window.H5PEditor !== undefined) {
prefix = H5PEditor.filesPath; prefix = H5PEditor.filesPath;
} }
else { else {
return; return;
} }
if (!hasProtocol(prefix)) { if (!hasProtocol(prefix)) {
prefix = window.parent.location.protocol + "//" + window.parent.location.host + prefix; prefix = window.parent.location.protocol + "//" + window.parent.location.host + prefix;
} }
return prefix + '/' + path; return prefix + '/' + path;
}; };
/** /**
@ -318,7 +317,7 @@ H5P.getContentPath = function (contentId) {
/** /**
* Get library class constructor from H5P by classname. * Get library class constructor from H5P by classname.
* Note that this class will only work for resolve "H5P.NameWithoutDot". * Note that this class will only work for resolve "H5P.NameWithoutDot".
* Also check out: H5P.newRunnable * Also check out: H5P.newRunnable
* *
* Used from libraries to construct instances of other libraries' objects by name. * Used from libraries to construct instances of other libraries' objects by name.
@ -336,34 +335,36 @@ H5P.classFromName = function (name) {
* *
* TODO: Should we check if version matches the library? * TODO: Should we check if version matches the library?
* TODO: Dynamically try to load libraries currently not loaded? That will require a callback. * TODO: Dynamically try to load libraries currently not loaded? That will require a callback.
* *
* @param {Object} library Library/action object form params. * @param {Object} library Library/action object form params.
* @param {Number} contentId * @param {Number} contentId
* @param {jQuery} $attachTo An optional element to attach the instance to. * @param {jQuery} $attachTo An optional element to attach the instance to.
* @param {Boolean} skipResize Optionally skip triggering of the resize event after attaching. * @param {Boolean} skipResize Optionally skip triggering of the resize event after attaching.
* @return {Object} Instance. * @return {Object} Instance.
*/ */
H5P.newRunnable = function (library, contentId, $attachTo, skipResize) { H5P.newRunnable = function (library, contentId, $attachTo, skipResize) {
var nameSplit, versionSplit;
try { try {
var nameSplit = library.library.split(' ', 2); nameSplit = library.library.split(' ', 2);
var versionSplit = nameSplit[1].split('.', 2); versionSplit = nameSplit[1].split('.', 2);
} }
catch (err) { catch (err) {
return H5P.error('Invalid library string: ' + library.library); return H5P.error('Invalid library string: ' + library.library);
} }
if ((library.params instanceof Object) !== true || (library.params instanceof Array) === true) { if ((library.params instanceof Object) !== true || (library.params instanceof Array) === true) {
H5P.error('Invalid library params for: ' + library.library); H5P.error('Invalid library params for: ' + library.library);
return H5P.error(library.params); return H5P.error(library.params);
} }
// Find constructor function // Find constructor function
var constructor;
try { try {
nameSplit = nameSplit[0].split('.'); nameSplit = nameSplit[0].split('.');
var constructor = window; constructor = window;
for (var i = 0; i < nameSplit.length; i++) { for (var i = 0; i < nameSplit.length; i++) {
constructor = constructor[nameSplit[i]]; constructor = constructor[nameSplit[i]];
}; }
if (typeof constructor !== 'function') { if (typeof constructor !== 'function') {
throw null; throw null;
} }
@ -371,16 +372,16 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize) {
catch (err) { catch (err) {
return H5P.error('Unable to find constructor for: ' + library.library); return H5P.error('Unable to find constructor for: ' + library.library);
} }
var instance = new constructor(library.params, contentId); var instance = new constructor(library.params, contentId);
if (instance.$ === undefined) { if (instance.$ === undefined) {
instance.$ = H5P.jQuery(instance); instance.$ = H5P.jQuery(instance);
} }
if ($attachTo !== undefined) { if ($attachTo !== undefined) {
instance.attach($attachTo); instance.attach($attachTo);
if (skipResize === undefined || !skipResize) { if (skipResize === undefined || !skipResize) {
// Resize content. // Resize content.
instance.$.trigger('resize'); instance.$.trigger('resize');
@ -417,18 +418,18 @@ H5P.t = function (key, vars, ns) {
if (H5PIntegration.i18n[ns] === undefined) { if (H5PIntegration.i18n[ns] === undefined) {
return '[Missing translation namespace "' + ns + '"]'; return '[Missing translation namespace "' + ns + '"]';
} }
if (H5PIntegration.i18n[ns][key] === undefined) { if (H5PIntegration.i18n[ns][key] === undefined) {
return '[Missing translation "' + key + '" in "' + ns + '"]'; return '[Missing translation "' + key + '" in "' + ns + '"]';
} }
var translation = H5PIntegration.i18n[ns][key]; var translation = H5PIntegration.i18n[ns][key];
if (vars !== undefined) { if (vars !== undefined) {
// Replace placeholder with variables. // Replace placeholder with variables.
for (var placeholder in vars) { for (var placeholder in vars) {
translation = translation.replace(placeholder, vars[placeholder]); translation = translation.replace(placeholder, vars[placeholder]);
} }
} }
return translation; return translation;
@ -457,7 +458,7 @@ H5P.Dialog = function (name, title, content, $element) {
}) })
.end() .end()
.end(); .end();
this.open = function () { this.open = function () {
setTimeout(function () { setTimeout(function () {
$dialog.addClass('h5p-open'); // Fade in $dialog.addClass('h5p-open'); // Fade in
@ -465,7 +466,7 @@ H5P.Dialog = function (name, title, content, $element) {
H5P.jQuery(self).trigger('dialog-opened', [$dialog]); H5P.jQuery(self).trigger('dialog-opened', [$dialog]);
}, 1); }, 1);
}; };
this.close = function () { this.close = function () {
$dialog.removeClass('h5p-open'); // Fade out $dialog.removeClass('h5p-open'); // Fade out
setTimeout(function () { setTimeout(function () {
@ -489,7 +490,7 @@ H5P.openCopyrightsDialog = function ($element, instance) {
if (copyrights === undefined || copyrights === '') { if (copyrights === undefined || copyrights === '') {
copyrights = H5P.t('noCopyrights'); copyrights = H5P.t('noCopyrights');
} }
var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $element); var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $element);
dialog.open(); dialog.open();
}; };
@ -503,12 +504,12 @@ H5P.openCopyrightsDialog = function ($element, instance) {
*/ */
H5P.openEmbedDialog = function ($element, embedCode) { H5P.openEmbedDialog = function ($element, embedCode) {
var dialog = new H5P.Dialog('embed', H5P.t('embed'), '<textarea class="h5p-embed-code-container">' + embedCode + '</textarea>', $element); var dialog = new H5P.Dialog('embed', H5P.t('embed'), '<textarea class="h5p-embed-code-container">' + embedCode + '</textarea>', $element);
// Selecting embed code when dialog is opened // Selecting embed code when dialog is opened
H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) { H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) {
$dialog.find('.h5p-embed-code-container').select(); $dialog.find('.h5p-embed-code-container').select();
}); });
dialog.open(); dialog.open();
}; };
@ -519,7 +520,7 @@ H5P.ContentCopyrights = function () {
var label; var label;
var media = []; var media = [];
var content = []; var content = [];
/** /**
* Public. Set label. * Public. Set label.
* *
@ -528,7 +529,7 @@ H5P.ContentCopyrights = function () {
this.setLabel = function (newLabel) { this.setLabel = function (newLabel) {
label = newLabel; label = newLabel;
}; };
/** /**
* Public. Add sub content. * Public. Add sub content.
* *
@ -539,7 +540,7 @@ H5P.ContentCopyrights = function () {
media.push(newMedia); media.push(newMedia);
} }
}; };
/** /**
* Public. Add sub content. * Public. Add sub content.
* *
@ -550,7 +551,7 @@ H5P.ContentCopyrights = function () {
content.push(newContent); content.push(newContent);
} }
}; };
/** /**
* Public. Print content copyright. * Public. Print content copyright.
* *
@ -558,28 +559,28 @@ H5P.ContentCopyrights = function () {
*/ */
this.toString = function () { this.toString = function () {
var html = ''; var html = '';
// Add media rights // Add media rights
for (var i = 0; i < media.length; i++) { for (var i = 0; i < media.length; i++) {
html += media[i]; html += media[i];
} }
// Add sub content rights // Add sub content rights
for (var i = 0; i < content.length; i++) { for (i = 0; i < content.length; i++) {
html += content[i]; html += content[i];
} }
if (html !== '') { if (html !== '') {
// Add a label to this info // Add a label to this info
if (label !== undefined) { if (label !== undefined) {
html = '<h3>' + label + '</h3>' + html; html = '<h3>' + label + '</h3>' + html;
} }
// Add wrapper // Add wrapper
html = '<div class="h5p-content-copyrights">' + html + '</div>'; html = '<div class="h5p-content-copyrights">' + html + '</div>';
} }
return html; return html;
}; };
}; };
@ -595,35 +596,35 @@ H5P.ContentCopyrights = function () {
H5P.MediaCopyright = function (copyright, labels, order, extraFields) { H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
var thumbnail; var thumbnail;
var list = new H5P.DefinitionList(); var list = new H5P.DefinitionList();
/** /**
* Private. Get translated label for field. * Private. Get translated label for field.
* *
* @param {String} fieldName * @param {String} fieldName
* @return {String} * @return {String}
*/ */
var getLabel = function (fieldName) { var getLabel = function (fieldName) {
if (labels === undefined || labels[fieldName] === undefined) { if (labels === undefined || labels[fieldName] === undefined) {
return H5P.t(fieldName); return H5P.t(fieldName);
} }
return labels[fieldName]; return labels[fieldName];
}; };
/** /**
* Private. Get humanized value for field. * Private. Get humanized value for field.
* *
* @param {String} fieldName * @param {String} fieldName
* @return {String} * @return {String}
*/ */
var humanizeValue = function (fieldName, value) { var humanizeValue = function (fieldName, value) {
if (fieldName === 'license') { if (fieldName === 'license') {
return H5P.copyrightLicenses[value]; return H5P.copyrightLicenses[value];
} }
return value; return value;
}; };
if (copyright !== undefined) { if (copyright !== undefined) {
// Add the extra fields // Add the extra fields
for (var field in extraFields) { for (var field in extraFields) {
@ -631,12 +632,12 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
copyright[field] = extraFields[field]; copyright[field] = extraFields[field];
} }
} }
if (order === undefined) { if (order === undefined) {
// Set default order // Set default order
order = ['title', 'author', 'year', 'source', 'license']; order = ['title', 'author', 'year', 'source', 'license'];
} }
for (var i = 0; i < order.length; i++) { for (var i = 0; i < order.length; i++) {
var fieldName = order[i]; var fieldName = order[i];
if (copyright[fieldName] !== undefined) { if (copyright[fieldName] !== undefined) {
@ -644,7 +645,7 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
} }
} }
} }
/** /**
* Public. Set thumbnail. * Public. Set thumbnail.
* *
@ -653,7 +654,7 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
this.setThumbnail = function (newThumbnail) { this.setThumbnail = function (newThumbnail) {
thumbnail = newThumbnail; thumbnail = newThumbnail;
}; };
/** /**
* Public. Checks if this copyright is undisclosed. * Public. Checks if this copyright is undisclosed.
* I.e. only has the license attribute set, and it's undisclosed. * I.e. only has the license attribute set, and it's undisclosed.
@ -669,7 +670,7 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
} }
return false; return false;
}; };
/** /**
* Public. Print media copyright. * Public. Print media copyright.
* *
@ -677,20 +678,20 @@ H5P.MediaCopyright = function (copyright, labels, order, extraFields) {
*/ */
this.toString = function () { this.toString = function () {
var html = ''; var html = '';
if (this.undisclosed()) { if (this.undisclosed()) {
return html; // No need to print a copyright with a single undisclosed license. return html; // No need to print a copyright with a single undisclosed license.
} }
if (thumbnail !== undefined) { if (thumbnail !== undefined) {
html += thumbnail; html += thumbnail;
} }
html += list; html += list;
if (html !== '') { if (html !== '') {
html = '<div class="h5p-media-copyright">' + html + '</div>'; html = '<div class="h5p-media-copyright">' + html + '</div>';
} }
return html; return html;
}; };
}; };
@ -742,16 +743,16 @@ H5P.Field = function (label, value) {
* Public. Get field label. * Public. Get field label.
* *
* @returns {String} * @returns {String}
*/ */
this.getLabel = function () { this.getLabel = function () {
return label; return label;
}; };
/** /**
* Public. Get field value. * Public. Get field value.
* *
* @returns {String} * @returns {String}
*/ */
this.getValue = function () { this.getValue = function () {
return value; return value;
}; };
@ -762,7 +763,7 @@ H5P.Field = function (label, value) {
*/ */
H5P.DefinitionList = function () { H5P.DefinitionList = function () {
var fields = []; var fields = [];
/** /**
* Public. Add field to list. * Public. Add field to list.
* *
@ -771,7 +772,7 @@ H5P.DefinitionList = function () {
this.add = function (field) { this.add = function (field) {
fields.push(field); fields.push(field);
}; };
/** /**
* Public. Get Number of fields. * Public. Get Number of fields.
* *
@ -780,7 +781,7 @@ H5P.DefinitionList = function () {
this.size = function () { this.size = function () {
return fields.length; return fields.length;
}; };
/** /**
* Public. Get field at given index. * Public. Get field at given index.
* *
@ -790,7 +791,7 @@ H5P.DefinitionList = function () {
this.get = function (index) { this.get = function (index) {
return fields[index]; return fields[index];
}; };
/** /**
* Public. Print definition list. * Public. Print definition list.
* *
@ -879,7 +880,7 @@ H5P.getLibraryPath = function (library) {
/** /**
* Recursivly clone the given object. * Recursivly clone the given object.
* TODO: Consider if this needs to be in core. Doesn't $.extend do the same? * TODO: Consider if this needs to be in core. Doesn't $.extend do the same?
* *
* @param {object} object Object to clone. * @param {object} object Object to clone.
* @param {type} recursive * @param {type} recursive

1
js/jquery.js vendored

File diff suppressed because one or more lines are too long

View File

@ -244,4 +244,7 @@ button.h5p-admin.disabled:hover {
padding: 0 0.5em; padding: 0 0.5em;
font-size: 1.5em; font-size: 1.5em;
font-weight: bold; font-weight: bold;
} }
#h5p-admin-container .h5p-admin-center {
text-align: center;
}