src/event/target.js
import { reject, filter } from '../helpers/array-helpers';
/*
* EventTarget is an interface implemented by objects that can
* receive events and may have listeners for them.
*
* https://developer.mozilla.org/en-US/docs/Web/API/EventTarget
*/
class EventTarget {
constructor() {
this.listeners = {};
}
/*
* Ties a listener function to an event type which can later be invoked via the
* dispatchEvent method.
*
* @param {string} type - the type of event (ie: 'open', 'message', etc.)
* @param {function} listener - callback function to invoke when an event is dispatched matching the type
* @param {boolean} useCapture - N/A TODO: implement useCapture functionality
*/
addEventListener(type, listener /* , useCapture */) {
if (typeof listener === 'function') {
if (!Array.isArray(this.listeners[type])) {
this.listeners[type] = [];
}
// Only add the same function once
if (filter(this.listeners[type], item => item === listener).length === 0) {
this.listeners[type].push(listener);
}
}
}
/*
* Removes the listener so it will no longer be invoked via the dispatchEvent method.
*
* @param {string} type - the type of event (ie: 'open', 'message', etc.)
* @param {function} listener - callback function to invoke when an event is dispatched matching the type
* @param {boolean} useCapture - N/A TODO: implement useCapture functionality
*/
removeEventListener(type, removingListener /* , useCapture */) {
const arrayOfListeners = this.listeners[type];
this.listeners[type] = reject(arrayOfListeners, listener => listener === removingListener);
}
/*
* Invokes all listener functions that are listening to the given event.type property. Each
* listener will be passed the event as the first argument.
*
* @param {object} event - event object which will be passed to all listeners of the event.type property
*/
dispatchEvent(event, ...customArguments) {
const eventName = event.type;
const listeners = this.listeners[eventName];
if (!Array.isArray(listeners)) {
return false;
}
listeners.forEach(listener => {
if (customArguments.length > 0) {
listener.apply(this, customArguments);
} else {
listener.call(this, event);
}
});
return true;
}
}
export default EventTarget;