Last active
February 8, 2018 13:14
-
-
Save Maxstupo/e81ec2f35f2f303d1ee5b725ae6533a9 to your computer and use it in GitHub Desktop.
A event system to provide event handling.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* The EventSystem provides basic event handling. | |
* | |
* A basic example: | |
* <pre><code> | |
* let es = new EventSystem(); | |
* | |
* let listenerId = es.on('myEvent', function() { // Register a new event listener for the event 'myEvent'. | |
* console.log('Hello World!!'); | |
* }); | |
* | |
* es.emit('myEvent'); // Emit the 'myEvent' event. | |
* </code></pre> | |
* | |
* @constructor | |
* @param {object} [injectInto] The object to inject {@link EventSystem#on() on()}, {@link EventSystem#off() off()} methods into. If this is specified, event listeners will have this context instead of the instance of the event system. | |
* @param {boolean} [includeEmit=false] If true the {@link EventSystem#emit() emit()} method will also be injected into the provided object. | |
*/ | |
const EventSystem = function (injectInto, includeEmit) { | |
let evtQueue = {}; | |
let idSeq = 0; | |
const _this = this; | |
/** | |
* Fire an event. This will invoke all callbacks listening for this event. | |
* @param {string} eventName The name of the event. If 'falsey', undefined will be returned. | |
* @param {...*} [args] Parameters that will be passed to the event listeners. | |
* @returns {object|undefined} Undefined if <code>eventName</code> is 'falsey', | |
* otherwise returns the injected object provided by the {@link EventSystem constructor}, if not provided the {@link EventSystem} instance will be returned. | |
* | |
*/ | |
this.emit = function (eventName, ...args) { | |
if (!eventName) return; | |
let queue = evtQueue[eventName]; | |
if (queue) { | |
queue.events.forEach(event => { | |
event.remove = event.cb.apply(injectInto || _this, args); | |
}); | |
queue.events = queue.events.filter(event => event.remove); | |
} | |
return injectInto || _this; | |
}; | |
/** | |
* Add a event listener to a specific event. | |
* @param {string} eventName The number of the event to add this listener to. | |
* @param {function} callback The callback that will be invoked when the specified event occurs. Returning true in the callback will remove the listener. | |
* @returns {number|undefined} The id of this event listener. Useful for removing this listener via the {@link EventSystem#off() off()} method. If either specified parameter is 'falsey' undefined will be returned. | |
*/ | |
this.on = function (eventName, callback) { | |
if (!callback || !eventName) | |
return; | |
let queue = evtQueue[eventName] || {events: []}; | |
queue.events.push({ | |
id: ++idSeq, | |
remove: false, | |
cb: callback | |
}); | |
evtQueue[eventName] = queue; | |
return idSeq; | |
}; | |
/** | |
* Removes a specific listener when using a listener id, all listeners of a event if parameter is an event name, or all listeners of all events if no parameter is provided (undefined). | |
* @param {string|number|undefined [eventNameOrId] Using an event name it will remove all listeners for that event. Providing an id returned by {@link EventSystem#on() on()} can be used to remove a specific listener. All event listeners can be removed by using a 'falsey' value. | |
* @returns {object|undefined} The injected object provided by the {@link EventSystem constructor}, if not provided the {@link EventSystem} instance will be returned. | |
*/ | |
this.off = function (eventNameOrId) { | |
if (!eventNameOrId) { | |
idSeq = 0; | |
evtQueue = {}; | |
} else if (typeof eventNameOrId === 'string') { | |
delete evtQueue[eventNameOrId]; | |
} else if (typeof eventNameOrId === 'number') { | |
Object.keys(evtQueue).forEach(key => { | |
let queue = evtQueue[key]; | |
queue.events.forEach(event => { | |
if (event.id === eventNameOrId) | |
event.remove = true; | |
}); | |
queue.events = queue.events.filter(event => !event.remove); | |
if (queue.events.length === 0) | |
delete evtQueue[key]; | |
}); | |
} | |
return injectInto || _this; | |
}; | |
if (injectInto) { | |
Object.keys(_this).forEach(key => { | |
if (!includeEmit || (includeEmit && key !== 'emit')) | |
injectInto[key] = _this[key]; | |
}); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment