pragma-views2
Version:
106 lines (87 loc) • 3.8 kB
JavaScript
import {BehaviourBase} from "./behaviour-base.js";
import {addTriggers, removeTriggers, getObjOnPath, createFunctionForExpression, removeFunctionForExpression } from "../binding/observers.js";
import {domCaseMap} from "../binding/document-casemap.js";
import {setValueOnPath} from "../objectpath-helper.js";
import {inflateAttribute} from "../template-inflator.js";
import {postProcessPropertyChange} from "./behaviour-postprocess.js";
export class PropertyBehaviour extends BehaviourBase {
static create(attr, bindingContext, property) {
if (attr.nodeValue.indexOf("#") != -1) {
return inflateAttribute(attr, bindingContext);
}
const result = new PropertyBehaviour();
result._attribute = attr;
result._context = bindingContext;
result._attrName = property;
result._expression = attr.nodeValue;
result.connectedCallback(attr.ownerElement);
return result;
}
connectedCallback(element) {
super.connectedCallback(element);
this.initChangeEvent();
this.initBindings();
}
disconnectedCallback(element) {
super.disconnectedCallback();
removeFunctionForExpression(this._expression, this);
removeTriggers(this._context, this._expression, this.fn);
this.fn = null;
this.changeHandler = null;
this._pathStack = null;
this._context = null;
this._expression = null;
this._attrName = null;
this._attribute = null;
}
initChangeEvent() {
const validListeners = ["INPUT", "TEXTAREA", "SELECT"];
if (validListeners.indexOf(this._element.nodeName) != -1) {
this._pathStack = this._expression.split(".");
this._fieldName = this._pathStack[this._pathStack.length - 1];
this.changeHandler = this.change.bind(this);
this.registerEvent(this._element, "change", this.changeHandler);
}
}
notifyPropertyChanged(name, value) {
setValueOnPath(this._context, this._expression, value);
}
initBindings() {
const resultFn = createFunctionForExpression(this._expression, this);
const attrName = domCaseMap.has(this._attrName) ? domCaseMap.get(this._attrName) : this._attrName;
if (attrName == "innerHTML") {
this.fn = () => requestAnimationFrame(() => this._element ? this._element.innerHTML = resultFn(this._context) : null);
} else {
this.fn = () => {
const property = this.createPropertyName(attrName);
const oldValue = this._element[property];
const result = resultFn(this._context);
Reflect.set(this._element, property, result);
const changedName = `${property}Changed`;
if (this._element[changedName] != undefined) {
this._element[changedName].call(this._element, result, oldValue);
}
postProcessPropertyChange(this._element, property, result);
}
}
addTriggers(this._context, this._expression, this.fn);
this.fn();
}
createPropertyName(name) {
if (name.indexOf("-") == -1) {
return name;
}
const stack = name.split("-");
let result = stack[0];
for (let i = 1; i < stack.length; i++) {
const s = stack[i];
result += s.charAt(0).toUpperCase() + s.slice(1)
}
return result;
}
change(event) {
const value = event.target.value;
const obj = getObjOnPath(this._context, this._pathStack);
obj[this._fieldName] = value;
}
}