mirror of
https://github.com/Tonejs/Tone.js
synced 2024-12-28 12:33:12 +00:00
125 lines
3.3 KiB
TypeScript
125 lines
3.3 KiB
TypeScript
import { Tone } from "../Tone";
|
|
import { isUndef } from "./TypeCheck";
|
|
|
|
export interface EmitterEventObject {
|
|
[event: string]: Array<(...args: any[]) => void>;
|
|
}
|
|
|
|
/**
|
|
* Emitter gives classes which extend it
|
|
* the ability to listen for and emit events.
|
|
* Inspiration and reference from Jerome Etienne's [MicroEvent](https://github.com/jeromeetienne/microevent.js).
|
|
* MIT (c) 2011 Jerome Etienne.
|
|
* @category Core
|
|
*/
|
|
export class Emitter<EventType extends string = string> extends Tone {
|
|
|
|
readonly name: string = "Emitter";
|
|
|
|
/**
|
|
* Private container for the events
|
|
*/
|
|
private _events?: EmitterEventObject;
|
|
|
|
/**
|
|
* Bind a callback to a specific event.
|
|
* @param event The name of the event to listen for.
|
|
* @param callback The callback to invoke when the event is emitted
|
|
*/
|
|
on(event: EventType, callback: (...args: any[]) => void): this {
|
|
// split the event
|
|
const events = event.split(/\W+/);
|
|
events.forEach(eventName => {
|
|
if (isUndef(this._events)) {
|
|
this._events = {};
|
|
}
|
|
if (!this._events.hasOwnProperty(eventName)) {
|
|
this._events[eventName] = [];
|
|
}
|
|
this._events[eventName].push(callback);
|
|
});
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Bind a callback which is only invoked once
|
|
* @param event The name of the event to listen for.
|
|
* @param callback The callback to invoke when the event is emitted
|
|
*/
|
|
once(event: EventType, callback: (...args: any[]) => void): this {
|
|
const boundCallback = (...args: any[]) => {
|
|
// invoke the callback
|
|
callback(...args);
|
|
// remove the event
|
|
this.off(event, boundCallback);
|
|
};
|
|
this.on(event, boundCallback);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Remove the event listener.
|
|
* @param event The event to stop listening to.
|
|
* @param callback The callback which was bound to the event with Emitter.on.
|
|
* If no callback is given, all callbacks events are removed.
|
|
*/
|
|
off(event: EventType, callback?: (...args: any[]) => void): this {
|
|
const events = event.split(/\W+/);
|
|
events.forEach(eventName => {
|
|
if (isUndef(this._events)) {
|
|
this._events = {};
|
|
}
|
|
if (this._events.hasOwnProperty(eventName)) {
|
|
if (isUndef(callback)) {
|
|
this._events[eventName] = [];
|
|
} else {
|
|
const eventList = this._events[eventName];
|
|
for (let i = eventList.length - 1; i >= 0; i--) {
|
|
if (eventList[i] === callback) {
|
|
eventList.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Invoke all of the callbacks bound to the event
|
|
* with any arguments passed in.
|
|
* @param event The name of the event.
|
|
* @param args The arguments to pass to the functions listening.
|
|
*/
|
|
emit(event, ...args: any[]): this {
|
|
if (this._events) {
|
|
if (this._events.hasOwnProperty(event)) {
|
|
const eventList = this._events[event].slice(0);
|
|
for (let i = 0, len = eventList.length; i < len; i++) {
|
|
eventList[i].apply(this, args);
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Add Emitter functions (on/off/emit) to the object
|
|
*/
|
|
static mixin(constr: any): void {
|
|
// instance._events = {};
|
|
["on", "once", "off", "emit"].forEach(name => {
|
|
const property = Object.getOwnPropertyDescriptor(Emitter.prototype, name) as PropertyDescriptor;
|
|
Object.defineProperty(constr.prototype, name, property);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Clean up
|
|
*/
|
|
dispose(): this {
|
|
super.dispose();
|
|
this._events = undefined;
|
|
return this;
|
|
}
|
|
}
|