import {subscriberCollection} from 'aurelia-binding'; import {TaskQueue} from 'aurelia-task-queue'; /** * An implementation of Aurelia's Observer interface that is used to back bindable properties defined on a behavior. */ @subscriberCollection() export class BehaviorPropertyObserver { /** @internal */ taskQueue: TaskQueue; /** @internal */ obj: object; /** @internal */ propertyName: string; /** @internal */ notqueued: boolean; /** @internal */ publishing: boolean; /** @internal */ selfSubscriber: Function; /** @internal */ private currentValue: any; /** @internal */ private oldValue: any; /** * Creates an instance of BehaviorPropertyObserver. * @param taskQueue The task queue used to schedule change notifications. * @param obj The object that the property is defined on. * @param propertyName The name of the property. * @param selfSubscriber The callback function that notifies the object which defines the properties, if present. * @param initialValue The initial value of the property. */ constructor(taskQueue: TaskQueue, obj: object, propertyName: string, selfSubscriber: Function, initialValue?: any) { this.taskQueue = taskQueue; this.obj = obj; this.propertyName = propertyName; this.notqueued = true; this.publishing = false; this.selfSubscriber = selfSubscriber; this.currentValue = this.oldValue = initialValue; } /** * Gets the property's value. */ getValue(): any { return this.currentValue; } /** * Sets the property's value. * @param newValue The new value to set. */ setValue(newValue: any): void { let oldValue = this.currentValue; if (!Object.is(newValue, oldValue)) { this.oldValue = oldValue; this.currentValue = newValue; if (this.publishing && this.notqueued) { if (this.taskQueue.flushing) { this.call(); } else { this.notqueued = false; this.taskQueue.queueMicroTask(this); } } } } /** * Invoked by the TaskQueue to publish changes to subscribers. */ call(): void { let oldValue = this.oldValue; let newValue = this.currentValue; this.notqueued = true; if (Object.is(newValue, oldValue)) { return; } if (this.selfSubscriber) { this.selfSubscriber(newValue, oldValue); } this.callSubscribers(newValue, oldValue); this.oldValue = newValue; } // eslint-disable-next-line @typescript-eslint/no-unused-vars callSubscribers(newValue: any, oldValue: any) { throw new Error('Method not implemented.'); } /** * Subscribes to the observerable. * @param context A context object to pass along to the subscriber when it's called. * @param callable A function or object with a "call" method to be invoked for delivery of changes. */ subscribe(context: any, callable: Function): void { this.addSubscriber(context, callable); } // eslint-disable-next-line @typescript-eslint/no-unused-vars addSubscriber(context: any, callable: Function) { throw new Error('Method not implemented.'); } /** * Unsubscribes from the observerable. * @param context The context object originally subscribed with. * @param callable The callable that was originally subscribed with. */ unsubscribe(context: any, callable: Function): void { this.removeSubscriber(context, callable); } // eslint-disable-next-line @typescript-eslint/no-unused-vars removeSubscriber(context: any, callable: Function) { throw new Error('Method not implemented.'); } }