mframejs
Version:
simple framework
425 lines • 18.1 kB
JavaScript
import * as tslib_1 from "tslib";
import { customAttribute } from '../decorator/exported';
import { View } from '../view/exported';
import { ViewController } from '../view/exported';
import { BindingEngine } from '../binding/exported';
import { ArrayMethodCallHandler, ArrayPropertyChange, PropertyChangeSimple } from './repeatAttributeSubscriberHelpers';
import { DOM } from '../utils/exported';
import { createBindingContext } from '../binding/createBindingContext';
let RepeatAttribute = class RepeatAttribute {
constructor() {
this.templateArray = [];
this.arrayType = 'object';
}
setArrayLocalVariables(ctx, i) {
ctx.$index = i;
ctx.$even = i % 2 === 0 ? true : false;
ctx.$odd = i % 2 === 0 ? false : true;
ctx.$last = i === this.templateArray.length - 1 ? true : false;
ctx.$first = i === 0 ? true : false;
}
created() {
this.value = this.$attribute.value;
this.loopBinded = this.loopArray.bind(this);
this.$view = this.$controller.getView();
this.$element.attributes.removeNamedItem('repeat.for');
this.elementClone = this.$element.cloneNode(true);
this.templateElement = this.elementClone.tagName === 'TEMPLATE' ? true : false;
if (this.elementClone.getAttribute('if.bind') && this.templateElement) {
this.templateElement = false;
}
this.$element.style.display = 'None';
const x = DOM.document.createElement('div');
const template = this.elementClone.cloneNode(true);
if (this.templateElement) {
if (!template.content) {
template.content = DOM.document.createDocumentFragment();
while (template.childNodes[0]) {
template.content.appendChild(template.childNodes[0]);
}
}
}
x.appendChild(this.templateElement ? template.content : template);
this.anchor = DOM.document.createComment('mf-repeat-for');
this.repeatForArray = this.value.split(' of ');
this.repeatForArray = this.repeatForArray.map(x => x.trim());
if (this.repeatForArray.length !== 2) {
console.error('unknown expression in repeat:' + this.value);
}
else {
this.rowInstanceName = this.repeatForArray[0];
this.arrayVariableName = this.repeatForArray[1];
this.arrayExpression = this.repeatForArray[1];
if (this.arrayVariableName.indexOf('|')) {
const split = this.arrayVariableName.split('|').map(x => x.trim());
this.arrayVariableName = split[0];
}
this.$array = BindingEngine.evaluateExpression(this.arrayExpression, this.$bindingContext);
const propertyType = this.$array;
if (!Array.isArray(propertyType)) {
if (typeof propertyType === 'number') {
this.arrayType = 'number';
this.subscribePropSimple();
}
else {
if (typeof propertyType === 'string') {
this.arrayType = 'string';
this.subscribePropSimple();
}
else {
this.subscribeArray();
this.subscribePropArray();
}
}
}
else {
this.subscribeArray();
this.subscribePropArray();
}
}
}
loopArray(changed, remove, add) {
const array = this.$array;
if (array) {
if (changed) {
if (remove) {
const syncLength = this.templateArray.length - remove;
for (let i = 0; i < this.templateArray.length; i++) {
if (i < syncLength) {
if (this.templateArray[i].ctx.$context[this.rowInstanceName] !== array[i]) {
this.templateArray[i].ctx.$context[this.rowInstanceName] = array[i];
}
}
else {
const temp = this.templateArray.pop();
i--;
this.clearInRow(temp);
}
}
}
if (add) {
const syncLength = array.length - add;
for (let i = 0; i < array.length; i++) {
if (i < syncLength) {
if (this.templateArray[i].ctx.$context[this.rowInstanceName] !== this.$array[i]) {
this.templateArray[i].ctx.$context[this.rowInstanceName] = this.$array[i];
}
}
else {
this.push(array[i]);
}
}
}
}
else {
for (let i = 0; i < this.$array.length; i++) {
if (this.templateArray[i].ctx.$context[this.rowInstanceName] !== array[i]) {
this.templateArray[i].ctx.$context[this.rowInstanceName] = array[i];
}
}
}
this.updateInternals();
}
}
loopArrayNumber(changed, remove, add) {
const num = this.templateArray.length + 1;
if (num) {
if (changed) {
if (remove) {
const syncLength = this.templateArray.length - remove;
for (let i = 0; i < this.templateArray.length; i++) {
if (i >= syncLength) {
const temp = this.templateArray.pop();
i--;
this.clearInRow(temp);
}
}
}
if (add) {
const syncLength = num;
for (let i = 0; i < num + add; i++) {
if (i >= syncLength) {
this.push(i);
}
}
}
}
else {
for (let i = 0; i < this.$array; i++) {
if (this.templateArray[i].ctx.$context[this.rowInstanceName] !== i) {
this.templateArray[i].ctx.$context[this.rowInstanceName] = i;
}
}
}
this.updateInternals();
}
}
detached() {
this.clearTemplateArray();
if (this.arrayMethodCallHandler) {
BindingEngine.unSubscribeClassArray(this.$bindingContext, this.arrayMethodCallHandler);
}
if (this.arrayPropertyChangeHandler) {
BindingEngine.unSubscribeClassProperty(this.$bindingContext, this.arrayPropertyChangeHandler);
}
if (this.arrayPropertyChangeHandlerLocal) {
BindingEngine.unSubscribeClassProperty(this.$bindingContext, this.arrayPropertyChangeHandlerLocal);
}
if (this.propertyChangeHandlerSimple) {
BindingEngine.unSubscribeClassProperty(this.$bindingContext, this.propertyChangeHandlerSimple);
}
if (this.anchor) {
this.anchor.parentNode.removeChild(this.anchor);
this.anchor = null;
}
this.$view = null;
this.$array = null;
this.arrayMethodCallHandler = null;
this.arrayPropertyChangeHandler = null;
this.arrayPropertyChangeHandlerLocal = null;
this.propertyChangeHandlerSimple = null;
}
attached() {
this.remove();
this.isAttached = true;
this.$array = BindingEngine.evaluateExpression(this.arrayExpression, this.$bindingContext);
const array = this.$array;
if (Array.isArray(array)) {
array.forEach((ctx) => {
this.push(ctx);
});
}
else {
if (this.arrayType === 'number') {
if (this.templateArray.length !== array) {
this.clearTemplateArray();
for (let i = 0; i < array; i++) {
this.push(i + 1);
}
}
}
if (this.arrayType === 'string') {
const stringLength = typeof array === 'string' ? array.length : 0;
if (this.templateArray.length !== stringLength) {
this.clearTemplateArray();
for (let i = 0; i < stringLength; i++) {
this.push(array[i]);
}
}
}
}
this.updateInternals();
}
subscribeArray() {
if (!this.arrayMethodCallHandler) {
this.arrayMethodCallHandler = new ArrayMethodCallHandler(this);
}
BindingEngine.subscribeClassArray(this.$bindingContext, this.arrayVariableName, this.arrayMethodCallHandler);
}
subscribePropArray() {
if (!this.arrayPropertyChangeHandler) {
this.arrayPropertyChangeHandler = new ArrayPropertyChange(this);
}
else {
console.error('subscribePropArray fail, called when set', this.arrayExpression, this.arrayVariableName);
}
BindingEngine.subscribeClassProperty(this.$bindingContext, this.arrayVariableName, this.arrayPropertyChangeHandler);
if (this.arrayVariableName !== this.arrayExpression) {
if (!this.arrayPropertyChangeHandlerLocal) {
this.arrayPropertyChangeHandlerLocal = new ArrayPropertyChange(this);
}
const classKey = this.arrayExpression.replace(this.arrayVariableName, '$array');
BindingEngine.subscribeClassProperty(createBindingContext(this), classKey, this.arrayPropertyChangeHandlerLocal);
}
}
subscribePropSimple() {
if (!this.propertyChangeHandlerSimple) {
this.propertyChangeHandlerSimple = new PropertyChangeSimple(this);
}
BindingEngine.subscribeClassProperty(this.$bindingContext, this.arrayVariableName, this.propertyChangeHandlerSimple);
}
push(ctx, i) {
const template = this.elementClone.cloneNode(true);
if (this.templateElement) {
if (!template.content) {
template.content = DOM.document.createDocumentFragment();
while (template.childNodes[0]) {
template.content.appendChild(template.childNodes[0]);
}
}
}
const context = createBindingContext({ [this.rowInstanceName]: ctx }, createBindingContext(this.$bindingContext, this.$bindingContext));
const temp = DOM.document.createElement('div');
temp.appendChild(this.templateElement ? template.content : template);
const $view = new ViewController(template, this.$view);
if (!this.cache) {
this.cache = View.createTemplateCache(temp);
}
const controllers = View.parseTemplateCache(temp, context, $view, this.cache);
let childNodes;
if (this.templateElement) {
childNodes = [];
let anchor = DOM.document.createComment('repeat-template-row-anchor-start');
childNodes.push(anchor);
for (let i = 0, ii = temp.childNodes.length; i < ii; i++) {
childNodes.push(temp.childNodes[i]);
}
anchor = DOM.document.createComment('repeat-template-row-anchor-end');
childNodes.push(anchor);
}
if (i === undefined) {
const length = this.templateArray.length;
this.templateArray.push({
ctx: context,
template: this.templateElement ? childNodes : template,
$view: $view
});
this.setArrayLocalVariables(context.$context, this.templateArray.length - 1);
if (this.templateElement) {
if (length) {
const u = this.templateArray[length - 1].template.length - 1;
this.anchor.parentNode.insertBefore(childNodes[0], this.templateArray[length - 1].template[u].nextSibling);
for (let i = 1, ii = childNodes.length; i < ii; i++) {
this.anchor.parentNode.insertBefore(childNodes[i], childNodes[i - 1].nextSibling);
}
}
else {
this.anchor.parentNode.insertBefore(childNodes[0], this.anchor.nextSibling);
for (let i = 1, ii = childNodes.length; i < ii; i++) {
this.anchor.parentNode.insertBefore(childNodes[i], childNodes[i - 1].nextSibling);
}
}
}
else {
if (length) {
this.anchor.parentNode.insertBefore(template, this.templateArray[length - 1].template.nextSibling);
}
else {
this.anchor.parentNode.insertBefore(template, this.anchor.nextSibling);
}
}
}
else {
this.templateArray.splice(i, 0, {
ctx: context,
template: this.templateElement ? childNodes : template,
$view: $view
});
if (this.templateElement) {
if (this.templateArray[i + 1]) {
const u = this.templateArray[length - 1].template.length - 1;
this.anchor.parentNode.insertBefore(childNodes[0], this.templateArray[length - 1].template[u].nextSibling);
for (let i = 1, ii = childNodes.length; i < ii; i++) {
this.anchor.parentNode.insertBefore(childNodes[i], childNodes[i - 1].nextSibling);
}
}
else {
this.anchor.parentNode.insertBefore(childNodes[0], this.anchor.nextSibling);
for (let i = 1, ii = childNodes.length; i < ii; i++) {
this.anchor.parentNode.insertBefore(childNodes[i], childNodes[i - 1].nextSibling);
}
}
}
else {
if (this.templateArray[i + 1]) {
this.anchor.parentNode.insertBefore(template, this.templateArray[i + 1].template);
}
else {
this.anchor.parentNode.appendChild(template);
}
}
}
controllers.forEach((contr) => {
if (contr.attached) {
contr.attached();
}
});
}
pop() {
if (this.templateArray.length > 0) {
const temp = this.templateArray.pop();
this.clearInRow(temp);
this.updateInternals();
}
}
updateInternals() {
this.templateArray.forEach((context, i) => {
this.setArrayLocalVariables(context.ctx.$context, i);
});
}
shift() {
if (this.templateArray.length > 0) {
const temp = this.templateArray.shift();
this.clearInRow(temp);
this.updateInternals();
}
}
splice(args) {
if (this.templateArray.length > 0) {
const index = args[0];
const deleted = args[0] === 0 && args[1] === undefined ? this.templateArray.length : args[1];
const added = [];
for (let i = 2; i < args.length; i++) {
if (args[i]) {
added.push(args[i]);
}
}
if (deleted) {
const newIndex = index + deleted - 1;
for (let i = newIndex; i > index - 1; i--) {
const temp = this.templateArray.splice(i, 1)[0];
this.clearInRow(temp);
}
}
added.forEach((ctx) => {
this.push(ctx, index);
});
this.updateInternals();
}
}
clearTemplateArray() {
let x = DOM.document.createElement('div');
this.templateArray.forEach((temp) => {
if (this.templateElement) {
for (let i = 0, ii = temp.template.length; i < ii; i++) {
x.appendChild(temp.template[i]);
}
}
else {
x.appendChild(temp.template);
}
});
this.templateArray.forEach((temp) => {
temp.$view.clearView();
});
x = null;
this.templateArray = [];
}
remove() {
this.clearTemplateArray();
this.$element.parentNode.replaceChild(this.anchor, this.$element);
}
clearInRow(rowData) {
if (rowData) {
if (this.templateElement) {
for (let i = 0, ii = rowData.template.length; i < ii; i++) {
rowData.$view.clearView();
if (rowData.template[i].parentNode) {
rowData.template[i].parentNode.removeChild(rowData.template[i]);
}
}
}
else {
if (rowData.template.parentNode) {
rowData.template.parentNode.removeChild(rowData.template);
}
rowData.$view.clearView();
}
}
}
};
RepeatAttribute = tslib_1.__decorate([
customAttribute('repeat.for')
], RepeatAttribute);
export { RepeatAttribute };
//# sourceMappingURL=repeatAttribute.js.map