avocado-old/packages/core/event-emitter.js

122 lines
3.0 KiB
JavaScript
Raw Normal View History

2019-05-01 20:03:26 -05:00
function createListener(fn, that, type, once) {
2019-03-17 23:45:48 -05:00
return {
2019-05-01 20:03:26 -05:00
fn, that, type, once,
2019-03-17 23:45:48 -05:00
bound: that ? fn.bind(that) : fn,
}
}
export function EventEmitterMixin(Superclass) {
return class EventEmitter extends Superclass {
constructor(...args) {
super(...args);
2019-05-01 20:03:26 -05:00
this.$$events = Object.create(null);
2019-03-17 23:45:48 -05:00
}
2019-05-02 21:15:22 -05:00
addListener(typesOrType, fn, that) {
return this.on(typesOrType, fn, that);
}
2019-03-17 23:45:48 -05:00
// Notify ALL the listeners!
2019-05-01 20:03:26 -05:00
emit(type, ...args) {
const typeListeners = this.$$events[type];
if (typeListeners && typeListeners.length > 0) {
this.emitToListeners(typeListeners, args);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
}
2019-03-17 23:45:48 -05:00
2019-05-01 20:03:26 -05:00
emitToListeners(listeners, args) {
2019-04-17 00:05:12 -05:00
for (let i = 0; i < listeners.length; ++i) {
2019-05-01 20:03:26 -05:00
const {once, type, fn, bound, that} = listeners[i];
// Remove if only once.
2019-03-17 23:45:48 -05:00
if (once) {
2019-05-01 20:03:26 -05:00
this.offSingleEvent(type, fn);
2019-03-17 23:45:48 -05:00
}
// Fast path...
2019-05-01 20:03:26 -05:00
if (0 === args.length) {
2019-03-17 23:45:48 -05:00
bound()
}
2019-05-01 20:03:26 -05:00
else if (1 === args.length) {
bound(args[0]);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
else if (2 === args.length) {
bound(args[0], args[1]);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
else if (3 === args.length) {
bound(args[0], args[1], args[2]);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
else if (4 === args.length) {
bound(args[0], args[1], args[2], args[3]);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
else if (5 === args.length) {
bound(args[0], args[1], args[2], args[3], args[4]);
2019-03-17 23:45:48 -05:00
}
// Slow path...
else {
2019-05-02 21:15:13 -05:00
fn.apply(that, args);
2019-03-17 23:45:48 -05:00
}
}
}
2019-04-07 12:04:30 -05:00
off(typesOrType, fn) {
2019-05-01 20:03:26 -05:00
typesOrType = Array.isArray(typesOrType) ? typesOrType : [typesOrType];
for (let i = 0; i < typesOrType.length; i++) {
const type = typesOrType[i];
this.offSingleEvent(type, fn);
}
2019-03-17 23:45:48 -05:00
return this;
}
2019-05-01 20:03:26 -05:00
offSingleEvent(type, fn) {
if ('function' !== typeof fn) {
// Only type.
if (type in this.$$events) {
this.$$events[type] = [];
2019-03-17 23:45:48 -05:00
}
return;
}
2019-05-01 20:03:26 -05:00
// Function.
const lists = [];
if ((type in this.$$events)) {
lists.push(this.$$events);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
const listeners = this.$$events;
listeners[type] = listeners[type].filter((listener) => {
return listener.fn !== fn;
});
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
on(typesOrType, fn, that = undefined) {
this._on(typesOrType, fn, that, false);
2019-03-17 23:45:48 -05:00
return this;
}
2019-04-07 12:00:11 -05:00
_on(typesOrType, fn, that, once) {
2019-05-01 20:03:26 -05:00
typesOrType = Array.isArray(typesOrType) ? typesOrType : [typesOrType];
for (let i = 0; i < typesOrType.length; i++) {
const type = typesOrType[i];
this.onSingleEvent(type, fn, that, once);
}
2019-03-17 23:45:48 -05:00
}
once(types, fn, that = undefined) {
2019-04-07 12:00:11 -05:00
this._on(types, fn, that, true);
2019-03-17 23:45:48 -05:00
return this;
}
2019-05-01 20:03:26 -05:00
onSingleEvent(type, fn, that, once) {
const listener = createListener(fn, that, type, once);
if (!(type in this.$$events)) {
this.$$events[type] = [];
2019-03-17 23:45:48 -05:00
}
this.$$events[type].push(listener);
2019-03-17 23:45:48 -05:00
}
2019-05-01 20:03:26 -05:00
removeListener(...args) {
return this.off(...args);
2019-03-17 23:45:48 -05:00
}
}
}