Add iframe support and more license types

namespaces
Svein-Tore Griff With 2013-11-08 18:16:41 +01:00
parent 12523d810c
commit 0d97f6952c
3 changed files with 208 additions and 23 deletions

View File

@ -244,7 +244,7 @@ class H5PValidator {
private $h5pOptional = array( private $h5pOptional = array(
'contentType' => '/^.{1,255}$/', 'contentType' => '/^.{1,255}$/',
'author' => '/^.{1,255}$/', 'author' => '/^.{1,255}$/',
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT)$/', 'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3|MPL|MPL2)$/',
'dynamicDependencies' => array( 'dynamicDependencies' => array(
'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'machineName' => '/^[\w0-9\-\.]{1,255}$/i',
'majorVersion' => '/^[0-9]{1,5}$/', 'majorVersion' => '/^[0-9]{1,5}$/',
@ -268,7 +268,7 @@ class H5PValidator {
private $libraryOptional = array( private $libraryOptional = array(
'author' => '/^.{1,255}$/', 'author' => '/^.{1,255}$/',
'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3)$/', 'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3|MPL|MPL2)$/',
'description' => '/^.{1,}$/', 'description' => '/^.{1,}$/',
'dynamicDependencies' => array( 'dynamicDependencies' => array(
'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'machineName' => '/^[\w0-9\-\.]{1,255}$/i',
@ -1870,4 +1870,4 @@ class H5PContentValidator {
} }
} }
?> ?>

132
js/h5p.js
View File

@ -1,6 +1,8 @@
var H5P = H5P || {}; var H5P = H5P || {};
// // This needs to be determined before init is run.
H5P.isFramed = (window.self !== window.top); // (window.parent !== window);
// Initialize H5P content // Initialize H5P content
// Scans for ".h5p-content" // Scans for ".h5p-content"
H5P.init = function () { H5P.init = function () {
@ -11,11 +13,18 @@ H5P.init = function () {
H5P.$body = H5P.jQuery('body'); H5P.$body = H5P.jQuery('body');
} }
// Is this H5P being run in a frame?
if (H5P.isFramed) {
H5P.$body.addClass('h5p-iframe-content');
}
if (H5P.fullScreenBrowserPrefix === undefined) { if (H5P.fullScreenBrowserPrefix === undefined) {
if (document.documentElement.requestFullScreen) { if (document.documentElement.requestFullScreen) {
H5P.fullScreenBrowserPrefix = ''; H5P.fullScreenBrowserPrefix = '';
} }
else if (document.documentElement.webkitRequestFullScreen && navigator.userAgent.indexOf('Android') === -1) { // Skip Android else if (document.documentElement.webkitRequestFullScreen
&& navigator.userAgent.indexOf('Android') === -1 // Skip Android
) {
// Safari has stopped working as of v6.0.3. (Specifying keyboard input // Safari has stopped working as of v6.0.3. (Specifying keyboard input
// makes webkitRequestFullScreen silently fail.) The following code // makes webkitRequestFullScreen silently fail.) The following code
// assumes that the Safari developers figure out how to properly handle // assumes that the Safari developers figure out how to properly handle
@ -37,12 +46,17 @@ H5P.init = function () {
} }
} }
// H5Ps added in normal DIV.
H5P.jQuery(".h5p-content").each(function (idx, el) { H5P.jQuery(".h5p-content").each(function (idx, el) {
var $el = H5P.jQuery(el); var $el = H5P.jQuery(el),
var contentId = $el.data('content-id'); contentId = $el.data('content-id'),
var obj = new (H5P.classFromName($el.data('class')))(H5P.jQuery.parseJSON(H5PIntegration.getJsonContent(contentId)), contentId); mainLibrary = $el.data('class'),
obj = new (H5P.classFromName(mainLibrary))(H5P.jQuery.parseJSON(H5PIntegration.getJsonContent(contentId)), contentId);
// Render H5P in container.
obj.attach($el); obj.attach($el);
// Add Fullscreen button if relevant.
if (H5PIntegration.getFullscreen(contentId)) { if (H5PIntegration.getFullscreen(contentId)) {
H5P.jQuery('<div class="h5p-content-controls"><a href="#" class="h5p-enable-fullscreen">' + H5PIntegration.fullscreenText + '</a></div>').insertBefore($el).children().click(function () { H5P.jQuery('<div class="h5p-content-controls"><a href="#" class="h5p-enable-fullscreen">' + H5PIntegration.fullscreenText + '</a></div>').insertBefore($el).children().click(function () {
H5P.fullScreen($el, obj); H5P.fullScreen($el, obj);
@ -50,6 +64,47 @@ H5P.init = function () {
}); });
} }
}); });
// H5Ps living in iframes. Note: Fullscreen button will be added
// inside iFrame if relevant
var $h5pIframes = H5P.jQuery(".h5p-iframe");
if ($h5pIframes.length !== 0) {
$h5pIframes.each(function (idx, iframe) {
var $iframe = H5P.jQuery(iframe),
contentId = $iframe.data('content-id'),
mainLibrary = $iframe.data('class');
iframe.contentDocument.open();
iframe.contentDocument.write('<!doctype html><html><head>' + H5PIntegration.getHeadTags(contentId) + '</head><body><div class="h5p-content" data-class="' + mainLibrary + '" data-content-id="' + contentId + '"/></body></html>');
iframe.contentDocument.close();
});
// TODO: This seems very hacky... why can't we just use the resize event? What happens if we ain't done before the next interval starts?
setInterval(function () {
$h5pIframes.each(function (idx, iframe) {
var $iframe = H5P.jQuery(iframe);
var contentHeight = $iframe.contents().height();
var frameHeight = $iframe.innerHeight();
if (frameHeight !== contentHeight) {
H5P.resizeIframe($iframe.data('content-id'), contentHeight);
}
});
}, 250);
}
};
H5P.fullScreenIframe = function (contentId, obj, exitCallback) {
H5P.fullScreen(H5P.jQuery('#iframe-wrapper-' + contentId), obj, exitCallback);
};
H5P.resizeIframe = function (contentId, height) {
var iframe = document.getElementById('iframe-' + contentId);
// Don't allow iFrame to grow beyond window height;
if (height > window.innerHeight) {
height = window.innerHeight;
}
iframe.style.height = (H5P.isFullscreen) ? '100%' : height + 'px';
}; };
/** /**
@ -59,22 +114,44 @@ H5P.init = function () {
* @param {object} obj H5P * @param {object} obj H5P
* @returns {undefined} * @returns {undefined}
*/ */
H5P.fullScreen = function ($el, obj) { H5P.fullScreen = function ($el, obj, exitCallback) {
if (H5P.isFramed) {
var $classes = H5P.jQuery('html').add(H5P.$body).add($el);
$classes.addClass('h5p-fullscreen');
window.parent.H5P.fullScreenIframe($el.data('content-id'), obj, function () {
$classes.removeClass('h5p-fullscreen');
});
return;
}
if (H5P.fullScreenBrowserPrefix === undefined) { if (H5P.fullScreenBrowserPrefix === undefined) {
// Create semi fullscreen. // Create semi fullscreen.
$el.add(H5P.$body).addClass('h5p-semi-fullscreen'); $el.add(H5P.$body).addClass('h5p-semi-fullscreen');
// Move H5P content to top of body to make sure it is above other page // Move H5P content to top of body to make sure it is above other page
// content. Insert placeholder in original position to be able to move it // content. Insert placeholder in original position to be able to move it
// back. // back.
$el.after('<div id="h5pfullscreenreplacementplaceholder"></div>').prependTo(H5P.$body); // THIS DOES NOT WORK WITH IFRAMED CONTENT, iframe will reload/fail.
// $el.after('<div id="h5pfullscreenreplacementplaceholder"></div>').prependTo(H5P.$body);
H5P.isFullscreen = true;
var $disable = H5P.jQuery('<a href="#" class="h5p-disable-fullscreen">Disable fullscreen</a>').appendTo($el); var $disable = H5P.jQuery('<a href="#" class="h5p-disable-fullscreen">Disable fullscreen</a>').appendTo($el);
var keyup, disableSemiFullscreen = function () { var keyup, disableSemiFullscreen = function () {
$el.add(H5P.$body).removeClass('h5p-semi-fullscreen'); $el.add(H5P.$body).removeClass('h5p-semi-fullscreen');
$('#h5pfullscreenreplacementplaceholder').before($el).remove(); // H5P.jQuery('#h5pfullscreenreplacementplaceholder').before($el).remove();
$disable.remove(); $disable.remove();
H5P.isFullscreen = false;
H5P.$body.unbind('keyup', keyup); H5P.$body.unbind('keyup', keyup);
H5P.jQuery(".h5p-iframe").each(function (idx, el) {
H5P.resizeIframe(H5P.jQuery(el).data('content-id'), 0);
});
if (exitCallback) {
exitCallback();
}
if (obj.resize !== undefined) { if (obj.resize !== undefined) {
obj.resize(false); obj.resize(false);
} }
@ -91,12 +168,23 @@ H5P.fullScreen = function ($el, obj) {
} }
else { else {
var first, eventName = H5P.fullScreenBrowserPrefix + 'fullscreenchange'; var first, eventName = H5P.fullScreenBrowserPrefix + 'fullscreenchange';
H5P.isFullscreen = true;
document.addEventListener(eventName, function () { document.addEventListener(eventName, function () {
if (first === undefined) { if (first === undefined) {
first = false; first = false;
return; return;
} }
H5P.isFullscreen = false;
$el.add(H5P.$body).removeClass('h5p-fullscreen'); $el.add(H5P.$body).removeClass('h5p-fullscreen');
H5P.jQuery(".h5p-iframe").each(function (idx, el) {
H5P.resizeIframe(H5P.jQuery(el).data('content-id'), 0);
});
if (exitCallback) {
exitCallback();
}
if (obj.resize !== undefined) { if (obj.resize !== undefined) {
obj.resize(false); obj.resize(false);
} }
@ -112,7 +200,9 @@ H5P.fullScreen = function ($el, obj) {
$el.add(H5P.$body).addClass('h5p-fullscreen'); $el.add(H5P.$body).addClass('h5p-fullscreen');
} }
H5P.jQuery(".h5p-iframe").each(function (idx, el) {
H5P.resizeIframe(H5P.jQuery(el).data('content-id'), 0);
});
if (obj.resize !== undefined) { if (obj.resize !== undefined) {
obj.resize(true); obj.resize(true);
} }
@ -317,10 +407,10 @@ H5P.setFinished = function (contentId, points, maxPoints) {
}; };
// Add indexOf to browsers that lack them. (IEs) // Add indexOf to browsers that lack them. (IEs)
if(!Array.prototype.indexOf) { if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(needle) { Array.prototype.indexOf = function (needle) {
for(var i = 0; i < this.length; i++) { for (var i = 0; i < this.length; i++) {
if(this[i] === needle) { if (this[i] === needle) {
return i; return i;
} }
} }
@ -330,13 +420,19 @@ if(!Array.prototype.indexOf) {
// Need to define trim() since this is not available on older IEs, // Need to define trim() since this is not available on older IEs,
// and trim is used in several libs // and trim is used in several libs
if(String.prototype.trim === undefined) { if (String.prototype.trim === undefined) {
String.prototype.trim = function () { String.prototype.trim = function () {
return H5P.trim(this); return H5P.trim(this);
}; };
} }
// Finally, we want to run init when document is ready. // Finally, we want to run init when document is ready. But not if we're
H5P.jQuery(document).ready(function(){ // in an iFrame. Then we wait for parent to start init().
H5P.init(); if (H5P.jQuery) {
}); H5P.jQuery(document).ready(function () {
if (!H5P.initialized) {
H5P.initialized = true;
H5P.init();
}
});
}

View File

@ -1,9 +1,15 @@
body.h5p-iframe-content {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
}
body.h5p-semi-fullscreen { body.h5p-semi-fullscreen {
overflow: hidden; overflow: hidden;
} }
.h5p-content { .h5p-content {
width: 100%; display: block;
height: 100%; width: auto;
height: auto;
background: #fefefe; background: #fefefe;
font-size: 16px; font-size: 16px;
} }
@ -48,4 +54,87 @@ div.h5p-semi-fullscreen {
text-decoration: none; text-decoration: none;
opacity: 0.9; opacity: 0.9;
filter: alpha(opacity = 90); filter: alpha(opacity = 90);
}
.h5p-iframe-wrapper.h5p-fullscreen {
width: 100%;
height: 100%;
}
.h5p-iframe-wrapper {
width: auto;
height: auto;
}
.h5p-fullscreen .h5p-iframe-wrapper,
.h5p-semi-fullscreen .h5p-iframe-wrapper {
width: 100%;
height: 100%;
}
.h5p-iframe-wrapper.h5p-semi-fullscreen {
width: 100%;
height: 100%;
background: black;
position: fixed;
top: 0;
left: 0;
z-index: 100;
}
.h5p-iframe-wrapper .buttons {
text-align: right;
}
.h5p-iframe-wrapper.h5p-semi-fullscreen .buttons {
position: absolute;
top: 0;
right: 0;
z-index: 20;
}
.h5p-iframe-wrapper .h5p-iframe {
width: 100%;
height: 100%;
z-index: 10;
overflow: hidden;
border: 0;
}
.h5p-iframe-wrapper.h5p-semi-fullscreen .buttons button:before {
content: 'Exit ';
}
.h5p-iframe-wrapper button.fullscreen {
color: #e5eef6;
text-decoration: none;
padding: 6px 12px;
background: #539ad7;
background-image: -webkit-linear-gradient(top,#4584ba,#539ad7);
background-image: -moz-linear-gradient(top,#4584ba,#539ad7);
background-image: -o-linear-gradient(top,#4584ba,#539ad7);
background-image: -ms-linear-gradient(top,#4584ba,#539ad7);
background-image: linear-gradient(to bottom,#4584ba,#539ad7);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4584ba',endColorstr='#539ad7',GradientType=0);
box-shadow: 0 0 8px #bebebe;
border: none;
opacity: 0.8;
}
.h5p-iframe-wrapper button.fullscreen:hover {
opacity: 1;
background: #539ad7;
background-image: -webkit-linear-gradient(top,#539ad7,#4584ba);
background-image: -moz-linear-gradient(top,#539ad7,#4584ba);
background-image: -o-linear-gradient(top,#539ad7,#4584ba);
background-image: -ms-linear-gradient(top,#539ad7,#4584ba);
background-image: linear-gradient(to bottom,#539ad7,#4584ba);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#539ad7',endColorstr='#4584ba',GradientType=0);
cursor: pointer;
}
html.h5p-fullscreen, body.h5p-fullscreen {
height: 100%;
overflow: hidden;
}
.h5p-fullscreen .h5p-content-controls {
display: none;
}
body.h5p-iframe-content div.h5p-content {
overflow: hidden;
}
body.h5p-iframe-content.h5p-fullscreen div.h5p-content {
height: 100%;
} }