UNPKG

awv3

Version:
157 lines (140 loc) 5.5 kB
export default class Events { constructor() { this._callbacks = undefined; this._inspectors = undefined; } once(type, callback) { this.on(type, callback, true); } onFirst(type, callback) { this.on(type, callback, false, 1); } onLast(type, callback) { this.on(type, callback, false, -1); } on(arg1 = {}, arg2 = undefined, remove = false, priority = undefined) { if (!this._callbacks) this._callbacks = {}; if (Array.isArray(arg1) || typeof arg1 === 'string' && typeof arg2 === 'function') { // Types & Callback let types = Array.isArray(arg1) ? arg1 : [arg1]; for (let type of types) { let listeners = this._callbacks[type]; if (!listeners) listeners = this._callbacks[type] = []; if (listeners.indexOf(arg2) < 0) { arg2.remove = remove; if (priority) arg2.priority = priority; listeners.push(arg2); listeners.sort((a, b) => b.priority || 0 - a.priority || 0); if (this._inspectors) { for (let inspector of this._inspectors) inspector({ action: 'Add', type, callback: arg2 }); } } } } else if (typeof arg1 === 'object' && arg2 === undefined) { // Array of 'Type: Callback' pairs for (let key in arg1) { let callback = arg1[key]; typeof callback === 'function' && this.on(key, callback, remove, priority); } } return this; } inspect(callback) { if (!this._inspectors) this._inspectors = []; this._inspectors.push(callback); } removeListener(types, callback) { if (!Array.isArray(types) && typeof types === 'object' && callback === undefined) { // Object of 'Type: Callback' for (let [type, callback] of Object.entries(types)) this.removeListener(type, callback); return this; } if (!this._callbacks) this._callbacks = {}; types = Array.isArray(types) ? types : [types]; for (let type of types) { let listeners = this._callbacks[type]; if (!listeners) continue; if (!callback) { delete this._callbacks[type]; if (this._inspectors) { for (let inspector of this._inspectors) inspector({ action: 'Remove', type, callback: undefined }); } } else { let index = listeners.indexOf(callback); index > -1 && listeners.splice(index, 1); if (this._inspectors) { for (let inspector of this._inspectors) inspector({ action: 'Remove', type, callback }); } } } return this; } removeListeners() { this._callbacks = undefined; } removeInspectors() { this._inspectors = undefined; } emit(type, ...args) { let sequence = Promise.resolve(); if (!this._callbacks) this._callbacks = {}; let listeners = this._callbacks[type]; if (!!listeners) { for (let listener of listeners) { sequence = sequence.then(_ => { listener.remove && this.removeListener(type, listener); return listener.call(this, ...args); }); } } return sequence; } bubble(type, ...args) { let sequence = Promise.resolve(); if (!this._callbacks) this._callbacks = {}; let listeners = this._callbacks[type]; if (!!listeners) { for (let listener of listeners) sequence = sequence.then(_ => listener.call(this, ...args)); } else if (!!this.parent) { // No listener found, just bubble up ... this.parent.bubble(type, ...args); } return sequence; } findListener(type) { if (!this._callbacks) this._callbacks = {}; let listeners = this._callbacks[type]; if (!!listeners) { return this; } else if (!!this.parent) { // No listener found, just bubble up ... return this.parent.find(type); } return undefined; } hasListener(type, callback = undefined) { if (!this._callbacks) this._callbacks = {}; let listener = this._callbacks[type]; return !!listener && (!callback || callback === listener); } static mixin(object, handlers = null) { object.hasListener = Events.prototype.hasListener; object.on = Events.prototype.on; object.once = Events.prototype.once; object.onFirst = Events.prototype.onFirst; object.onLast = Events.prototype.onLast; object.inspect = Events.prototype.inspect; object.removeListener = Events.prototype.removeListener; object.removeListeners = Events.prototype.removeListeners; object.removeInspectors = Events.prototype.removeInspectors; object.emit = Events.prototype.emit; object.bubble = Events.prototype.bubble; object.findListener = Events.prototype.findListener; if (handlers) object.on.bind(object)(handlers); } }