UNPKG

capivarajs

Version:

Um framework para criação de componentes.

89 lines (77 loc) 3.34 kB
import isEqual from 'lodash.isequal'; import { Common } from '../../common'; import { Constants } from '../../constants'; import { Controller } from '../../core/controller'; import capivara from '../../index'; import { MapDom } from '../map-dom'; import { Directive } from './directive.interface'; export class CPRepeat implements Directive { private readonly attribute; private readonly originalElement; private readonly referenceNode; private readonly regex; private map: MapDom; private element; private lastArray = []; private elms = []; private attributeAlias; private attributeScope; constructor(_element: HTMLElement, _map: MapDom) { this.element = _element.cloneNode(true); this.element.removeAttribute(Constants.REPEAT_ATTRIBUTE_NAME); this.element.classList.add('binding-repeat'); this.originalElement = _element; this.map = _map; this.attribute = _element.getAttribute(Constants.REPEAT_ATTRIBUTE_NAME).replace(/\s+/g, ' '); this.regex = new RegExp('^[\\s*|\\S]+\\s+' + Constants.REPEAT_ATTRIBUTE_OPERATOR.replace(/ /g, '') + '\\s+\\S+\\s*', 'g'); const matches = this.attribute.match(this.regex); if (!this.attribute || (!matches || matches.length === 0)) { throw new Error(`syntax error invalid ${Constants.REPEAT_ATTRIBUTE_NAME} expresion: ${this.attribute}`); } this.referenceNode = document.createComment('start repeat ' + this.attribute); if (this.originalElement.parentNode.replaceChild) { this.originalElement.parentNode.replaceChild(this.referenceNode, this.originalElement); } } public create() { const operator = ` ${Constants.REPEAT_ATTRIBUTE_OPERATOR} `; this.attributeAlias = this.attribute.substring(0, this.attribute.indexOf(operator)).replace(/ /g, ''); this.attributeScope = this.attribute.substring(this.attribute.indexOf(operator) + operator.length, this.attribute.length).replace(/ /g, ''); this.applyLoop(); } public applyLoop() { const array = Common.evalInMultiContext(this.originalElement, this.attributeScope); if (array && !isEqual(array, this.lastArray)) { this.lastArray = array.slice(); this.removeChildes(); this.loop(array, this.attributeAlias); } } public removeChildes() { this.elms.forEach((elm) => this.referenceNode.parentNode.removeChild(elm)); } public loop(array, attributeAlias) { this.elms = []; // reset elements render let lastAdded = this.referenceNode; array.forEach((row, index) => { const elm = this.element.cloneNode(true); new Controller(elm, () => { }); Common.appendAfter(lastAdded, elm); const elementContext = Common.getScope(elm); elementContext.scope[attributeAlias] = row; elementContext.scope[Constants.REPEAT_INDEX_NAME] = index; elementContext.$parent = Common.getScope(this.referenceNode.parentNode); this.createChildrenComponents(elm); lastAdded = elm; this.elms.push(elm); // add element reference. }); if (lastAdded) { Common.appendAfter(lastAdded, this.referenceNode.parentNode.appendChild(document.createComment('end repeat ' + this.attribute))); } } private createChildrenComponents(elm) { (Array.from(elm.children) || []).forEach((child) => { capivara.constroyIfComponent(child); }); } }