Bubbling for event system

semantics-font
Svein-Tore Griff With 2015-04-07 19:33:21 +02:00
parent efbe56001d
commit 5c3620c637
4 changed files with 72 additions and 20 deletions

View File

@ -1606,7 +1606,7 @@ class H5PCore {
public static $coreApi = array( public static $coreApi = array(
'majorVersion' => 1, 'majorVersion' => 1,
'minorVersion' => 4 'minorVersion' => 5
); );
public static $styles = array( public static $styles = array(
'styles/h5p.css', 'styles/h5p.css',
@ -2749,13 +2749,13 @@ class H5PContentValidator {
'type' => 'group', 'type' => 'group',
'fields' => $library['semantics'], 'fields' => $library['semantics'],
), FALSE); ), FALSE);
$validkeys = array('library', 'params', 'uuid'); $validkeys = array('library', 'params', 'subContentId');
if (isset($semantics->extraAttributes)) { if (isset($semantics->extraAttributes)) {
$validkeys = array_merge($validkeys, $semantics->extraAttributes); $validkeys = array_merge($validkeys, $semantics->extraAttributes);
} }
$this->filterParams($value, $validkeys); $this->filterParams($value, $validkeys);
if (isset($value->uuid) && ! preg_match('/^\{?[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\}?$/', $value->uuid)) { if (isset($value->subContentId) && ! preg_match('/^\{?[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\}?$/', $value->subContentId)) {
unset($value->uuid); unset($value->subContentId);
} }
// Find all dependencies for this library // Find all dependencies for this library

View File

