data-tier
Version:
Tiny and fast two way (MV-VM) data binding framework for browser environments.
1 lines • 3.66 kB
JavaScript
import{TARGET_TYPES as d,getPath as r,setPath as o,callViewMethod as h,extractViewParams as a}from"./utils.min.js";const t=Object.freeze({subtree:!0,childList:!0,attributes:!0,attributeFilter:["data-tie"],attributeOldValue:!0,characterData:!1,characterDataOldValue:!1}),s="addEventListener",i="removeEventListener";class e{constructor(e){this._dtInstance=e,this._roots=new WeakMap,this._elementsMap=new WeakSet,this._boundDOMChangesListener=this._domChangesListener.bind(this),this._boundChangeListener=this._changeListener.bind(this)}addDocument(n){if(!n||Node.DOCUMENT_NODE!==n.nodeType&&Node.DOCUMENT_FRAGMENT_NODE!==n.nodeType)throw new Error("invalid argument, must be one of: DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE");if(this._roots.has(n))return console.warn("any root document may be added only once"),!1;var e=new MutationObserver(this._boundDOMChangesListener);e.observe(n,t),this._roots.set(n,e);for(let e=0,t=n.children.length;e<t;e++)this._addTree(n.children[e]);return!0}removeDocument(n){if(!this._roots.has(n))return console.warn(`no root document ${n} known`),!1;this._roots.get(n).disconnect(),this._roots.delete(n);for(let e=0,t=n.children.length;e<t;e++)this._dropTree(n.children[e]);return!0}_domChangesListener(n){let a,s,i,r,d,o;for(let e=0,t=n.length;e<t;e++)if("childList"===(s=(a=n[e]).type)){for(i=a.addedNodes,r=0,d=i.length;r<d;r++)(o=i[r]).nodeType===Node.ELEMENT_NODE&&this._addTree(o);for(i=a.removedNodes,r=0,d=i.length;r<d;r++)(o=i[r]).nodeType===Node.ELEMENT_NODE&&this._dropTree(o)}else{var h,l,_,c;"attributes"===s&&(h=a.attributeName,l=a.target,_=a.oldValue,c=l.getAttribute(h),"data-tie"===h)&&_!==c&&this._onTieParamChange(l,c,_)}}_onTieParamChange(e,t,n){n&&(n=e[this._dtInstance.paramsKey])&&(this._dtInstance.views.delView(e,n),this._handleChangeListener(e,i,n)),t&&(n=a(e))&&(this._dtInstance.views.addView(e,n),this._updateFromView(e,n),this._handleChangeListener(e,s,n))}_addTree(e){if(this._addOne(e),e.childElementCount)for(var t,n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT);t=n.nextNode();)this._addOne(t)}_dropTree(e){if(this._dropOne(e),e.childElementCount)for(var t,n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT);t=n.nextNode();)this._dropOne(t)}_addOne(e){var t;this._elementsMap.has(e)||(this._elementsMap.add(e),0<e.nodeName.indexOf("-")&&!e.matches(":defined")?this._waitDefined(e):((t=a(e))&&(this._dtInstance.views.addView(e,t),this._updateFromView(e,t),this._handleChangeListener(e,s,t)),e.shadowRoot&&this.addDocument(e.shadowRoot)))}_waitDefined(e){customElements.whenDefined(e.nodeName.toLowerCase()).then(()=>{this._elementsMap.delete(e),this._addOne(e)})}_dropOne(e){var t;this._elementsMap.has(e)&&(this._elementsMap.delete(e),(t=e[this._dtInstance.paramsKey])&&(this._dtInstance.views.delView(e,t),this._handleChangeListener(e,i,t)),e.shadowRoot)&&this.removeDocument(e.shadowRoot)}_changeListener(e){var s=e.type,i=e.currentTarget,r=i[this._dtInstance.paramsKey];if(r){let e,t,n,a=r.length;for(;a--;)(e=r[a]).changeEvent===s&&(t=this._dtInstance.ties.get(e.tieKey))&&(n=e.targetType===d.ATTRIBUTE?i.getAttribute(e.targetKey):i[e.targetKey],o(t,e.path,n))}}_handleChangeListener(n,a,s){var i;for(let e=0,t=s.length;e<t;e++)(i=s[e].changeEvent)&&n[a](i,this._boundChangeListener)}_updateFromView(e,t){let n=t.length;for(;n--;){var s=t[n];if(s.targetType===d.METHOD){let a=!1;const i=[];s.fParams.forEach(e=>{let t;var n=this._dtInstance.ties.get(e.tieKey);n&&(t=r(n,e.path),a=!0),i.push(t)}),a&&(i.push(null),h(e,s.targetKey,i))}else{var a=this._dtInstance.ties.get(s.tieKey);void 0!==a&&(a=r(a,s.path),this._dtInstance.views.updateViewByModel(e,s,a))}}}}export{e as DOMProcessor};