UNPKG

mframejs

Version:
199 lines (161 loc) 5.5 kB
import { ArrayObserverHandler } from './arrayObserverHandler'; // use prototype // by doing this instead of object define I only do it once for all arrays const events = ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'sort']; events.forEach((eventX) => { const eventType = Array.prototype[eventX]; Array.prototype[eventX] = function () { const result = eventType.apply(this, arguments); if (this.__array_observer__class) { this.__array_observer__class.check(arguments, eventX); } return result; }; }); /** * this is used to set observer on a array on a class/object * */ export class ClassArrayObserver { private callers: ArrayObserverHandler[]; private c1: ArrayObserverHandler; private c2: ArrayObserverHandler; private c3: ArrayObserverHandler; private c4: ArrayObserverHandler; private c5: ArrayObserverHandler; private internalEvents: any[] = []; private timer: any = null; constructor( private _class: Object, private key: string ) { if (typeof this._class === 'object') { this.observe(); } } /** * subscribe * */ public subscribe(caller: ArrayObserverHandler) { if (this.c1 !== caller && this.c2 !== caller && this.c3 !== caller && this.c4 !== caller && this.c5 !== caller) { if (!this.c1) { this.c1 = caller; } else { if (!this.c2) { this.c2 = caller; } else { if (!this.c3) { this.c3 = caller; } else { if (!this.c4) { this.c4 = caller; } else { if (!this.c5) { this.c5 = caller; } else { if (!this.callers) { this.callers = []; } if (this.callers.indexOf(caller) === -1) { this.callers.push(caller); } } } } } } } } /** * unsubscribe * */ public unsubscribe(caller: ArrayObserverHandler) { if (this.c1 === caller) { this.c1 = null; } if (this.c2 === caller) { this.c2 = null; } if (this.c3 === caller) { this.c3 = null; } if (this.c4 === caller) { this.c4 = null; } if (this.c5 === caller) { this.c5 = null; } if (this.callers && this.callers.indexOf(caller) !== -1) { this.callers.splice(this.callers.indexOf(caller), 1); } } public check(args: any, event: any) { clearTimeout(this.timer); this.timer = 0; // push event this.internalEvents.push({ event: event, args: args }); this.timer = setTimeout(() => { if (this.c1) { const cc1 = this.c1; this.c1 = undefined; cc1.update(this.internalEvents); } if (this.c2) { const cc2 = this.c2; this.c2 = undefined; cc2.update(this.internalEvents); } if (this.c3) { const cc3 = this.c3; this.c3 = undefined; cc3.update(this.internalEvents); } if (this.c4) { const cc4 = this.c4; this.c4 = undefined; cc4.update(this.internalEvents); } if (this.c5) { const cc5 = this.c5; this.c5 = undefined; cc5.update(this.internalEvents); } if (this.callers && this.callers.length > 0) { const calls = this.callers.slice(); this.callers = []; calls.forEach((call: any) => { call.update(this.internalEvents); }); } this.internalEvents = null; this.internalEvents = []; // check for length prop #13 // needs to be tested I dont break something else... if (this._class[this.key] && this._class[this.key].__observer) { for (const k in this._class[this.key].__observer) { if (this._class[this.key].__observer[k] && this._class[this.key].__observer[k].forceUpdate) { this._class[this.key].__observer[k].forceUpdate(); } } } }, 0); } /** * observe * */ private observe() { if (this._class[this.key] && Array.isArray(this._class[this.key])) { Object.defineProperty(this._class[this.key], '__array_observer__class', { writable: true, configurable: true, value: this }); } } }