/* eslint-disable no-restricted-syntax */
/**
* this module contains helper functions for managing events
* @author Aamir khan
* @module utils/events/eventManager
*/
/**
* Create a new `Event Emitter`.
* @constructor
* @api public
*/
function EventManager() {}
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api public
*/
EventManager.extend = function extend(obj, name) {
// eslint-disable-next-line guard-for-in
for (const key in EventManager.prototype) {
// eslint-disable-next-line no-param-reassign
obj[key] = EventManager.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {EventManager}
* @api public
*/
EventManager.prototype.addEvent = function addEvent(event, fn) {
if(!event){
throw new Error("event name is required");
}
this.log("regestring event", event);
this.callbacks = this.callbacks || {};
(this.callbacks['$' + event] = this.callbacks['$' + event] || [])
.push(fn);
return () => this.removeEvent(event, fn);
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {EventManager}
* @api public
*/
EventManager.prototype.addEventOnce = function addEventOnce(event, fn) {
this.log(`adding ${event} for once`);
function on() {
this.removeEvent(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.addEvent(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {EventManager}
* @api public
*/
EventManager.prototype.removeEvent = function removeEvent(event, fn) {
this.log("removing event", event);
this.callbacks = this.callbacks || {};
// all
if (arguments.length === 0) {
this.callbacks = {};
return this;
}
// specific event
const callbacks = this.callbacks['$' + event];
if (!callbacks) return this;
// remove all handlers
if (arguments.length === 1) {
delete this.callbacks['$' + event];
return this;
}
// remove specific handler
let cb;
for (let i = 0; i < callbacks.length; i += 1) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
// Remove event specific arrays for event types that no
// one is subscribed for to avoid memory leak.
if (callbacks.length === 0) {
delete this.callbacks['$' + event];
}
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {EventManager}
*/
EventManager.prototype.emit = function emit(event) {
this.callbacks = this.callbacks || {};
const args = new Array(arguments.length - 1);
let callbacks = this.callbacks['$' + event];
this.log("emit", event, args, callbacks);
for (let i = 1; i < arguments.length; i += 1) {
// eslint-disable-next-line prefer-rest-params
args[i - 1] = arguments[i];
}
if (callbacks) {
callbacks = callbacks.slice(0);
// eslint-disable-next-line no-plusplus
for (let i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
EventManager.prototype.listeners = function listeners(event) {
this.callbacks = this.callbacks || {};
return this.callbacks['$' + event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
EventManager.prototype.hasListeners = function hasListeners(event) {
return !!this.listeners(event).length;
};
export default EventManager;