1var H5P = window.H5P = window.H5P || {}; 2 3/** 4 * The Event class for the EventDispatcher. 5 * 6 * @class 7 * @param {string} type 8 * @param {*} data 9 * @param {Object} [extras] 10 * @param {boolean} [extras.bubbles] 11 * @param {boolean} [extras.external] 12 */ 13H5P.Event = function (type, data, extras) { 14 this.type = type; 15 this.data = data; 16 var bubbles = false; 17 18 // Is this an external event? 19 var external = false; 20 21 // Is this event scheduled to be sent externally? 22 var scheduledForExternal = false; 23 24 if (extras === undefined) { 25 extras = {}; 26 } 27 if (extras.bubbles === true) { 28 bubbles = true; 29 } 30 if (extras.external === true) { 31 external = true; 32 } 33 34 /** 35 * Prevent this event from bubbling up to parent 36 */ 37 this.preventBubbling = function () { 38 bubbles = false; 39 }; 40 41 /** 42 * Get bubbling status 43 * 44 * @returns {boolean} 45 * true if bubbling false otherwise 46 */ 47 this.getBubbles = function () { 48 return bubbles; 49 }; 50 51 /** 52 * Try to schedule an event for externalDispatcher 53 * 54 * @returns {boolean} 55 * true if external and not already scheduled, otherwise false 56 */ 57 this.scheduleForExternal = function () { 58 if (external && !scheduledForExternal) { 59 scheduledForExternal = true; 60 return true; 61 } 62 return false; 63 }; 64}; 65 66/** 67 * Callback type for event listeners. 68 * 69 * @callback H5P.EventCallback 70 * @param {H5P.Event} event 71 */ 72 73H5P.EventDispatcher = (function () { 74 75 /** 76 * The base of the event system. 77 * Inherit this class if you want your H5P to dispatch events. 78 * 79 * @class 80 * @memberof H5P 81 */ 82 function EventDispatcher() { 83 var self = this; 84 85 /** 86 * Keep track of listeners for each event. 87 * 88 * @private 89 * @type {Object} 90 */ 91 var triggers = {}; 92 93 /** 94 * Add new event listener. 95 * 96 * @throws {TypeError} 97 * listener must be a function 98 * @param {string} type 99 * Event type 100 * @param {H5P.EventCallback} listener 101 * Event listener 102 * @param {Object} [thisArg] 103 * Optionally specify the this value when calling listener. 104 */ 105 this.on = function (type, listener, thisArg) { 106 if (typeof listener !== 'function') { 107 throw TypeError('listener must be a function'); 108 } 109 110 // Trigger event before adding to avoid recursion 111 self.trigger('newListener', {'type': type, 'listener': listener}); 112 113 var trigger = {'listener': listener, 'thisArg': thisArg}; 114 if (!triggers[type]) { 115 // First 116 triggers[type] = [trigger]; 117 } 118 else { 119 // Append 120 triggers[type].push(trigger); 121 } 122 }; 123 124 /** 125 * Add new event listener that will be fired only once. 126 * 127 * @throws {TypeError} 128 * listener must be a function 129 * @param {string} type 130 * Event type 131 * @param {H5P.EventCallback} listener 132 * Event listener 133 * @param {Object} thisArg 134 * Optionally specify the this value when calling listener. 135 */ 136 this.once = function (type, listener, thisArg) { 137 if (!(listener instanceof Function)) { 138 throw TypeError('listener must be a function'); 139 } 140 141 var once = function (event) { 142 self.off(event.type, once); 143 listener.call(this, event); 144 }; 145 146 self.on(type, once, thisArg); 147 }; 148 149 /** 150 * Remove event listener. 151 * If no listener is specified, all listeners will be removed. 152 * 153 * @throws {TypeError} 154 * listener must be a function 155 * @param {string} type 156 * Event type 157 * @param {H5P.EventCallback} listener 158 * Event listener 159 */ 160 this.off = function (type, listener) { 161 if (listener !== undefined && !(listener instanceof Function)) { 162 throw TypeError('listener must be a function'); 163 } 164 165 if (triggers[type] === undefined) { 166 return; 167 } 168 169 if (listener === undefined) { 170 // Remove all listeners 171 delete triggers[type]; 172 self.trigger('removeListener', type); 173 return; 174 } 175 176 // Find specific listener 177 for (var i = 0; i < triggers[type].length; i++) { 178 if (triggers[type][i].listener === listener) { 179 triggers[type].splice(i, 1); 180 self.trigger('removeListener', type, {'listener': listener}); 181 break; 182 } 183 } 184 185 // Clean up empty arrays 186 if (!triggers[type].length) { 187 delete triggers[type]; 188 } 189 }; 190 191 /** 192 * Try to call all event listeners for the given event type. 193 * 194 * @private 195 * @param {string} Event type 196 */ 197 var call = function (type, event) { 198 if (triggers[type] === undefined) { 199 return; 200 } 201 202 // Clone array (prevents triggers from being modified during the event) 203 var handlers = triggers[type].slice(); 204 205 // Call all listeners 206 for (var i = 0; i < handlers.length; i++) { 207 var trigger = handlers[i]; 208 var thisArg = (trigger.thisArg ? trigger.thisArg : this); 209 trigger.listener.call(thisArg, event); 210 } 211 }; 212 213 /**
214 * Dispatch event. 215 * 216 * @param {string|H5P.Event} event 217 * Event object or event type as string 218 * @param {*} [eventData] 219 * Custom event data(used when event type as string is used as first 220 * argument). 221 * @param {Object} [extras] 222 * @param {boolean} [extras.bubbles] 223 * @param {boolean} [extras.external] 224 */ 225 this.trigger = function (event, eventData, extras) { 226 if (event === undefined) { 227 return; 228 } 229 if (event instanceof String || typeof event === 'string') { 230 event = new H5P.Event(event, eventData, extras); 231 } 232 else if (eventData !== undefined) { 233 event.data = eventData; 234 } 235 236 // Check to see if this event should go externally after all triggering and bubbling is done 237 var scheduledForExternal = event.scheduleForExternal(); 238 239 // Call all listeners 240 call.call(this, event.type, event); 241 242 // Call all * listeners 243 call.call(this, '*', event); 244 245 // Bubble 246 if (event.getBubbles() && self.parent instanceof H5P.EventDispatcher && 247 (self.parent.trigger instanceof Function || typeof self.parent.trigger === 'function')) { 248 self.parent.trigger(event); 249 } 250 251 if (scheduledForExternal) { 252 H5P.externalDispatcher.trigger.call(this, event); 253 } 254 }; 255 } 256 257 return EventDispatcher; 258})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.