UNPKG

jsboost

Version:

A tiny library that extends the capability of javascript

112 lines (95 loc) 2.9 kB
/** * Author: JCloudYu * Create: 2019/12/13 **/ const _PRIVATES = new WeakMap(); class _HTMLElementAccessor { constructor(element=null) { const _PRIVATE = Object.assign(Object.create(null), { element:null, exported:Object.create(null), func_bind: _HTMLElementAccessor.prototype.bind.bind(this), func_relink: _HTMLElementAccessor.prototype.relink.bind(this), }); _PRIVATES.set(this, _PRIVATE); if ( arguments.length === 0 ) return; this.bind(element); } bind(element) { if ( !(element instanceof Element) ) { throw new TypeError( "HTMLElementAccessor constructor only accept Element instances!" ); } const _PRIVATE = _PRIVATES.get(this); _PRIVATE.element = element; _PRIVATE.exported = Object.create(null); this.relink(); } relink() { const _PRIVATE = _PRIVATES.get(this); _PRIVATE.exported = Object.create(null); const {element, exported} = _PRIVATE; const exported_items = element.querySelectorAll('[elm-export]'); for( const item of exported_items ) { const export_name = item.getAttribute('elm-export'); exported[export_name] = item; } } } const HTMLElementAccessorProxy = { getPrototypeOf: function(obj) { return Object.getPrototypeOf(obj); }, get: function(obj, prop) { const {element, exported, func_bind, func_relink} = _PRIVATES.get(obj); if ( prop === 'element' ) return element; if ( prop === 'bind' ) return func_bind; if ( prop === 'relink' ) return func_relink; return exported[prop] || obj[prop]; }, set: function(obj, prop, value) { if ( prop === "element" ) return false; if ( prop === "bind" ) return false; if ( prop === "relink" ) return false; const {exported} = _PRIVATES.get(obj); if ( !exported[prop] ) { obj[prop] = value; } return true; } }; export const HTMLElementAccessor = new Proxy(_HTMLElementAccessor, { construct(target, args) { const inst = new target(...args); return new Proxy(inst, HTMLElementAccessorProxy); }, apply() { throw new TypeError( "Class constructor a cannot be invoked without 'new'" ); } }); export class HTMLElementTemplate { constructor(element) { if ( typeof element === "string" ) { var tmp = document.implementation.createHTMLDocument(); tmp.body.innerHTML = element; if ( tmp.body.children.length !== 1 ) { throw new TypeError( "HTMLTemplate constructor only html string that is resolved as single Element instance!" ); } element = tmp.body.children[0]; } else if ( element instanceof Element ){ element = element.cloneNode(true); } else { throw new TypeError( "HTMLTemplate constructor only accepts an Element instance!" ); } Object.defineProperties(this, { _tmpl_elm: { configurable:false, writable:false, enumerable:false, value:element } }); } produce() { return new HTMLElementAccessor(this._tmpl_elm.cloneNode(true)); } }