UNPKG

event-mixer

Version:
125 lines (113 loc) 4.78 kB
// helper methods var cap = (s) => s.slice(0,1).toUpperCase() + s.slice(1); var map = (v,f) => [].concat(v).map(f); exports.mixer = function(target={}, emitter={}) { var events = {}, targetFns = ['on', 'off']; // create new event handler var create = (name, data) => { var cname = cap(name); // add on/off functions to target for this event targetFns.forEach(n => target[n + cname] = function(f) { return this[n](name, f); }); // add fire function to emitter for this event emitter['fire' + cname] = function(d) { return this.fire(name, d); }; // add event handler return events[name] = exports.handler(target, name, data); }; // clear named event handler var destroy = (name) => { var cname = cap(name), handler = events[name]; // clear and remove event handler events[name].clear(); delete events[name]; // remove on/off functions from target for this event targetFns.forEach(n => delete target[n + cname]); // remove fire function from emitter for this event delete emitter['fire' + cname]; return handler; }; var methods = { // create/register a new event for target create(n, d) { return create(n, d); }, // destroy/unregister event for target destroy(n) { return destroy(n); }, // return the emitter for this event manager emitter() { return emitter; }, // return the named event event(n) { return events[n]; }, // fire the named event fire(n, d) { return events[n].fire(d); }, // is the named event registered? has(n) { return events[n] ? true : false; }, // return the names of all registered events names() { return Object.keys(events); }, // remove listener(s) for named event(s) off(n, f) { map(n, x => events[x].remove(f)); return this; }, // add listener(s) for named event(s) on(n, f) { map(n, x => events[x].append(f)); return this; }, // return the target of this event manager target() { return target; } }; // add on/off methods to target targetFns.forEach(n => target[n] = methods[n]); // add fire method to emitter emitter.fire = methods.fire; return methods; }; exports.handler = function(target, name, hdata) { var listeners = []; var fire = (idata) => { // should the result of this event (if any) be allowed? var allow = true; // event data - invocation data overwrites handler data var data = Object.assign({}, hdata, idata); for (var i=0;i<listeners.length;i++) { // call listener with an 'event object' var rtn = listeners[i]({ target, name, data }) || {}; // listener can indicate loss of interest in this event if (rtn.remove) { listeners.splice(i, 1); i--; } // listener can indicate a desire to prevent whatever comes next if (rtn.prevent) allow = false; // listener can end notifications if (rtn.stop) break; } return allow; }; var methods = { // append listener(s) add(f) { return this.append(f); }, // add listener(s) to end of list append(f) { map(f, this.push); return this; }, // returns the listener at the given index at(i) { return i >= 0 && i < listeners.length ? listeners[i] : null; }, // remove all listeners clear() { listeners = []; return this; }, // return the number of listeners for this event count() { return listeners.length; }, // removes and returns the listener at index cut(i) { return i >= 0 && i < listeners.length ? listeners.splice(i, 1)[0] : null; }, // filter/change the listener list each(m) { [...listeners].reduce((a,l,i) => this.push(m(l,i)), listeners = []); return this; }, // is the given function a listener on this event? has(f) { return listeners.indexOf(f) >= 0; }, // return the index of a given listener indexOf(f,s) { return listeners.indexOf(f,s); }, // trigger this event (with data) fire(d) { return fire(d); }, // add listener(s) to beginning of list prepend(f) { [].concat(f).reverse().map(this.unshift); return this; }, // add last listener push(f) { return typeof f === 'function' && listeners.push(f); }, // remove listener(s) remove(f) { map(f, m => this.cut(listeners.indexOf(m))); return this; }, // add first listener unshift(f) { return typeof f === 'function' && listeners.unshift(f); } }; return methods; };