From 8431304dd0556a02a8f53c5c65777d74ce7e1226 Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Fri, 10 Jul 2015 11:41:28 +0200 Subject: [PATCH 1/9] Remove todos --- js/h5p.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/h5p.js b/js/h5p.js index 9bf7c21..f217a5f 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -682,9 +682,6 @@ H5P.classFromName = function (name) { * Instance. */ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { - // TODO: Should we check if version matches the library? - // TODO: Dynamically try to load libraries currently not loaded? That will require a callback. - var nameSplit, versionSplit, machineName; try { nameSplit = library.library.split(' ', 2); From 03370c95006e6ea175d721270ef93b08a642b2b2 Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Fri, 10 Jul 2015 12:58:02 +0200 Subject: [PATCH 2/9] Add info about the library being used to the xAPI statements --- js/h5p-x-api-event.js | 11 +++++++++++ js/h5p.js | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/js/h5p-x-api-event.js b/js/h5p-x-api-event.js index a973dee..acaed22 100644 --- a/js/h5p-x-api-event.js +++ b/js/h5p-x-api-event.js @@ -131,6 +131,17 @@ H5P.XAPIEvent.prototype.setContext = function (instance) { } }; } + if (instance.libraryInfo) { + if (this.data.statement.context === undefined) { + this.data.statement.context = {"contextActivities":{}}; + } + this.data.statement.context.contextActivities.category = [ + { + "id": "http://h5p.org/libraries/" + instance.libraryInfo.versionedNameNoSpaces, + "objectType": "Activity" + } + ]; + } }; /** diff --git a/js/h5p.js b/js/h5p.js index f217a5f..a57fe64 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -748,6 +748,15 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { if (instance.parent === undefined && extras && extras.parent) { instance.parent = extras.parent; } + if (instance.libraryInfo === undefined) { + instance.libraryInfo = { + versionedName: library.library, + versionedNameNoSpaces: machineName + '-' + versionSplit[0] + '.' + versionSplit[1], + machineName: machineName, + majorVersion: versionSplit[0], + minorVersion: versionSplit[1] + }; + } if ($attachTo !== undefined) { instance.attach($attachTo); From e36582c71423b0304809baddf783d5dacbc908cd Mon Sep 17 00:00:00 2001 From: Paal Joergensen Date: Tue, 14 Jul 2015 14:37:39 +0200 Subject: [PATCH 3/9] Added H5P base class that all H5P libraries automatically extends --- js/h5p.js | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/js/h5p.js b/js/h5p.js index a57fe64..63c29a8 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -72,6 +72,38 @@ H5P.DISABLE_ABOUT = 16; */ H5P.opened = {}; +/** + * H5P Base class. Adds utility functions to a library's prototype object. + * + * Functions here may be overridable by the libraries. In special cases, + * it is also possible to override H5P.Base on a global level. + * */ +H5P.Base = function (constructor, standalone, library) { + /** + * Is library standalone or not? Not beeing standalone, means it is + * included in another library + * + * @method isStandalone + * @return {Boolean} + */ + this.isStandalone = function () { + return standalone; + }; + + /** + * Returns the file path of a file in the current library + * @method getLibraryFilePath + * @param {string} filePath The path to the file relative to the library folder + * @return {string} The full path to the file + */ + this.getLibraryFilePath = function (filePath) { + return H5P.getLibraryPath(library.library) + '/' + filePath; + }; + + // This order makes it possible for an H5P library to override H5P.Base functions! + return H5P.jQuery.extend({}, this, constructor.prototype); +}; + /** * Initialize H5P content. * Scans for ".h5p-content" in the document and initializes H5P instances where found. @@ -135,7 +167,7 @@ H5P.init = function (target) { }); // Create new instance. - var instance = H5P.newRunnable(library, contentId, $container, true); + var instance = H5P.newRunnable(library, contentId, $container, true, {standalone: true}); // Check if we should add and display a fullscreen button for this H5P. if (contentData.fullScreen == 1 && H5P.canHasFullScreen) { @@ -724,6 +756,10 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { extras.previousState = library.userDatas.state; } + // Makes all H5P libraries extend H5P.Base: + var standalone = extras.standalone || false; + constructor.prototype = H5P.Base(constructor, standalone, library); + var instance; // Some old library versions have their own custom third parameter. // Make sure we don't send them the extras. @@ -759,6 +795,7 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { } if ($attachTo !== undefined) { + $attachTo.toggleClass('h5p-standalone', standalone); instance.attach($attachTo); H5P.trigger(instance, 'domChanged', { '$target': $attachTo, From 8cf384f46ace41b678c4829ba52d5e55619bbe57 Mon Sep 17 00:00:00 2001 From: Paal Joergensen Date: Tue, 14 Jul 2015 14:46:35 +0200 Subject: [PATCH 4/9] Fixed H5P.Base.getLibraryFilePath() bug --- js/h5p.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/h5p.js b/js/h5p.js index 63c29a8..41cad63 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -97,7 +97,8 @@ H5P.Base = function (constructor, standalone, library) { * @return {string} The full path to the file */ this.getLibraryFilePath = function (filePath) { - return H5P.getLibraryPath(library.library) + '/' + filePath; + var libraryObject = H5P.libraryFromString(library.library); + return H5P.getLibraryPath(libraryObject.machineName + '-' + libraryObject.majorVersion + '.' + libraryObject.minorVersion) + '/' + filePath; }; // This order makes it possible for an H5P library to override H5P.Base functions! From 56e74c2d680e732c70931e526938e6f4afe96c94 Mon Sep 17 00:00:00 2001 From: Paal Joergensen Date: Fri, 17 Jul 2015 13:32:35 +0200 Subject: [PATCH 5/9] Renamed H5P.Base to H5P.ContentType. Moved H5P.ContentType code to separate file. Made H5P.ContentType extend H5P.EventDispatcher. --- h5p.classes.php | 1 + js/h5p-content-type.js | 37 +++++++++++++++++++++++++++++++++++++ js/h5p.js | 38 +++----------------------------------- 3 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 js/h5p-content-type.js diff --git a/h5p.classes.php b/h5p.classes.php index c291c2d..d9dc982 100644 --- a/h5p.classes.php +++ b/h5p.classes.php @@ -1643,6 +1643,7 @@ class H5PCore { 'js/h5p-event-dispatcher.js', 'js/h5p-x-api-event.js', 'js/h5p-x-api.js', + 'js/h5p-content-type.js', ); public static $adminScripts = array( 'js/jquery.js', diff --git a/js/h5p-content-type.js b/js/h5p-content-type.js new file mode 100644 index 0000000..3a56c72 --- /dev/null +++ b/js/h5p-content-type.js @@ -0,0 +1,37 @@ +/** + * H5P.ContentType is a base class for all content types. Used by newRunnable() + * + * Functions here may be overridable by the libraries. In special cases, + * it is also possible to override H5P.ContentType on a global level. + * */ +H5P.ContentType = function (standalone, library) { + + function ContentType() {}; + + // Inherit from EventDispatcher. + ContentType.prototype = new H5P.EventDispatcher(); + + /** + * Is library standalone or not? Not beeing standalone, means it is + * included in another library + * + * @method isStandalone + * @return {Boolean} + */ + ContentType.prototype.isStandalone = function () { + return standalone; + }; + + /** + * Returns the file path of a file in the current library + * @method getLibraryFilePath + * @param {string} filePath The path to the file relative to the library folder + * @return {string} The full path to the file + */ + ContentType.prototype.getLibraryFilePath = function (filePath) { + var libraryObject = H5P.libraryFromString(library.library); + return H5P.getLibraryPath(libraryObject.machineName + '-' + libraryObject.majorVersion + '.' + libraryObject.minorVersion) + '/' + filePath; + }; + + return ContentType; +}; diff --git a/js/h5p.js b/js/h5p.js index 41cad63..ea48c4e 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -72,39 +72,6 @@ H5P.DISABLE_ABOUT = 16; */ H5P.opened = {}; -/** - * H5P Base class. Adds utility functions to a library's prototype object. - * - * Functions here may be overridable by the libraries. In special cases, - * it is also possible to override H5P.Base on a global level. - * */ -H5P.Base = function (constructor, standalone, library) { - /** - * Is library standalone or not? Not beeing standalone, means it is - * included in another library - * - * @method isStandalone - * @return {Boolean} - */ - this.isStandalone = function () { - return standalone; - }; - - /** - * Returns the file path of a file in the current library - * @method getLibraryFilePath - * @param {string} filePath The path to the file relative to the library folder - * @return {string} The full path to the file - */ - this.getLibraryFilePath = function (filePath) { - var libraryObject = H5P.libraryFromString(library.library); - return H5P.getLibraryPath(libraryObject.machineName + '-' + libraryObject.majorVersion + '.' + libraryObject.minorVersion) + '/' + filePath; - }; - - // This order makes it possible for an H5P library to override H5P.Base functions! - return H5P.jQuery.extend({}, this, constructor.prototype); -}; - /** * Initialize H5P content. * Scans for ".h5p-content" in the document and initializes H5P instances where found. @@ -757,9 +724,10 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { extras.previousState = library.userDatas.state; } - // Makes all H5P libraries extend H5P.Base: + // Makes all H5P libraries extend H5P.ContentType: var standalone = extras.standalone || false; - constructor.prototype = H5P.Base(constructor, standalone, library); + // This order makes it possible for an H5P library to override H5P.ContentType functions! + constructor.prototype = H5P.jQuery.extend({}, H5P.ContentType(standalone, library).prototype, constructor.prototype); var instance; // Some old library versions have their own custom third parameter. From 769fd219bc280ec81fdd47e0c9bfa225dfa92885 Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Mon, 20 Jul 2015 13:03:05 +0200 Subject: [PATCH 6/9] API 1.6 --- h5p.classes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h5p.classes.php b/h5p.classes.php index c291c2d..57cf6ff 100644 --- a/h5p.classes.php +++ b/h5p.classes.php @@ -1632,7 +1632,7 @@ class H5PCore { public static $coreApi = array( 'majorVersion' => 1, - 'minorVersion' => 5 + 'minorVersion' => 6 ); public static $styles = array( 'styles/h5p.css', From 5d1cd188d0c33f691498cc54db822e10878a58c1 Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Mon, 20 Jul 2015 13:05:41 +0200 Subject: [PATCH 7/9] Add duration and scaled to result --- js/h5p-x-api-event.js | 11 ++++++++++- js/h5p-x-api.js | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/js/h5p-x-api-event.js b/js/h5p-x-api-event.js index acaed22..98b287a 100644 --- a/js/h5p-x-api-event.js +++ b/js/h5p-x-api-event.js @@ -19,7 +19,7 @@ H5P.XAPIEvent.prototype.constructor = H5P.XAPIEvent; * @param {number} score * @param {number} maxScore */ -H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore) { +H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance) { this.data.statement.result = { 'score': { 'min': 0, @@ -27,6 +27,15 @@ H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore) { 'raw': score } }; + if (maxScore > 0) { + this.data.statement.result.score.scaled = Math.round(score / maxScore * 10000) / 10000; + } + if (instance && instance.activityStartTime) { + var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100; + // xAPI spec allows a precision of 0.01 seconds + + this.data.statement.result.duration = 'PT' + duration + 'S'; + } }; /** diff --git a/js/h5p-x-api.js b/js/h5p-x-api.js index ea5ba79..e287c1a 100644 --- a/js/h5p-x-api.js +++ b/js/h5p-x-api.js @@ -82,10 +82,14 @@ H5P.EventDispatcher.prototype.triggerXAPICompleted = function (score, maxScore) */ H5P.EventDispatcher.prototype.triggerXAPIScored = function (score, maxScore, verb) { var event = this.createXAPIEventTemplate(verb); - event.setScoredResult(score, maxScore); + event.setScoredResult(score, maxScore, this); this.trigger(event); }; +H5P.EventDispatcher.prototype.setActivityStarted = function() { + this.activityStartTime = Date.now(); +}; + /** * Internal H5P function listening for xAPI completed events and stores scores * From 71f147058d684de05c90fde148ffb993fc4cbe84 Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Mon, 20 Jul 2015 13:40:59 +0200 Subject: [PATCH 8/9] Rename isStandalone to isRoot and use ned libraryInfo instead of the so called ubername --- js/h5p-content-type.js | 9 ++++----- js/h5p.js | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/js/h5p-content-type.js b/js/h5p-content-type.js index 3a56c72..afe4136 100644 --- a/js/h5p-content-type.js +++ b/js/h5p-content-type.js @@ -4,7 +4,7 @@ * Functions here may be overridable by the libraries. In special cases, * it is also possible to override H5P.ContentType on a global level. * */ -H5P.ContentType = function (standalone, library) { +H5P.ContentType = function (isRootLibrary, library) { function ContentType() {}; @@ -18,8 +18,8 @@ H5P.ContentType = function (standalone, library) { * @method isStandalone * @return {Boolean} */ - ContentType.prototype.isStandalone = function () { - return standalone; + ContentType.prototype.isRoot = function () { + return isRootLibrary; }; /** @@ -29,8 +29,7 @@ H5P.ContentType = function (standalone, library) { * @return {string} The full path to the file */ ContentType.prototype.getLibraryFilePath = function (filePath) { - var libraryObject = H5P.libraryFromString(library.library); - return H5P.getLibraryPath(libraryObject.machineName + '-' + libraryObject.majorVersion + '.' + libraryObject.minorVersion) + '/' + filePath; + return H5P.getLibraryPath(this.libraryInfo.versionedNameNoSpaces) + '/' + filePath; }; return ContentType; diff --git a/js/h5p.js b/js/h5p.js index ea48c4e..d87d63c 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -727,7 +727,7 @@ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { // Makes all H5P libraries extend H5P.ContentType: var standalone = extras.standalone || false; // This order makes it possible for an H5P library to override H5P.ContentType functions! - constructor.prototype = H5P.jQuery.extend({}, H5P.ContentType(standalone, library).prototype, constructor.prototype); + constructor.prototype = H5P.jQuery.extend({}, H5P.ContentType(standalone).prototype, constructor.prototype); var instance; // Some old library versions have their own custom third parameter. From 8d9781f4ae296b1a561b00cd54828cfefe8ab0ef Mon Sep 17 00:00:00 2001 From: Svein-Tore Griff With Date: Thu, 30 Jul 2015 18:11:59 +0200 Subject: [PATCH 9/9] Also add class when framed --- js/h5p.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/h5p.js b/js/h5p.js index d87d63c..0d1ff2f 100644 --- a/js/h5p.js +++ b/js/h5p.js @@ -182,6 +182,7 @@ H5P.init = function (target) { // Insert action bar if it has any content if (!(contentData.disable & H5P.DISABLE_FRAME) && $actions.children().length) { $actions.insertAfter($container); + $element.addClass('h5p-frame'); } else { $element.addClass('h5p-no-frame');