@ -9,18 +9,55 @@ H5P.Event = function(type, data, extras) {
this.type = type; this.type = type;
this.data = data; this.data = data;
var bubbles = false; var bubbles = false;
// Is this an external event?
var external = false;
// Is this event scheduled to be sent externally?
var scheduledForExternal = false;
if (extras === undefined) { if (extras === undefined) {
extras = {}; extras = {};
} }
if (extras.bubbles === true) { if (extras.bubbles === true) {
bubbles = true; bubbles = true;
} }
if (extras.external === true) {
external = true;
}
/**
* Prevent this event from bubbling up to parent
*
* @returns {undefined}
*/
this.preventBubbling = function() { this.preventBubbling = function() {
bubbles = false; bubbles = false;
}; };
/**
* Get bubbling status
*
* @returns {Boolean} - true if bubbling false otherwise
*/
this.getBubbles = function() { this.getBubbles = function() {
return bubbles; return bubbles;
}; };
/**
* Try to schedule an event for externalDispatcher
*
* @returns {Boolean}
* - true if external and not already scheduled
* - false otherwise
*/
this.scheduleForExternal = function() {
if (external && !scheduledForExternal) {
scheduledForExternal = true;
return true;
}
return false;
};
}; };
H5P.EventDispatcher = (function () { H5P.EventDispatcher = (function () {
@ -144,27 +181,42 @@ H5P.EventDispatcher = (function () {
* Custom event data(used when event type as string is used as first * Custom event data(used when event type as string is used as first
* argument * argument
*/ */
this.trigger = function (event, eventData) { this.trigger = function (event, eventData, extras) {
if (event === undefined) { if (event === undefined) {
return; return;
} }
if (typeof event === 'string') { if (typeof event === 'string') {
event = new H5P.Event(event, eventData); event = new H5P.Event(event, eventData, extras);
} }
else if (eventData !== undefined) { else if (eventData !== undefined) {
event.data = eventData; event.data = eventData;
} }
if (triggers[event.type] === undefined) {
return; // Check to see if this event should go externally after all triggering and bubbling is done
} var scheduledForExternal = event.scheduleForExternal();
if (triggers[event.type] !== undefined) {
// Call all listeners // Call all listeners
for (var i = 0; i < triggers[event.type].length; i++) { for (var i = 0; i < triggers[event.type].length; i++) {
triggers[event.type][i].listener.call(triggers[event.type][i].thisArg, event); triggers[event.type][i].listener.call(triggers[event.type][i].thisArg, event);
} }
}
if (triggers['*'] !== undefined) {
// Call all * listeners
for (var i = 0; i < triggers['*'].length; i++) {
triggers['*'][i].listener.call(triggers['*'][i].thisArg, event);
}
}
// Bubble // Bubble
if (event.getBubbles() && self.parent instanceof H5P.EventDispatcher && typeof self.parent.trigger === 'function') { if (event.getBubbles() && self.parent instanceof H5P.EventDispatcher && typeof self.parent.trigger === 'function') {
self.parent.trigger(event); self.parent.trigger(event);
} }
if (scheduledForExternal) {
H5P.externalDispatcher.trigger(event);
}
}; };
} }

View File

@ -6,7 +6,7 @@ var H5P = H5P || {};
* @class * @class
*/ */
H5P.XAPIEvent = function() { H5P.XAPIEvent = function() {
H5P.Event.call(this, 'xAPI', {'statement': {}}, {bubbles: true}); H5P.Event.call(this, 'xAPI', {'statement': {}}, {bubbles: true, external: true});
}; };
H5P.XAPIEvent.prototype = Object.create(H5P.Event.prototype); H5P.XAPIEvent.prototype = Object.create(H5P.Event.prototype);
@ -87,8 +87,8 @@ H5P.XAPIEvent.prototype.setObject = function(instance) {
} }
} }
}; };
if (instance.uuid) { if (instance.subContentId) {
this.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-uuid'] = instance.uuid; this.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-subContentId'] = instance.subContentId;
// Don't set titles on main content, title should come from publishing platform // Don't set titles on main content, title should come from publishing platform
if (typeof instance.getH5PTitle === 'function') { if (typeof instance.getH5PTitle === 'function') {
this.data.statement.object.definition.name = { this.data.statement.object.definition.name = {
@ -112,8 +112,8 @@ H5P.XAPIEvent.prototype.setObject = function(instance) {
* @param {object} instance - the H5P instance * @param {object} instance - the H5P instance
*/ */
H5P.XAPIEvent.prototype.setContext = function(instance) { H5P.XAPIEvent.prototype.setContext = function(instance) {
if (instance.parent && (instance.parent.contentId || instance.parent.uuid)) { if (instance.parent && (instance.parent.contentId || instance.parent.subContentId)) {
var parentId = instance.parent.uuid === undefined ? instance.parent.contentId : instance.parent.uuid; var parentId = instance.parent.subContentId === undefined ? instance.parent.contentId : instance.parent.subContentId;
this.data.statement.context = { this.data.statement.context = {
"contextActivities": { "contextActivities": {
"parent": [ "parent": [
@ -179,8 +179,8 @@ H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) {
var xAPIId; var xAPIId;
if (instance.contentId && H5PIntegration && H5PIntegration.contents) { if (instance.contentId && H5PIntegration && H5PIntegration.contents) {
xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url; xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url;
if (instance.uuid) { if (instance.subContentId) {
xAPIId += '?uuid=' + instance.uuid; xAPIId += '?subContentId=' + instance.subContentId;
} }
} }
return xAPIId; return xAPIId;

View File

@ -4,7 +4,7 @@ var H5P = H5P || {};
H5P.externalDispatcher = new H5P.EventDispatcher(); H5P.externalDispatcher = new H5P.EventDispatcher();
if (H5P.isFramed && H5P.externalEmbed !== true) { if (H5P.isFramed && H5P.externalEmbed !== true) {
H5P.externalDispatcher.on('xAPI', window.top.H5P.externalDispatcher.trigger); H5P.externalDispatcher.on('*', window.top.H5P.externalDispatcher.trigger);
} }
// EventDispatcher extensions // EventDispatcher extensions