UNPKG

radi

Version:

**Radi** is a tiny javascript framework.

241 lines (209 loc) 6.86 kB
/* eslint-disable no-restricted-syntax */ // import GLOBALS from '../consts/GLOBALS'; import Component from '../component/Component'; import flatten from '../utils/flatten'; import patch from './patch'; import getElementFromQuery from './utils/getElementFromQuery'; import textNode from './utils/textNode'; import explode from './utils/explode'; import filterNode from './utils/filterNode'; import isComponent from '../component/utils/isComponent'; import Listener from '../listen/Listener'; import setAttributes from './setAttributes'; /** * @param {*} query * @param {object} props * @param {...*} children * @param {number} depth */ class Structure { constructor(query, props = {}, children, depth = 0) { this.query = query; this.props = Boolean !== props ? props : {}; if (isComponent(query) || query instanceof Component) { this.$compChildren = flatten(children || []).map(filterNode); this.children = []; } else { this.children = flatten(children || []).map(filterNode); this.$compChildren = []; } this.html = null; this.$attrListeners = []; this.$styleListeners = []; this.$pointer = null; this.$component = null; this.$listener = null; this.$redirect = null; this.$destroyed = false; this.$isSvg = query === 'svg'; this.$depth = depth; } mount() { this.$destroyed = false; if (this.$component instanceof Component) { this.$component.mount(); } if (typeof this.onMount === 'function') { this.onMount(); } } destroy(childrenToo = true) { if (this.$destroyed) return false; for (const l in this.$styleListeners) { if (this.$styleListeners[l] && typeof this.$styleListeners[l].deattach === 'function') { this.$styleListeners[l].deattach(); } } for (const l in this.$attrListeners) { if (this.$attrListeners[l] && typeof this.$attrListeners[l].deattach === 'function') { this.$attrListeners[l].deattach(); } } if (this.$redirect) { for (let i = 0; i < this.$redirect.length; i++) { if (typeof this.$redirect[i].destroy === 'function') { this.$redirect[i].destroy(); } } } if (childrenToo && this.children) { for (let i = 0; i < this.children.length; i++) { if (typeof this.children[i].destroy === 'function') { this.children[i].destroy(); } } } if (this.html) { const items = this.html; for (let i = 0; i < this.html.length; i++) { if (items[i].parentNode) { const destroyHTML = () => items[i].parentNode.removeChild(items[i]); if (typeof items[i].beforedestroy === 'function') { items[i].beforedestroy(destroyHTML); } else { destroyHTML(); } } } } if (this.$component instanceof Component) { this.$component.destroy(); } if (this.$listener instanceof Listener) { this.$listener.deattach(); } if (this.$pointer && this.$pointer.parentNode) { this.$pointer.parentNode.removeChild(this.$pointer); } if (typeof this.onDestroy === 'function') { this.onDestroy(); } this.$pointer = null; this.$redirect = null; this.$component = null; this.render = () => {}; this.html = null; this.$destroyed = true; return true; } render(next, parent, depth = 0, isSvg = false) { // console.log('RENDER', isSvg, parent, parent && parent.$isSvg) this.$depth = Math.max(this.$depth, depth); this.$isSvg = isSvg || (parent && parent.$isSvg) || this.query === 'svg'; if (this.query === '#text') { this.html = [textNode(this.props)]; return next(this.html); } if (typeof this.query === 'string' || typeof this.query === 'number') { this.html = [getElementFromQuery(this.query, this.$isSvg)]; setAttributes(this, this.props, {}); return next(this.html); } if (this.query instanceof Listener) { if (!this.$listener) { this.$listener = this.query.applyDepth(this.$depth).init(); this.mount(); } return this.query.onValueChange(v => { if (this.html) { const tempParent = this.html[0]; if (this.$pointer) { this.$redirect = patch(this.$redirect, v, this.$pointer, true, this.$isSvg, this.$depth + 1); } else { this.$redirect = patch(this.$redirect, v, tempParent, true, this.$isSvg, this.$depth + 1); } // let a = { // $redirect: [], // children: [], // }; // // explode(v, a, output => { // // this.html = output; // if (this.$pointer) { // this.$redirect = patch(this.$redirect, a.$redirect, // this.$pointer, true, this.$isSvg, this.$depth + 1); // } else { // this.$redirect = patch(this.$redirect, a.$redirect, // tempParent, true, this.$isSvg, this.$depth + 1); // } // // next(output); // }, this.$depth + 1, this.$isSvg); } else { explode(v, parent || this, output => { // console.warn('change HTML', this.html) this.html = output; next(output); }, this.$depth + 1, this.$isSvg); } }); } if (this.query instanceof Promise || this.query.constructor.name === 'LazyPromise') { return this.query.then(v => { const normalisedValue = v.default || v; explode(normalisedValue, parent || this, output => { this.html = output; next(output); }, this.$depth, this.$isSvg); }); } if (this.query instanceof Component && typeof this.query.render === 'function') { this.$component = this.query; return explode(this.$component.render(), parent || this, v => { this.html = v; next(v); this.mount(); }, this.$depth, this.$isSvg); } if (isComponent(this.query)) { if (!this.$component) { this.$component = new this.query(this.$compChildren).setProps(this.props); // eslint-disable-line } if (typeof this.$component.render === 'function') { explode(this.$component.render(), parent || this, v => { this.html = v; next(v); }, this.$depth, this.$isSvg); this.mount(); } return null; } if (typeof this.query === 'function') { return explode(this.query(this.props), parent || this, v => { this.html = v; next(v); }, this.$depth, this.$isSvg); } return next(textNode(this.query)); } isStructure() { return true; } } export default Structure;