mframejs
Version:
simple framework
154 lines (129 loc) • 5.93 kB
text/typescript
import { tokenize } from './ast/tokenize';
import { generateAST } from './ast/generateAst';
import { ClassPropertyObserverCreator } from './property/classPropertyObserverCreator';
import { PropertyObserverHandler } from './property/propertyObserverHandler';
import { Cache } from '../utils/exported';
import { CONSTANTS, IBindingContext } from '../interface/exported';
import { getCorrectContext } from './contextOfObject';
/**
* creates binding expression by getting tokens from the text
*
*/
export function createBindingExpression(expression: string, _class: IBindingContext, setterClass: PropertyObserverHandler) {
let attributesValues: any[] = [];
let ast;
if (expression) {
if (!setterClass.attributesValues) {
let tokens: any;
let tokenValues: any = [];
let tokenObject: any = [];
if (Cache.expressionMap.has(expression)) {
const cacheX = Cache.expressionMap.get(expression);
ast = (<any>cacheX).ast;
tokens = (<any>cacheX).tokens;
tokenValues = (<any>cacheX).tokenValues;
tokenObject = (<any>cacheX).tokenObject;
} else {
tokens = tokenize(expression);
ast = generateAST(tokens);
let curVal: any = null;
let curObject: any = [];
for (let next = 0; next < tokens.length; next++) {
const tok = tokens[next];
if (tok.type === 'variable') {
if (!curVal) {
curVal = tok.value;
curObject.push(tok.value);
} else {
curVal = curVal + tok.value;
curObject.push(tok.value);
}
} else {
if (tok.type === 'operator' && tok.value === '.') {
if (curVal) {
curVal = curVal + '.';
}
} else {
if (tok.type === 'operator' // support binding to "somevalue.array[0].name"
&& tok.value === '['
&& tokens[next + 2]
&& tokens[next + 2].type === 'operator'
&& tokens[next + 2].value === ']') {
if (curVal) {
curVal = curVal + '[' + tokens[next + 1].value + ']';
}
next = next + 2;
} else {
if (curVal) {
tokenValues.push(curVal);
curVal = null;
tokenObject.push(curObject);
curObject = [];
}
}
}
}
}
if (curVal) {
tokenValues.push(curVal);
tokenObject.push(curObject);
curObject = [];
curVal = null;
}
Cache.expressionMap.set(expression, {
ast: ast,
tokens: tokens,
tokenValues: tokenValues,
tokenObject: tokenObject
});
}
// for each token get the attribute on variables
tokenValues.forEach((tok: any) => {
const newctx = getCorrectContext(tok, _class);
if (typeof tok === 'string'
&& tok[0] !== '$'
&& newctx
&& newctx.__bindingContext
&& newctx.$context.__proto__
&& newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM]
&& newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM][tok]) {
const computedFrom = newctx.$context.__proto__[CONSTANTS.META_COMPUTEDFROM];
computedFrom[tok].attributes.forEach((val: any) => {
if (attributesValues.indexOf(val) === -1) {
attributesValues.push(val);
}
});
} else {
if (attributesValues.indexOf(tok) === -1) {
attributesValues.push(tok);
}
}
});
// set ast to setter
setterClass.setAst(ast);
} else {
attributesValues = setterClass.attributesValues;
}
// for each attribute found
for (let i = 0; i < attributesValues.length; i++) {
const newctx = getCorrectContext(attributesValues[i], _class);
ClassPropertyObserverCreator.create(newctx || _class, attributesValues[i], setterClass);
}
// initiate setter class
setterClass.init();
setterClass.attributesValues = attributesValues;
}
}
/**
* remove binding expression
*
*/
export function removeBindingExpression(text: string, _class: IBindingContext, handlerClass: PropertyObserverHandler) {
if (text && handlerClass.attributesValues) {
const attributesValues = handlerClass.attributesValues;
for (let i = 0; i < attributesValues.length; i++) {
const newctx = getCorrectContext(attributesValues[i], _class);
ClassPropertyObserverCreator.remove(newctx || _class, attributesValues[i], handlerClass);
}
}
}