export class EventLimit { private lastTriggerValue: T = null; private handlers: Array> = []; public on(limit: T, handler: { (data?: T): void }) { this.handlers.push(new EventLimitHandler(limit, handler)); if (this.lastTriggerValue != null) { this.trigger(this.lastTriggerValue); } } public onSingle(limit: T, handler: { (data?: T): void }) { this.handlers.push(new SingleFireEventLimitHandler(limit, handler)); if (this.lastTriggerValue != null) { this.trigger(this.lastTriggerValue); } } public off(limit: T, handler: { (data?: T): void }) { this.handlers = this.handlers.filter(h => h.handler !== handler && h.limit !== limit); } public allOff() { this.handlers = []; } public trigger = (data?: T) => { if (this.handlers) { this.handlers.slice(0).forEach(h => { if (h.limit <= data && (h.lastTriggerValue < h.limit || h.lastTriggerValue == null)) { h.fire(data); } h.lastTriggerValue = data; }); this.handlers = this.handlers.filter(h => h.isValid()); } this.lastTriggerValue = data; }; } class EventLimitHandler { public lastTriggerValue: T = null; constructor(public limit: T, public handler: { (data?: T): void }) { } public fire(data?: T) { this.handler(data); } public isValid(): boolean { return true; } } class SingleFireEventLimitHandler extends EventLimitHandler { public fired = false; constructor(public limit: T, public handler: { (data?: T): void }) { super(limit, handler); } public fire(data?: T) { if (this.fired == false) { this.handler(data); } this.fired = true } public isValid(): boolean { return this.fired === false; } }