UNPKG

mframejs

Version:
138 lines (107 loc) 3.33 kB
import { traverseAST, getBehavior } from '../ast/traverseAst'; import { createBindingExpression, removeBindingExpression } from '../createBindingExpression'; import { IListener, IBindingContext } from '../../interface/exported'; import { ContainerBehavior } from '../../container/exported'; /** * Register/creates a property observer with expression * It be called on changes to value of expression * */ export class PropertyObserverHandler { private expression: string; private ast: any; private context: IBindingContext; private observing: boolean; private listener: IListener; private value: any = undefined; private isNew = true; public curBehavior: any; public attributesValues: string[]; constructor(expression: string, listener: IListener) { this.expression = expression; this.listener = listener; } /** * binds observer handler to passed in context * */ public bind(context: IBindingContext) { this.observing = true; this.context = context; createBindingExpression(this.expression, this.context, this); } /** * gets new AST "createNewBindingExpression" * */ public setAst(ast: Object) { this.ast = ast; if (!this.curBehavior) { this.connectBehavior(); } } /** * Sets init value * */ public init() { if (this.isNew) { this.isNew = false; const oldValue = this.value; const newValue = traverseAST(this.ast, this.context); this.value = newValue; this.listenerCall(newValue, oldValue); this.isNew = false; } } /** * connectBehavior * only used for signal * */ public connectBehavior() { const behaviors = getBehavior(this.ast); if (behaviors) { behaviors.forEach((behavior: { name: string, args: any[] }) => { if (behavior.name === 'signal') { const x = ContainerBehavior.findBehavior(behavior.name); if (x) { this.curBehavior = new x(this, behavior.args); } } }); } } /** * Gets called by observer, it then calls the listener * */ public update() { const newValue = traverseAST(this.ast, this.context); const oldValue = this.value; this.value = newValue; this.listenerCall(newValue, oldValue); this.bind(this.context); } public listenerCall(newValue: any, oldValue: any) { if (this.listener) { this.listener.call(newValue, oldValue); } } /** * Unbinds and clears all internals * */ public unbind() { if (this.observing) { removeBindingExpression(this.expression, this.context, this); } // remove this from caller this.listener.caller = null; // remove rest of internals this.observing = false; this.context = null; this.listener = null; this.value = null; } }