New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

crs-binding

Package Overview
Dependencies
Maintainers
1
Versions
143
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

crs-binding - npm Package Compare versions

Comparing version 0.0.90 to 0.0.91

82

crs-bindable-element.js

@@ -1,1 +0,81 @@

class t extends HTMLElement{constructor(){super(),crsbinding.events.enableEvents(this),crsbinding.dom.enableEvents(this)}dispose(){crsbinding.events.disableEvents(this),crsbinding.dom.disableEvents(this)}async connectedCallback(){null!=this.html&&(this.innerHTML=await fetch(this.html).then(t=>t.text()),crsbinding.parsers.parseElements(this.children,this),crsbinding.expression.updateUI(this)),this.dispatchEvent(new CustomEvent("ready"))}async disconnectedCallback(){this.dispose(),null!=this.observer&&(this.observer.disconnect(),this.attributesChangedHandler=null,this.observer=null),crsbinding.observation.releaseBinding(this)}getProperty(t){let e=this[`_${t}`];return null==e&&null!=this.getAttribute&&(e=this.getAttribute(t)),e}setProperty(t,e){this[`_${t}`]=e,crsbinding.events.notifyPropertyChanged(this,t)}observeAttributes(t){this.attributesChangedHandler=this.attributesChanged.bind(this),this.observer=new MutationObserver(this.attributesChangedHandler),this.observer.observe(this,{attributes:!0,attributeFilter:t,attributeOldValue:!0})}attributesChanged(t){for(let e of t){const t=`${e.attributeName}AttributeChanged`;null!=this[t]&&this[t](e.target[e.attributeName],e.oldValue)}}}export{t as BindableElement};
class BindableElement extends HTMLElement {
constructor() {
super();
crsbinding.events.enableEvents(this);
crsbinding.dom.enableEvents(this);
}
dispose() {
this._disposing = true;
crsbinding.events.disableEvents(this);
crsbinding.dom.disableEvents(this);
}
async connectedCallback() {
if (this.html != null) {
this.innerHTML = await fetch(this.html).then(result => result.text());
crsbinding.parsers.parseElements(this.children, this);
crsbinding.expression.updateUI(this);
}
this.dispatchEvent(new CustomEvent("ready"));
}
async disconnectedCallback() {
this.dispose();
if (this.observer != null) {
this.observer.disconnect();
this.attributesChangedHandler = null;
this.observer = null;
}
crsbinding.observation.releaseBinding(this);
}
getProperty(prop) {
let result = this[`_${prop}`];
if (result == null && this.getAttribute != null) {
result = this.getAttribute(prop);
}
return result;
}
setProperty(prop, value) {
const property = this[`${prop}`];
if (property != null && typeof property == "object") {
const elEvents = property.__elEvents || property.__events;
delete property.__elEvents;
if (value == undefined) {
value = {};
}
if (value != null) {
value.__elEvents = elEvents;
}
}
this[`_${prop}`] = value;
crsbinding.events.notifyPropertyChanged(this, prop);
}
observeAttributes(attributes) {
this.attributesChangedHandler = this.attributesChanged.bind(this);
this.observer = new MutationObserver(this.attributesChangedHandler);
this.observer.observe(this, {attributes: true, attributeFilter: attributes, attributeOldValue: true});
}
attributesChanged(mutationsList) {
for(let mutation of mutationsList) {
const attr = `${mutation.attributeName}AttributeChanged`;
if (this[attr] != null) {
this[attr](mutation.target[mutation.attributeName], mutation.oldValue);
}
}
}
}
export { BindableElement };

@@ -1,1 +0,1915 @@

const e=Object.getPrototypeOf((async function(){})).constructor;function t(t,n,i){n=n||[];let s=!0,r=!1,l="context";if(null!=i&&(null!=i.sanitize&&(s=i.sanitize),null!=i.async&&(r=i.async),null!=i.ctxName&&(l=i.ctxName)),crsbinding._expFn.has(t)){const e=crsbinding._expFn.get(t);return e.count+=1,e}let o,a=t;if(1==s){if(o=crsbinding.expression.sanitize(t,l),crsbinding._expFn.has(o.expression)){const e=crsbinding._expFn.get(o.expression);return e.count+=1,e}a=!0===o.isLiteral?["return `",o.expression,"`"].join(""):`return ${o.expression}`,o.expression.split(".").length>2&&(a=`try { ${a} } catch(error) { return null }`)}else o={expression:t};const _={function:1==r?new e(l,...n,a):new Function(l,...n,a),parameters:o,count:1};return crsbinding._expFn.set(o.expression,_),_}function n(e){e.__isArray=!0,null==e._events&&crsbinding.events.enableEvents(e),e.__nextId=1;for(let t=0;t<e.length;t++)o(e,t);return new Proxy(e,{get:r})}const i=["pop","splice"],s=["push"];function r(e,t){const n=e[t];return"function"==typeof n?(...n)=>{const r=e[t](...n);return-1!=i.indexOf(t)?(!function(e,t){if(null==t)return;if(crsbinding.events.notifyPropertyChanged(e,"items-deleted",t),Array.isArray(t))for(let e of t)crsbinding.observation.releaseObserved(e);else crsbinding.observation.releaseObserved(t)}(e,r),"splice"==t&&n.length>2&&(n=n.splice(2,n.length),l(e,n))):-1!=s.indexOf(t)&&l(e,n),r}:n}function l(e,t){if(null==t)return;const n={items:[],indexes:[]};for(let i of t){const t=e.indexOf(i);o(e,t),n.items.push(i),n.indexes.push(t)}crsbinding.events.notifyPropertyChanged(e,"items-added",n)}function o(e,t){const n=e[t];n.__uid=e.__nextId,e.__nextId++,1!=n.__isProxy&&(e[t]=crsbinding.observation.observe(n))}const a="__isProxy";function _(e){if(1==e.__isArray)return t=e,crsbinding.events.disableEvents(t),void t.forEach(e=>crsbinding.observation.releaseObserved(e));var t;crsbinding.events.disableEvents(e),null!=e.dispose&&(e._disposing=!0,e.dispose());const n=Object.getOwnPropertyNames(e);for(let t of n)0==t.indexOf("__")||-1!=t.indexOf("Changed")&&"function"==typeof e[t]?delete e[t]:e[t]&&1==e[t][a]&&(_(e[t]),delete e[t])}function c(e,t){return e[t]}function h(e,t,n){return"_disposing"==t||1==e._disposing||(-1!=t.indexOf("__")?e[t]=n:function(e,t,n){e.__processing=!0;const i=e.__backup,s=e[t];e[t]=function(e,t){if(null==t)return null;let n=t;if(e&&1==e.__isProxy){n&&1!=n.__isProxy?n=crsbinding.observation.observe(n,e):n&&e&&(n.__events=e.__events,delete e.__events);const t=Object.getOwnPropertyNames(e).filter(e=>-1==e.indexOf("__"));for(let i of t)if(1==e[i][a]&&1!=n[i][a]){const t=crsbinding.observation.observe(n[i],e[i]);n.__processing=!0,delete n[i],n[i]=t,delete n.__processing}}return n}(e[t],n),crsbinding.events.notifyPropertyChanged(e,t),null!=e.propertyChanged&&e.propertyChanged(n,s);!function(e){return e&&"object"==typeof e&&1==e[a]}(s)?-1==p.indexOf(t)&&-1==t.indexOf("__")&&(i[t]=s):_(s);delete e.__processing}(e,t,n),!0)}const p=["__isProxy","element"];function d(e){if(-1==e.indexOf("("))return e;const t=[];for(let n of e.split(".")){if(-1!=n.indexOf("("))break;t.push(n)}return t.join(".")}const u=["true","false","-","+","=","<",">","(",")","{","}","/","&","|","=","!","'","`",'"'," ","$",".",",","?",":","null","undefined"],f=[".","(",")",","],x=["'",'"',"`"],m=["'",'"'];function g(e,t,n){return t.length>0&&(e.push(t.join("")),t.length=0),e.push(n),!1}class v{constructor(e,t,n,i,s){this._element=e,this._context=t,this._property=n,this._value=i,this._ctxName=s||"context",this._eventsToRemove=[],this._isNamedContext="context"!=this._ctxName,crsbinding.providerManager.register(this),this.initialize().catch(e=>{throw e}),-1!=this._element.nodeName.indexOf("-")&&this._property==this._ctxName&&(this._element[this._property]=this._context)}dispose(){this._eventsToRemove.forEach(e=>{crsbinding.events.removeOn(this._context,e.value,e.callback)}),this._eventsToRemove.length=0,this._eventsToRemove=null,this._element=null,this._context=null,this._property=null,this._value=null,this._ctxName=null}async initialize(){}listenOnPath(e,t){if(1!=Array.isArray(e))this._isNamedContext&&(e=e.replace(`${this._ctxName}.`,"")),-1==e.indexOf(".")?crsbinding.events.listenOn(this._context,e,t):crsbinding.events.listenOnPath(this._context,e,t),this._eventsToRemove.push({value:e,callback:t});else for(let n of e)this.listenOnPath(n,t)}removeOn(e,t){crsbinding.events.removeOn(this._context,e,t)}}const b='element.dataset["__property__"] = value || ""',y="\nif (element.__classList!=null) {\n const remove = Array.isArray(element.__classList) ? element.__classList : [element.__classList];\n remove.forEach(cls => element.classList.remove(cls));\n}",O="\nelement.__classList = value;\nconst add = Array.isArray(value) ? value : [value];\nadd.forEach(cls => element.classList.add(cls));",j=`${y} ${O}`,$=`\n ${y}\n\n if (__exp__) {\n ${O.split("value").join("__true__")}\n }\n else {\n ${O.split("value").join("__false__")}\n }\n`;class A extends v{dispose(){const e=`${this._ctxName}.`;0==this._value.indexOf(e)&&(this._value=this._value.replace(e,"")),this.removeOn(this._value,this._eventHandler),null!=this._expObj&&(crsbinding.expression.release(this._expObj),delete this._expObj),null!=this._getObj&&(crsbinding.expression.release(this._getObj),delete this._getObj),this._exp=null,this._eventHandler=null,super.dispose()}async initialize(){if("$context"==this._value)return this.setContext();this._eventHandler=this.propertyChanged.bind(this),this._exp=function(e){let t;if("classlist"==e._property.toLocaleLowerCase())return j;if(-1!=e._property.indexOf("data-")){const t=e._property.replace("data-","");return b.split("__property__").join(t)}-1==e._property.indexOf("-")||-1!=e._property.indexOf("-")&&-1!=e._property.indexOf(".")?(t='requestAnimationFrame(() => element.__property__ = value || "")',e._property=crsbinding.utils.capitalizePropertyPath(e._property)):t='element.setAttribute("__property__", value || "")';return t.split("__property__").join(e._property)}(this),this._expObj=crsbinding.expression.compile(this._exp,["element","value"],{sanitize:!1,ctxName:this._ctxName}),-1!=this._value.indexOf(".")&&(this._getObj=crsbinding.expression.compile(this._value,null,{ctxName:this._ctxName})),this.listenOnPath(this._value,this._eventHandler);const e=this._context[this._value];this.propertyChanged(null,e)}setContext(){null!=this._element&&null!=this._property&&(this._element[this._property]=this._context)}propertyChanged(e,t){let n=t;null!=this._getObj&&(n=this._getObj.function(this._context)),crsbinding.idleTaskManager.add(this._expObj.function(this._context,this._element,n))}}class E extends A{dispose(){this._element.removeEventListener("change",this._changeHandler),this._changeHandler=null,crsbinding.expression.release(this._setObj),delete this._setObj,super.dispose()}async initialize(){await super.initialize(),this._changeHandler=this._change.bind(this),this._element.addEventListener("change",this._changeHandler);const e=1==this._isNamedContext?`${this._value} = value`:`context.${this._value} = value`;this._setObj=crsbinding.expression.compile(e,["value"],{sanitize:!1,ctxName:this._ctxName})}_change(e){let t=e.target[this._property];const n=`_${e.target.type||"text"}`;null!=this[n]&&(t=this[n](t,e.target)),this._setObj.function(this._context,t),e.stopPropagation()}_number(e){return Number(e)}_date(e){return new Date(e)}_checkbox(e,t){return 1==t.checked}}function C(e,t,n,i,s="context"){return"context"==s?function(e,t,n,i){const s=new Function("context",`return context.${i}`);w(e,n,s(t))}(e,t,n,i):function(e,t,n,i,s){const r=0==i.indexOf(s)?`return ${i}`:`return ${s}.${i}`,l=new Function(s,r);w(e,n,l(t))}(e,t,n,i,s),null}function w(e,t,n){if(-1==t.indexOf("data-")){t=crsbinding.utils.capitalizePropertyPath(t),new Function("element","value",`element.${t} = value`)(e,n)}else{const i=t.replace("data-","");e.dataset[i]=n}}class N extends v{constructor(e,t,n,i,s){super(e,t,n,i,s),this._eventHandler=this.event.bind(this),this._element.addEventListener(this._property,this._eventHandler)}dispose(){this._element.removeEventListener(this._property,this._eventHandler),this._eventHandler=null,this._fn=null,super.dispose()}async initialize(){let e=`context.${this._value}`.split("$event").join("event");-1==e.indexOf(")")&&(e=`${e}.call(context)`),this._fn=new Function("context",e)}event(e){crsbinding.idleTaskManager.add(this._fn(this._context)),e.stopPropagation()}}class H extends v{constructor(e,t,n,i,s){super(e,t,n,i,s),this._eventHandler=this._change.bind(this),this._expObj=crsbinding.expression.compile(e.innerText,null,{ctxName:this._ctxName});for(let e of this._expObj.parameters.properties)this.listenOnPath(e,this._eventHandler);this._change()}dispose(){crsbinding.expression.release(this._expObj),this._expObj=null,super.dispose(),this._eventHandler=null}_change(){null!=this._expObj&&(this._element.innerText=this._expObj.function(this._context))}}class P extends v{constructor(e,t,n,i,s){super(e,t,n,i,s),this._eventHandler=this._change.bind(this),this._expObj=crsbinding.expression.compile(i,null,{ctxName:this._ctxName});for(let e of this._expObj.parameters.properties)this.listenOnPath(e,this._eventHandler)}dispose(){crsbinding.expression.release(this._expObj),this._expObj=null,super.dispose(),this._eventHandler=null}_change(){if(null==this._expObj)return;const e=this._expObj.function(this._context);this._element.setAttribute(this._property,e)}}class z extends v{get ar(){return this._ar}set ar(e){null!=this._ar&&(crsbinding.events.removeOn(this._ar,"items-added",this._itemsAddedHandler),crsbinding.events.removeOn(this._ar,"items-deleted",this._itemsDeletedHandler)),this._ar=e,null!=this._ar&&(crsbinding.events.on(this._ar,"items-added",this._itemsAddedHandler),crsbinding.events.on(this._ar,"items-deleted",this._itemsDeletedHandler))}constructor(e,t,n,i,s){super(e,t,n,i,s),this._itemsAddedHandler=this._itemsAdded.bind(this),this._itemsDeletedHandler=this._itemsDeleted.bind(this)}dispose(){this.ar=null,crsbinding.expression.release(this._forExp),this._forExp=null,this._itemsAddedHandler=null,this._itemsDeletedHandler=null,this._singular=null,this._plural=null,this._container=null,this._collectionChangedHandler=null,super.dispose()}async initialize(){this._container=this._element.parentElement,this._container.removeChild(this._element);const e=this._value.split("of");this._singular=e[0].trim(),this._plural=e[1].trim();const t=T.split("_p").join(this._singular).split("_c").join("context"==this._ctxName?`context.${this._plural}`:this._plural);this._forExp=crsbinding.expression.compile(t,["callback"],{sanitize:!1,async:!0,ctxName:this._ctxName}),this._collectionChangedHandler=this._collectionChanged.bind(this),this.listenOnPath(this._plural,this._collectionChangedHandler)}async _collectionChanged(e,t){if(Array.isArray(t))this.ar=t;else{const e=new Function("context",`return context.${this._plural}`);this.ar=e(this._context)}null!=this.ar&&await this._renderItems()}async _renderItems(){if(await crsbinding.observation.releaseChildBinding(this._container),null==this.ar)return;const e=document.createDocumentFragment();await this._forExp.function(this._context,t=>{const n=this.createElement(t);e.appendChild(n)}),this._container.innerHTML="",this._container.appendChild(e),crsbinding.expression.updateUI(this.ar),null==this._container.__providers&&(this._container.__providers=[]),-1==this._container.__providers.indexOf(this.id)&&this._container.__providers.push(this.id)}_itemsAdded(e,t,n){for(let e=0;e<n.items.length;e++){const t=n.items[e],i=n.indexes[e],s=this.createElement(t),r=s.children[0],l=this._container.children[i];this._container.insertBefore(s,l);for(let e of r.__providers||[]){const t=crsbinding.providerManager.items.get(e);t instanceof P&&t._change()}crsbinding.expression.updateUI(t)}}_itemsDeleted(e,t,n){const i=[],s=e=>{const t=e.__uid;this._container.querySelectorAll([`[data-uid="${t}"]`]).forEach(e=>i.push(e))};if(Array.isArray(n))for(let e of n)s(e);else s(n);for(let e of i)null!=e&&(e.parentElement.removeChild(e),crsbinding.observation.releaseBinding(e))}createElement(e){const t=this._element.content.cloneNode(!0);crsbinding.parsers.parseElement(t,e,this._singular);for(let n of t.children)n.dataset.uid=e.__uid;return t}}const T="for (_p of _c || []) {callback(_p);}";class L extends v{constructor(e,t,n,i,s){super(e,t,n,i,s)}dispose(){crsbinding.expression.release(this._expObj),delete this._expObj,this._eventHandler=null,super.dispose()}async initialize(){this._eventHandler=this.propertyChanged.bind(this),-1==this._value.indexOf("?")?this._initCndAttr():-1!=this._value.indexOf(":")?this._initCndValue():this._initCndAttrValue(),this.propertyChanged()}_initCndAttr(){const e=crsbinding.expression.sanitize(this._value,this._ctxName),t=k.split("__exp__").join(e.expression).split("__attr__").join(this._property).split("__attr-value__").join(this._property);this._expObj=crsbinding.expression.compile(t,["element"],{sanitize:!1,ctxName:this._ctxName}),this.listenOnPath(e.properties,this._eventHandler)}_initCndValue(){const e=crsbinding.expression.sanitize(this._value,this._ctxName),t=e.expression.split("?"),n=t[1].split(":"),i=F.split("__exp__").join(t[0].trim()).split("__attr__").join(this._property).split("__true__").join(n[0].trim()).split("__false__").join(n[1].trim());this._expObj=crsbinding.expression.compile(i,["element"],{sanitize:!1,ctxName:this._ctxName}),this.listenOnPath(e.properties,this._eventHandler)}_initCndAttrValue(){const e=crsbinding.expression.sanitize(this._value,this._ctxName),t=e.expression.split("?"),n=k.split("__exp__").join(t[0].trim()).split("__attr__").join(this._property).split("__attr-value__").join(t[1].trim());this._expObj=crsbinding.expression.compile(n,["element"],{sanitize:!1,ctxName:this._ctxName}),this.listenOnPath(e.properties,this._eventHandler)}propertyChanged(){crsbinding.idleTaskManager.add(this._expObj.function(this._context,this._element))}}const k='\nif (__exp__) {\n element.setAttribute("__attr__", "__attr-value__");\n}\nelse {\n element.removeAttribute("__attr__");\n}\n',F='\nif (__exp__) {\n element.setAttribute("__attr__", "__true__");\n}\nelse {\n element.setAttribute("__attr__", "__false__");\n}\n';class I extends v{constructor(e,t,n,i,s){super(e,t,n,i,s)}dispose(){crsbinding.expression.release(this._expObj),delete this._expObj,this._eventHandler=null,super.dispose()}async initialize(){this._eventHandler=this.propertyChanged.bind(this);const e=this._value.split("?"),t=crsbinding.expression.sanitize(e[0],this._ctxName),n=t.expression,i=e[1].split(":"),s=i[0].trim(),r=i.length>1?i[1].trim():"[]",l=$.split("__property__").join(this._property).split("__exp__").join(n).split("__true__").join(s).split("__false__").join(r);this._expObj=crsbinding.expression.compile(l,["element"],{sanitize:!1,ctxName:this._ctxName}),this.listenOnPath(t.properties,this._eventHandler)}propertyChanged(){crsbinding.idleTaskManager.add(this._expObj.function(this._context,this._element))}}class M extends v{constructor(e,t,n,i,s){super(e,t,n,i,s)}dispose(){crsbinding.expression.release(this._expObj),delete this._expObj,this._eventHandler=null,super.dispose()}async initialize(){this._eventHandler=this.propertyChanged.bind(this);const e=crsbinding.expression.sanitize(this._value,this._ctxName),t=e.expression.split("?"),n=t[0].trim(),i=t[1].split(":"),s=i[0].trim(),r=i.length>1?i[1].trim():'""',l="requestAnimationFrame(() => element.__property__ = (__exp__) ? __true__ : __false__)".split("__property__").join(this._property).split("__exp__").join(n).split("__true__").join(s).split("__false__").join(r);this._expObj=crsbinding.expression.compile(l,["element"],{sanitize:!1,ctxName:this._ctxName}),this.listenOnPath(e.properties,this._eventHandler)}propertyChanged(){crsbinding.idleTaskManager.add(this._expObj.function(this._context,this._element))}}class S{static bind(e,t,n,i,s){return-1!=["value","checked"].indexOf(n)?new E(e,t,n,i,s):this["one-way"](e,t,n,i,s)}static"two-way"(e,t,n,i,s){return this.bind(e,t,n,i,s)}static"one-way"(e,t,n,i,s){return new A(e,t,n,i,s)}static once(e,t,n,i,s){return C(e,t,n,i,s)}static call(e,t,n,i,s){return new N(e,t,n,i,s)}static delegate(e,t,n,i,s){return new N(e,t,n,i,s)}static inner(e,t,n,i,s){return new H(e,t,n,i,s)}static for(e,t,n,i,s){return new z(e,t,n,i,s)}static if(e,t,n,i,s){return"classlist"==n.toLowerCase()?new I(e,t,n,i,s):-1!=n.toLowerCase().indexOf("style.")?new M(e,t,n,i,s):new L(e,t,n,i,s)}static attr(e,t,n,i,s){return new P(e,t,n,i,s)}}function D(e,t,n="context"){for(let i of e||[])R(i,t,n)}function R(e,t,n="context"){D(e.children,t,n),function(e,t,n){for(let i of e)q(i,t,n)}(Array.from(e.attributes||[]).filter(e=>"TEMPLATE"==e.ownerElement.tagName&&"for"==e.name||-1!=e.name.indexOf(".")||0==(e.value||"").indexOf("${")),t,n),e.children&&0==e.children.length&&-1!=(e.innerText||"").indexOf("${")&&S.inner(e,t,null,null,n)}function q(e,t,n){const i=e.name.split(".");let s=2==i.length?i[0]:i.slice(0,i.length-1).join("."),r="for"==s?s:i[i.length-1];0==s.length&&"$"==e.value[0]&&(s=r,r="attr");const l=S[r](e.ownerElement,t,s,e.value,n);return e.ownerElement.removeAttribute(e.nodeName),l}function V(e){crsbinding.providerManager.releaseElement(e)}globalThis.requestIdleCallback=globalThis.requestIdleCallback||function(e){const t=Date.now();return setTimeout((function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})}),1)},globalThis.cancelIdleCallback=globalThis.cancelIdleCallback||function(e){clearTimeout(e)};function B(e){if(0==e.__isProxy)return;if(Array.isArray(e))return U(e);const t=e.constructor.properties||Object.keys(e).filter(e=>-1==e.indexOf("__")&&"__isProxy"!=e);for(let n of t)crsbinding.events.notifyPropertyChanged(e,n),Array.isArray(e[n])&&U(e[n])}function U(e){e.forEach(e=>B(e))}function Q(e,t,n){crsbinding.events.on(e,t.trim(),n)}function W(e,t){this.addEventListener(e,t),this._domEvents.push({event:e,callback:t})}function G(e,t){const n=this._domEvents.find(n=>n.event==e&&n.callback==t);null!=n&&(this.removeEventListener(n.event,n.callback),this._domEvents.splice(this._domEvents.indexOf(n),1),n.callback=null,n.event=null)}class J{constructor(){this.inflateSrc=[],this.deflateSrc=[]}dispose(){this.inflateSrc=null,this.deflateSrc=null}generateCodeFor(e){const t=e.content.children[0];this.path="element",this._processElement(t);const n=this.inflateSrc.join("\n"),i=this.deflateSrc.join("\n");return{inflate:new Function("element","context",n),deflate:new Function("element","context",i)}}_processElement(e){this._processInnerText(e),this._processAttributes(e);const t=this.path;for(let n=0;n<e.children.length;n++)this.path=`${t}.children[${n}]`,this._processElement(e.children[n])}_processInnerText(e){const t=(e.innerHTML||"").trim();if(0==t.indexOf("${")){let e=t.substr(2,t.length-3);e=crsbinding.expression.sanitize(e).expression,this.inflateSrc.push(`${this.path}.innerText = ${e};`),this.deflateSrc.push(`${this.path}.innerText = "";`)}}_processAttributes(e){const t=Array.from(e.attributes).filter(e=>-1!=e.value.indexOf("${")||-1!=e.name.indexOf(".if"));for(let e of t)-1!=e.value.indexOf("${")?this._processAttrValue(e):this._processAttrCondition(e)}_processAttrValue(e){const t=e.value.trim();let n=t.substr(2,t.length-3);n=crsbinding.expression.sanitize(n).expression,this.inflateSrc.push(`${this.path}.setAttribute("${e.name}", ${n});`),this.deflateSrc.push(`${this.path}.removeAttribute("${e.name}");`)}_processAttrCondition(e){return 0==e.name.trim().indexOf("style")?this._processStyle(e):0==e.name.trim().indexOf("classlist")?this._processClassList(e):-1!=e.name.trim().indexOf(".if")?this._processConditional(e):void 0}_processStyle(e){const t=e.name.split(".")[1],n=crsbinding.expression.sanitize(e.value.trim()).expression;this.inflateSrc.push(`${this.path}.style.${t} = ${n};`),this.deflateSrc.push(`${this.path}.style.${t} = "";`),e.ownerElement.removeAttribute(e.name)}_processClassList(e){const t=e.value.split("?"),n=crsbinding.expression.sanitize(t[0]).expression,i=t[1].split(":"),s=i[0].trim(),r=i.length>1?i[1].trim():"",l=-1==s.indexOf("[")?s:`...${s}`;let o=`if (${n}) {${this.path}.classList.add(${l});}`;if(r.length>0){let e=-1==r.indexOf("[")?r:`...${r}`;o+=`else {${this.path}.classList.add(${e});}`}const a=`while (${this.path}.classList.length > 0) {${this.path}.classList.remove(${this.path}.classList.item(0));}`;this.inflateSrc.push(o),this.deflateSrc.push(a),e.ownerElement.removeAttribute(e.name)}_processConditional(e){const t=e.name.split(".if")[0].trim(),n=e.value.split("?");let i=[`if(${crsbinding.expression.sanitize(n[0].trim()).expression})`];const s=n.length>1?n[1].trim():`"${t}"`;if(-1==s.indexOf(":"))i.push("{"),i.push(`${this.path}.setAttribute("${t}", ${s});`),i.push("}"),i.push(`else {${this.path}.removeAttribute("${t}")}`);else{const e=n[1].split(":");i.push("{"),i.push(`${this.path}.setAttribute("${t}", ${e[0].trim()});`),i.push("}"),i.push(`else {${this.path}.setAttribute("${t}", ${e[1].trim()})}`)}this.inflateSrc.push(i.join("")),this.deflateSrc.push(`${this.path}.removeAttribute("${t}")`),e.ownerElement.removeAttribute(e.name)}}String.prototype.capitalize=function(){return this.charAt(0).toUpperCase()+this.slice(1)};const K={_expFn:new Map,idleTaskManager:new class{constructor(){this.processing=!1,this._list=[]}dispose(){this._list=null}add(e){e&&this._list.push(e),!this.processing&&this._processQueue()}_processQueue(){if(null==requestIdleCallback)return this._runNextFunction();this.processing=!0,requestIdleCallback(e=>{for(;(e.timeRemaining()>0||e.didTimeout)&&this._list.length;)this._runNextFunction();this.processing=!1},{timeout:1e3})}_runNextFunction(){let e=this._list.shift();e&&e()}},providerManager:new class{constructor(){this._nextId=0,this.items=new Map}async register(e){e.id=this._nextId,null==e._element.__providers&&Reflect.set(e._element,"__providers",[]),e._element.__providers.push(this._nextId),this.items.set(this._nextId,e),this._nextId+=1}async releaseElement(e){for(let t of e.children||[])await this.releaseElement(t);if(null!=e.__providers){for(let t of e.__providers){const e=this.items.get(t);this.items.delete(t),e&&e.dispose()}e.__providers=null}}},inflationManager:new class{constructor(){this._items=new Map}dispose(){this._items.clear(),this._items=null}register(e,t){const n=new J,i=n.generateCodeFor(t);n.dispose(),this._items.set(e,{template:t,inflate:i.inflate,deflate:i.deflate})}unregister(e){const t=this._items.get(e);null!=t&&(t.template=null,t.inflate=null,t.defaulte=null,this._items.delete(e))}get(e,t){const n=this._items.get(e);if(null==n)return null;const i=document.createDocumentFragment();for(let s of t){const t=n.template.content.cloneNode(!0);this.inflate(e,t.children[0],s,n.inflate),i.appendChild(t)}return i}inflate(e,t,n,i=null){(i||this._items.get(e).inflate)(t,n)}deflate(e,t){const n=this._items.get(e).deflate;if(Array.isArray(t))for(let e of t)n(e);else n(t)}},expression:{sanitize:function(e,t="context"){const n="context"!=t,i=`${t}.`,s=function(e,t){let n=[],i=[],s=!1;for(let t=0;t<e.length;t++){const r=e[t];1==s&&"$"==r&&"{"==e[t+1]&&(s=!1),1==s?-1==m.indexOf(r)?i.push(r):(g(n,i,r),s=!1):-1!=u.indexOf(r)?(g(n,i,r),-1!=m.indexOf(r)&&(s=!0)):i.push(r)}i.length>0&&n.push(i.join(""));null!=t&&(n=function e(t,n){const i=t.indexOf(n);if(-1==i)return t;"."==t[i+1]&&(t.splice(i,2),-1!=t.indexOf(n)&&e(t,n));return t}(n,t));return n}(e,n?t:null);if(1==s.length)return{isLiteral:!1,expression:`${i}${s[0]}`,properties:[e]};const r=[],l=-1!=e.indexOf("${");let o=null,a=[],_=[];for(let e=0;e<s.length;e++){const t=s[e];-1!=x.indexOf(o)||-1!=u.indexOf(t)&&-1==f.indexOf(t)?(o=t,a.length>0&&(0!=l&&"}"!=o||isNaN(a)&&(_.push(e-a.length),r.push(d(`${a.join("")}`))),a.length=0)):(a.push(t),o=t)}n&&a.length>0&&(0!=l&&"}"!=o||isNaN(a)&&(_.push(s.length-1),r.push(d(`${a.join("")}`)))),0==_.length&&-1!=e.indexOf(".")&&_.push(0);for(let e=0;e<_.length;e++)s.splice(e+_[e],0,i);return{isLiteral:l,expression:s.join(""),properties:r}},compile:t,release:function(e){if(null==e||"object"!=typeof e)return;const t=e.parameters.expression;if(crsbinding._expFn.has(t)){const e=crsbinding._expFn.get(t);e.count-=1,0==e.count&&(e.function=null,e.parameters=null,crsbinding._expFn.delete(t))}},updateUI:B},observation:{observe:function(e,t){if(e[a]=!0,crsbinding.events.enableEvents(e),Array.isArray(e))return n(e);e.__backup={},null!=t&&(e.__events=t.__events,delete t.__events);const i=Object.keys(e);for(let t of i)Array.isArray(e[t])&&(e[t]=n(e[t]));return new Proxy(e,{get:c,set:h})},releaseObserved:_,releaseBinding:V,releaseChildBinding:function(e){for(let t of e.children)V(t)}},parsers:{parseElement:R,parseElements:D},events:{enableEvents:function(e){e.__events=new Map,e.__conditions=new Map},disableEvents:function(e){null!=e.__events&&(e.__events.forEach(e=>{e.length=0}),e.__events.clear(),delete e.__events),e.__conditions&&(e.__conditions.forEach(e=>{delete e.fn,delete e.properties}),e.__conditions.clear(),delete e.__conditions)},when:function(e,n,i){let s=e.__events.get(n)||[];s=[...s,i],e.__events.set(n,s);const r=t(n);let l=e.__conditions.get(n);if(null==l){l={fn:()=>{if(1==r.function(e))for(let e of s)e()},properties:r.parameters.properties.slice(0)},e.__conditions.set(n,l)}const o=r.parameters.properties;for(let t of o)crsbinding.events.on(e,t,l.fn)},on:function(e,t,n){if(null==e||null==e.__events)return;let i=e.__events.get(t)||[];i=[...i,n],e.__events.set(t,i)},notifyPropertyChanged:function(e,t,n){if(null==e.__events||0==e.__events.has(t))return;const i=e.__events.get(t);for(let s of i)s(t,e[t],n);const s=`${t}Changed`;null!=e[s]&&e[s].call(e,n)},removeOn:function(e,t,n){if(null==e||null==e.__events)return;const i=e.__events.get(t)||[],s=i.indexOf(n);-1!=s&&(i.splice(s,1),e.__events.set(t,i)),0==i.length&&e.__events.delete(t)},removeWhen:function(e,t,n){crsbinding.events.removeOn(e,t,n);const i=e.__conditions.get(t);for(let t of i.properties)crsbinding.events.removeOn(e,t,i.fn);delete i.fn,delete i.properties,e.__conditions.delete(t)},listenOn:Q,listenOnPath:function(e,t,n){let i=e;const s=t.split(".");for(let e=0;e<s.length;e++){const t=s[e];e==s.length-1?Q(i,t,n):(null==i[t]&&(i[t]=crsbinding.observation.observe({})),Q(i,t,n),i=i[t])}}},dom:{enableEvents:function(e){e._domEvents=[],e.registerEvent=W,e.unregisterEvent=G},disableEvents:function(e){if(null!=e._domEvents){for(let t of e._domEvents)t.callback=null,t.event=null;e._domEvents.length=0,delete e._domEvents,delete e.registerEvent,delete e.unregisterEvent}}},utils:{capitalizePropertyPath:function(e){const t=e.split("-");for(let e=1;e<t.length;e++)t[e]=t[e].capitalize();return t.join("")}}};globalThis.crsbinding=K;export{K as crsbinding};
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
function compileExp(exp, parameters, options) {
parameters = parameters || [];
let sanitize = true;
let async = false;
let ctxName = "context";
if (options != null) {
if (options.sanitize != null) sanitize = options.sanitize;
if (options.async != null) async = options.async;
if (options.ctxName != null) ctxName = options.ctxName;
}
if (crsbinding._expFn.has(exp)) {
const x = crsbinding._expFn.get(exp);
x.count += 1;
return x;
}
let src = exp;
let san;
if (sanitize == true) {
san = crsbinding.expression.sanitize(exp, ctxName);
if (crsbinding._expFn.has(san.expression)) {
const x = crsbinding._expFn.get(san.expression);
x.count += 1;
return x;
}
src = san.isLiteral === true ? ["return `", san.expression, "`"].join("") : `return ${san.expression}`;
const parts = san.expression.split(".");
if (parts.length > 2) {
src = `try { ${src} } catch(error) { return null }`;
}
}
else {
san = {
expression: exp
};
}
const fn = async == true ? new AsyncFunction(ctxName, ...parameters, src) : new Function(ctxName, ...parameters, src);
const result = {
function: fn,
parameters: san,
count: 1
};
crsbinding._expFn.set(san.expression, result);
return result;
}
function releaseExp(exp) {
if (exp == null || typeof exp != "object") return;
const key = exp.parameters.expression;
if (crsbinding._expFn.has(key)) {
const x = crsbinding._expFn.get(key);
x.count -= 1;
if (x.count == 0) {
x.function = null;
x.parameters = null;
crsbinding._expFn.delete(key);
}
}
}
function enableEvents(obj) {
obj.__events = new Map();
obj.__conditions = new Map();
}
function disableEvents(obj) {
if (obj.__events != null) {
obj.__events.forEach((ev) => {
ev.length = 0;
});
obj.__events.clear();
delete obj.__events;
}
if (obj.__conditions) {
obj.__conditions.forEach((cnd) => {
delete cnd.fn;
delete cnd.properties;
});
obj.__conditions.clear();
delete obj.__conditions;
}
}
function when(obj, exp, callback) {
let functions = obj.__events.get(exp) || [];
functions = [...functions, callback];
obj.__events.set(exp, functions);
const cmp = compileExp(exp);
let cond = obj.__conditions.get(exp);
if (cond == null) {
const fn = () => {
if (cmp.function(obj) == true) {
for (let call of functions) {
call();
}
}
};
cond = {fn: fn, properties: cmp.parameters.properties.slice(0)};
obj.__conditions.set(exp, cond);
}
const properties = cmp.parameters.properties;
for (let property of properties) {
crsbinding.events.on(obj, property, cond.fn);
}
}
function removeWhen(obj, exp, callback) {
crsbinding.events.removeOn(obj, exp, callback);
const cnd = obj.__conditions.get(exp);
for (let property of cnd.properties) {
crsbinding.events.removeOn(obj, property, cnd.fn);
}
delete cnd.fn;
delete cnd.properties;
obj.__conditions.delete(exp);
}
function on(obj, property, callback) {
if (obj == null || obj.__events == null) return;
let functions = obj.__events.get(property) || [];
functions = [...functions, callback];
obj.__events.set(property, functions);
}
function removeOn(obj, property, callback) {
if (obj == null || obj.__events == null) return;
const functions = obj.__events.get(property) || [];
const index = functions.indexOf(callback);
if (index != -1) {
functions.splice(index, 1);
obj.__events.set(property, functions);
}
if (functions.length == 0) {
obj.__events.delete(property);
}
}
function notifyPropertyChanged(obj, property, args) {
if (obj.__events == null || obj.__events.has(property) == false) return;
callFunctions(obj.__events.get(property), obj, property, args);
if (obj.__elEvents) {
callFunctions(obj.__elEvents.get(property), obj, property, args);
}
const changedFnName = `${property}Changed`;
if (obj[changedFnName] != null) {
obj[changedFnName].call(obj, args);
}
}
function callFunctions(functions, obj, property, args) {
for(let fn of functions) {
fn(property, obj[property], args);
}
}
const ISARRAY = "__isArray";
function observeArray(collection, persistent = false) {
collection[ISARRAY] = true;
if (collection._events == null) {
crsbinding.events.enableEvents(collection);
}
collection.__nextId = 1;
collection.__persistent = persistent;
for (let i = 0; i < collection.length; i++) {
observeIndex(collection, i);
}
const proxy = new Proxy(collection, {
get: get
});
return proxy;
}
function releaseObservedArray(collection, force = false) {
crsbinding.events.disableEvents(collection);
collection.forEach(item => crsbinding.observation.releaseObserved(item, force));
}
const deleteFunctions = ["pop", "splice"];
const addFunctions = ["push"];
function get(collection, prop) {
const value = collection[prop];
if (typeof value == "function") {
return (...args) => {
const result = collection[prop](...args);
if (deleteFunctions.indexOf(prop) != -1) {
itemsRemoved(collection, result);
if (prop == "splice" && args.length > 2) {
args = args.splice(2, args.length);
itemsAdded(collection, args);
}
}
else if (addFunctions.indexOf(prop) != -1) {
itemsAdded(collection, args);
}
return result;
}
}
return value;
}
function itemsRemoved(collection, items) {
if (items == null) return;
crsbinding.events.notifyPropertyChanged(collection, "items-deleted", items);
if (Array.isArray(items)) {
for (let item of items) {
crsbinding.observation.releaseObserved(item);
}
}
else {
crsbinding.observation.releaseObserved(items);
}
}
function itemsAdded(obj, items) {
if (items == null) return;
const payload = {
items: [],
indexes: []
};
for (let item of items) {
const index = obj.indexOf(item);
observeIndex(obj, index);
payload.items.push(item);
payload.indexes.push(index);
}
crsbinding.events.notifyPropertyChanged(obj, "items-added", payload);
}
function observeIndex(collection, index) {
const item = collection[index];
item.__uid = collection.__nextId;
collection.__nextId++;
if (item.__isProxy != true) {
collection[index] = crsbinding.observation.observe(item, null, collection.__persistent);
}
}
const PROXY = "__isProxy";
const BACKUP = "__backup";
/**
* Start observing an object for property changes.
* This will turn the object into a proxy and enable events and conditions.
* Mark the object as persistent using the persistent parameter if you don't want it to be cleaned when replaced with another objects.
* @param obj
* @param prior
* @param persistent
* @returns {*}
*/
function observe(obj, prior, persistent = false) {
obj[PROXY] = true;
crsbinding.events.enableEvents(obj);
if (Array.isArray(obj)) return observeArray(obj, persistent);
obj[BACKUP] = {};
if (prior != null) {
obj.__events = prior.__events;
delete prior.__events;
}
obj.__persistent = persistent;
const keys = Object.keys(obj);
for (let key of keys) {
if (Array.isArray(obj[key])) {
obj[key] = observeArray(obj[key]);
}
}
const proxy = new Proxy(obj, {
get: get$1,
set: set
});
return proxy;
}
/**
* Release a object's binding properties to clean up memory
* if the object's __persistent field is true, it will not be released unless force is true.
* This helps the system bypass persistent objects being used between multiple UI parts
* @param obj: <any> object to release, must be a proxy
* @param force: <boolean> force cleanup.
*/
function releaseObserved(obj, force = false) {
if (obj.__persistent == true && force != true) return;
if (obj.__isArray == true) return releaseObservedArray(obj, force);
crsbinding.events.disableEvents(obj);
if (obj.dispose != null) {
obj._disposing = true;
obj.dispose();
}
const properties = Object.getOwnPropertyNames(obj);
for (let prop of properties) {
if (prop.indexOf("__") == 0 || (prop.indexOf("Changed") != -1 && typeof obj[prop] == "function")) {
delete obj[prop];
}
else if (obj[prop] && obj[prop][PROXY] == true) {
releaseObserved(obj[prop]);
delete obj[prop];
}
}
}
/**
* Standard get function for proxy actions
* @param obj
* @param prop
* @returns {*}
*/
function get$1(obj, prop) {
return obj[prop];
}
/**
* Standard set operation for proxy actions
* @param obj
* @param prop
* @param value
* @returns {boolean}
*/
function set(obj, prop, value) {
if (prop == "_disposing" || obj._disposing == true) return true;
if (prop.indexOf("__") != -1) {
obj[prop] = value;
}
else {
setSingle(obj, prop, value);
}
return true;
}
const excludeBackup = ["__isProxy", "element"];
function setSingle(obj, prop, value) {
obj.__processing = true;
const backup = obj[BACKUP];
const oldValue = obj[prop];
obj[prop] = createProxyValue(obj[prop], value);
crsbinding.events.notifyPropertyChanged(obj, prop);
if (obj.propertyChanged != null) {
obj.propertyChanged(value, oldValue);
}
if (isProxy(oldValue)) {
// Need to put a marker to say DON"T RELEASE THIS YET
releaseObserved(oldValue);
}
else {
if (excludeBackup.indexOf(prop) == -1 && prop.indexOf("__") == -1 && oldValue != null) {
backup[prop] = oldValue;
}
}
delete obj.__processing;
}
function createProxyValue(origional, value) {
if (value == null) return null;
let result = value;
if (origional && origional.__isProxy == true) {
if (result && result.__isProxy != true) {
result = crsbinding.observation.observe(result, origional);
}
else if (result && origional) {
copyOverEvents(result, origional);
}
// Process properties and make them observed if they are required.
// Used to ensure object path bindings.
if (Array.isArray(value) != true) {
const properties = Object.getOwnPropertyNames(origional).filter(item => item.indexOf("__") == -1);
for (let property of properties) {
if (origional[property][PROXY] == true && result[property][PROXY] != true) {
const nc = crsbinding.observation.observe(result[property], origional[property]);
result.__processing = true;
delete result[property];
result[property] = nc;
delete result.__processing;
}
}
}
}
return result;
}
function isProxy(obj) {
return obj && typeof obj == "object" && obj[PROXY] == true;
}
function copyOverEvents(target, source) {
/**
* In some cases like using a item between a list and a bindable element, you need to maintain the origional events.
* Only copy events over in cases when it is null because those are the cases where you have a single use case.
* The __events object is removed on releasing of the old object.
*/
if (target.__events == null) {
target.__events = source.__events;
delete source.__events;
}
}
/**
* Contextualize a expression and extract the properties defined in the expression
* @param exp
* @returns {{expression: *, properties: *}}
*/
function sanitizeExp(exp, ctxName = "context") {
const namedExp = ctxName != "context";
const prefix = `${ctxName}.`;
const tokens = tokenize(exp, namedExp ? ctxName : null);
if (tokens.length == 1) {
return {
isLiteral: false,
expression: `${prefix}${tokens[0]}`,
properties: [exp]
}
}
const properties = [];
const isLiteral = exp.indexOf("${") != -1;
let oldToken = null;
let path = [];
let indexes = [];
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (quotes.indexOf(oldToken) != -1 || (reserved.indexOf(token) != -1 && ignore.indexOf(token) == -1))
{
oldToken = token;
if (path.length > 0) {
if (isLiteral == false || oldToken == "}") {
if (isNaN(path)) {
indexes.push(i - path.length);
properties.push(extractProperty(`${path.join("")}`));
}
}
path.length = 0;
}
continue;
}
path.push(token);
oldToken = token;
}
if (namedExp && path.length > 0) {
if (isLiteral == false || oldToken == "}") {
if (isNaN(path)) {
indexes.push(tokens.length - 1);
properties.push(extractProperty(`${path.join("")}`));
}
}
}
if (indexes.length == 0 && exp.indexOf(".") != -1) {
indexes.push(0);
}
for (let i = 0; i < indexes.length; i++) {
tokens.splice(i + indexes[i], 0, prefix);
}
return {
isLiteral: isLiteral,
expression: tokens.join(""),
properties: properties
}
}
/**
* Extract the property path up to where a function is being called.
* @param property {string}
* @returns {string|*}
*/
function extractProperty(property) {
if (property.indexOf("(") == -1) return property;
const result = [];
for (let p of property.split(".")) {
if (p.indexOf("(") != -1) {
break;
}
result.push(p);
}
return result.join(".");
}
const reserved = ["true", "false", "-", "+", "=", "<", ">", "(", ")","{", "}", "/", "&", "|", "=", "!", "'", "`", '"', " ", "$", ".", ",", "?", ":", "null", "undefined"];
const ignore = [".", "(", ")", ","];
const quotes = ["'", '"', "`"];
const stdQuotes = ["'", '"'];
/**
* Break the expression into expression tokens
* @param exp
* @returns {[]}
*/
function tokenize(exp, ctxName) {
let tokens = [];
let word = [];
let isString = false;
for (let i = 0; i < exp.length; i++) {
const char = exp[i];
if (isString == true && char == "$" && exp[i + 1] == "{") {
isString = false;
}
if (isString == true) {
if (stdQuotes.indexOf(char) == -1) {
word.push(char);
}
else {
pushToken(tokens, word, char);
isString = false;
}
}
else if (reserved.indexOf(char) != -1) {
pushToken(tokens, word, char);
if (stdQuotes.indexOf(char) != -1) {
isString = true;
}
}
else {
word.push(char);
}
}
if (word.length > 0) {
tokens.push(word.join(""));
}
if (ctxName != null) {
tokens = removeNamedCtx(tokens, ctxName);
}
return tokens;
}
function removeNamedCtx(collection, ctxName) {
const index = collection.indexOf(ctxName);
if (index == -1) return collection;
if (collection[index + 1] == ".") {
collection.splice(index, 2);
if (collection.indexOf(ctxName) != -1) {
removeNamedCtx(collection, ctxName);
} }
return collection;
}
function pushToken(tokens, word, char) {
if (word.length > 0) {
tokens.push(word.join(""));
word.length = 0;
}
tokens.push(char);
return false;
}
class ProviderBase {
constructor(element, context, property, value, ctxName) {
this._element = element;
this._context = context;
this._property = property;
this._value = value;
this._ctxName = ctxName || "context";
this._eventsToRemove = [];
this._isNamedContext = this._ctxName != "context";
crsbinding.providerManager.register(this);
this.initialize().catch(error => {
throw error;
});
if (this._element.nodeName.indexOf("-") != -1 && this._property == this._ctxName) {
this._element[this._property] = this._context;
}
}
dispose() {
this._eventsToRemove.forEach(event => {
crsbinding.events.removeOn(this._context, event.value, event.callback);
});
this._eventsToRemove.length = 0;
this._eventsToRemove = null;
this._element = null;
this._context = null;
this._property = null;
this._value = null;
this._ctxName = null;
}
/**
* Override to perform starting process
*/
async initialize() {
}
listenOnPath(value, callback) {
if (Array.isArray(value) == true) {
for (let v of value) {
this.listenOnPath(v, callback);
}
return;
}
if (this._isNamedContext) {
value = value.replace(`${this._ctxName}.`, "");
}
if (value.indexOf(".") == -1) {
crsbinding.events.listenOn(this._context, value, callback);
}
else {
crsbinding.events.listenOnPath(this._context, value, callback);
}
this._eventsToRemove.push({
value: value,
callback: callback
});
}
removeOn(value, callback) {
crsbinding.events.removeOn(this._context, value, callback);
}
}
const setElementProperty = `requestAnimationFrame(() => element.__property__ = value);`;
const setElementValueProperty = `requestAnimationFrame(() => element.__property__ = value == null ? "" : value);`;
const setElementConditional = "requestAnimationFrame(() => element.__property__ = (__exp__) ? __true__ : __false__)";
const setDataset = `element.dataset["__property__"] = value == null ? "" : value`;
const setClassListRemove = `
if (element.__classList!=null) {
const remove = Array.isArray(element.__classList) ? element.__classList : [element.__classList];
remove.forEach(cls => element.classList.remove(cls));
}`;
const setClassListValue = `
element.__classList = value;
const add = Array.isArray(value) ? value : [value];
add.forEach(cls => element.classList.add(cls));`;
const setClassList = `${setClassListRemove} ${setClassListValue}`;
const setClassListCondition = `
${setClassListRemove}
if (__exp__) {
${setClassListValue.split("value").join("__true__")}
}
else {
${setClassListValue.split("value").join("__false__")}
}
`;
class OneWayProvider extends ProviderBase {
dispose() {
const contextPrefix = `${this._ctxName}.`;
if (this._value.indexOf(contextPrefix) == 0) {
this._value = this._value.replace(contextPrefix, "");
}
this.removeOn(this._value, this._eventHandler);
if (this._expObj != null) {
crsbinding.expression.release(this._expObj);
delete this._expObj;
}
if (this._getObj != null) {
crsbinding.expression.release(this._getObj);
delete this._getObj;
}
this._exp = null;
this._eventHandler = null;
super.dispose();
}
async initialize() {
if (this._value == "$context") {
return this.setContext();
}
this._eventHandler = this.propertyChanged.bind(this);
this._exp = getExpForProvider(this);
this._expObj = crsbinding.expression.compile(this._exp, ["element", "value"], {sanitize: false, ctxName: this._ctxName});
if (this._value.indexOf(".") != -1) {
this._getObj = crsbinding.expression.compile(this._value, null, {ctxName: this._ctxName});
}
this.listenOnPath(this._value, this._eventHandler);
const v = this._ctxName == "context" ? this._context[this._value] : this._context;
this.propertyChanged(null, v);
}
setContext() {
if (this._element != null && this._property != null) {
this._element[this._property] = this._context;
}
}
propertyChanged(prop, value) {
let v = value;
if (this._getObj != null) {
v = this._getObj.function(this._context);
}
crsbinding.idleTaskManager.add(this._expObj.function(this._context, this._element, v));
}
}
function getExpForProvider(provider) {
let result;
if (provider._property.toLocaleLowerCase() == "classlist") {
return setClassList;
}
if (provider._property.indexOf("data-") != -1) {
const prop = provider._property.replace("data-", "");
return setDataset.split("__property__").join(prop);
}
result = provider._property == "value" ? setElementValueProperty : setElementProperty;
provider._property = crsbinding.utils.capitalizePropertyPath(provider._property);
return result.split("__property__").join(provider._property);
}
class BindProvider extends OneWayProvider {
dispose() {
this._element.removeEventListener("change", this._changeHandler);
this._changeHandler = null;
crsbinding.expression.release(this._setObj);
delete this._setObj;
super.dispose();
}
async initialize() {
await super.initialize();
this._changeHandler = this._change.bind(this);
this._element.addEventListener("change", this._changeHandler);
const exp = this._isNamedContext == true ? `${this._value} = value` : `context.${this._value} = value`;
this._setObj = crsbinding.expression.compile(exp, ["value"], {sanitize: false, ctxName: this._ctxName});
}
_change(event) {
let value = event.target[this._property];
const type = event.target.type || "text";
const typeFn = `_${type}`;
if (this[typeFn] != null) {
value = this[typeFn](value, event.target);
}
this._setObj.function(this._context, value);
event.stopPropagation();
}
_number(value) {
return Number(value);
}
_date(value) {
return new Date(value);
}
_checkbox(value, element) {
return element.checked == true;
}
}
function OnceProvider(element, context, property, value, ctxName = "context") {
if (ctxName == "context") {
setContext(element, context, property, value);
}
else {
setItem(element, context, property, value, ctxName);
}
return null;
}
function setContext(element, context, property, value) {
const fn = new Function("context", `return context.${value}`);
setProperty(element, property, fn(context));
}
function setItem(element, context, property, value, ctxName) {
const code = value.indexOf(ctxName) == 0 ? `return ${value}` : `return ${ctxName}.${value}`;
const fn = new Function(ctxName, code);
setProperty(element, property, fn(context));
}
function setProperty(element, property, value) {
if (property.indexOf("data-") == -1) {
property = crsbinding.utils.capitalizePropertyPath(property);
const fn = new Function("element", "value", `element.${property} = value`);
fn(element, value);
}
else {
const prop = property.replace("data-", "");
element.dataset[prop] = value;
}
}
class CallProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
this._eventHandler = this.event.bind(this);
this._element.addEventListener(this._property, this._eventHandler);
}
dispose() {
this._element.removeEventListener(this._property, this._eventHandler);
this._eventHandler = null;
this._fn = null;
super.dispose();
}
async initialize() {
let src = `context.${this._value}`.split("$event").join("event");
if (src.indexOf(")") == -1) {
src = `${src}.call(context)`;
}
this._fn = new Function("context", src);
}
event(event) {
crsbinding.idleTaskManager.add(this._fn(this._context));
event.stopPropagation();
}
}
class InnerProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
this._eventHandler = this._change.bind(this);
this._expObj = crsbinding.expression.compile(element.innerText, null, {ctxName: this._ctxName});
for (let prop of this._expObj.parameters.properties) {
this.listenOnPath(prop, this._eventHandler);
}
this._change();
}
dispose() {
crsbinding.expression.release(this._expObj);
this._expObj = null;
super.dispose();
this._eventHandler = null;
}
_change() {
if (this._expObj == null) return;
this._element.innerText = this._expObj.function(this._context);
}
}
class AttrProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
this._eventHandler = this._change.bind(this);
this._expObj = crsbinding.expression.compile(value, null, {ctxName: this._ctxName});
for (let prop of this._expObj.parameters.properties) {
this.listenOnPath(prop, this._eventHandler);
}
}
dispose() {
crsbinding.expression.release(this._expObj);
this._expObj = null;
super.dispose();
this._eventHandler = null;
}
_change() {
if (this._expObj == null) return;
const value = this._expObj.function(this._context);
this._element.setAttribute(this._property, value);
}
}
class ForProvider extends ProviderBase {
get ar() {
return this._ar;
}
set ar(newValue) {
if (this._ar != null) {
crsbinding.events.removeOn(this._ar, "items-added", this._itemsAddedHandler);
crsbinding.events.removeOn(this._ar, "items-deleted", this._itemsDeletedHandler);
}
this._ar = newValue;
if (this._ar != null) {
crsbinding.events.on(this._ar, "items-added", this._itemsAddedHandler);
crsbinding.events.on(this._ar, "items-deleted", this._itemsDeletedHandler);
}
}
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
this._itemsAddedHandler = this._itemsAdded.bind(this);
this._itemsDeletedHandler = this._itemsDeleted.bind(this);
}
dispose() {
this.ar = null;
crsbinding.expression.release(this._forExp);
this._forExp = null;
this._itemsAddedHandler = null;
this._itemsDeletedHandler = null;
this._singular = null;
this._plural = null;
this._container = null;
this._collectionChangedHandler = null;
super.dispose();
}
async initialize() {
// 1. get the container and remove the template
this._container = this._element.parentElement;
this._container.removeChild(this._element);
// 2. get the properties to work with and build the for loop
const parts = this._value.split("of");
this._singular = parts[0].trim();
this._plural = parts[1].trim();
const forExp = repeatCode
.split("_p").join(this._singular)
.split("_c").join(this._ctxName == "context" ? `context.${this._plural}` : this._plural);
this._forExp = crsbinding.expression.compile(forExp, ["callback"], {sanitize: false, async: true, ctxName: this._ctxName});
// 3. listen to the collection property on the context changing
this._collectionChangedHandler = this._collectionChanged.bind(this);
this.listenOnPath(this._plural, this._collectionChangedHandler);
}
async _collectionChanged(property, newValue) {
if (Array.isArray(newValue)) {
this.ar = newValue;
}
else {
const fn = new Function("context", `return context.${this._plural}`);
this.ar = fn(this._context);
}
if (this.ar != null) {
await this._renderItems();
}
}
async _renderItems() {
// release the old content
await crsbinding.observation.releaseChildBinding(this._container);
if (this.ar == null) return;
// create document fragment
const fragment = document.createDocumentFragment();
// loop through items and add them to fragment after being parsed
await this._forExp.function(this._context, (item) => {
const element = this.createElement(item);
fragment.appendChild(element);
});
this._container.innerHTML = "";
this._container.appendChild(fragment);
// render the updates. custom components are not ready at this time yet. so do it on the next frame.
crsbinding.expression.updateUI(this.ar);
// update the container's provider to this so that this can be freed when content changes
if (this._container.__providers == null) {
this._container.__providers = [];
}
if (this._container.__providers.indexOf(this.id) == -1) {
this._container.__providers.push(this.id);
}
}
_itemsAdded(event, value, added) {
for (let i = 0; i < added.items.length; i++) {
const item = added.items[i];
const index = added.indexes[i];
const element = this.createElement(item);
const update = element.children[0];
const child = this._container.children[index];
this._container.insertBefore(element, child);
for (let p of update.__providers || []) {
const provider = crsbinding.providerManager.items.get(p);
if (provider instanceof AttrProvider) {
provider._change();
}
}
crsbinding.expression.updateUI(item);
}
}
_itemsDeleted(event, value, removed) {
const elements = [];
const push = (item) => {
const uid = item.__uid;
const result = this._container.querySelectorAll([`[data-uid="${uid}"]`]);
result.forEach(element => elements.push(element));
};
if (Array.isArray(removed)) {
for (let item of removed) {
push(item);
}
}
else {
push(removed);
}
for (let element of elements) {
if (element != null) {
element.parentElement.removeChild(element);
crsbinding.observation.releaseBinding(element);
}
}
}
createElement(item) {
const element = this._element.content.cloneNode(true);
crsbinding.parsers.parseElement(element, item, this._singular);
for (let child of element.children) {
child.dataset.uid = item.__uid;
}
return element;
}
}
const repeatCode = `for (_p of _c || []) {callback(_p);}`;
class IfProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
}
dispose() {
crsbinding.expression.release(this._expObj);
delete this._expObj;
this._eventHandler = null;
super.dispose();
}
async initialize() {
this._eventHandler = this.propertyChanged.bind(this);
if (this._value.indexOf("?") == -1) {
this._initCndAttr();
}
else if(this._value.indexOf(":") != -1) {
this._initCndValue();
}
else {
this._initCndAttrValue();
}
this.propertyChanged();
}
/**
* There is no value to be set.
* Add or remove the attribute.
* Used for hidden.bind or disabled.bind
* @private
*/
_initCndAttr() {
const value = crsbinding.expression.sanitize(this._value, this._ctxName);
const fnCode = initCndAttrExp
.split("__exp__").join(value.expression)
.split("__attr__").join(this._property)
.split("__attr-value__").join(this._property);
this._expObj = crsbinding.expression.compile(fnCode, ["element"], {sanitize: false, ctxName: this._ctxName});
this.listenOnPath(value.properties, this._eventHandler);
}
/**
* There is an attribute value that gets toggled do not remove the attribute
* @private
*/
_initCndValue() {
const value = crsbinding.expression.sanitize(this._value, this._ctxName);
const parts = value.expression.split("?");
const valueParts = parts[1].split(":");
const fnCode = initCndValueExp
.split("__exp__").join(parts[0].trim())
.split("__attr__").join(this._property)
.split("__true__").join(valueParts[0].trim())
.split("__false__").join(valueParts[1].trim());
this._expObj = crsbinding.expression.compile(fnCode, ["element"], {sanitize: false, ctxName: this._ctxName});
this.listenOnPath(value.properties, this._eventHandler);
}
/**
* if the expression passes set the attribute else remove the attribute
* @private
*/
_initCndAttrValue() {
const value = crsbinding.expression.sanitize(this._value, this._ctxName);
const parts = value.expression.split("?");
const fnCode = initCndAttrExp
.split("__exp__").join(parts[0].trim())
.split("__attr__").join(this._property)
.split("__attr-value__").join(parts[1].trim());
this._expObj = crsbinding.expression.compile(fnCode, ["element"], {sanitize: false, ctxName: this._ctxName});
this.listenOnPath(value.properties, this._eventHandler);
}
propertyChanged() {
crsbinding.idleTaskManager.add(this._expObj.function(this._context, this._element));
}
}
const initCndAttrExp = `
if (__exp__) {
element.setAttribute("__attr__", "__attr-value__");
}
else {
element.removeAttribute("__attr__");
}
`;
const initCndValueExp = `
if (__exp__) {
element.setAttribute("__attr__", "__true__");
}
else {
element.setAttribute("__attr__", "__false__");
}
`;
class IfClassProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
}
dispose() {
crsbinding.expression.release(this._expObj);
delete this._expObj;
this._eventHandler = null;
super.dispose();
}
async initialize() {
this._eventHandler = this.propertyChanged.bind(this);
const parts = this._value.split("?");
const value = crsbinding.expression.sanitize(parts[0], this._ctxName);
const condition = value.expression;
const values = parts[1].split(":");
const trueValue = values[0].trim();
const falseValue = values.length > 1 ? values[1].trim() : '[]';
const fnCode = setClassListCondition
.split("__property__").join(this._property)
.split("__exp__").join(condition)
.split("__true__").join(trueValue)
.split("__false__").join(falseValue);
this._expObj = crsbinding.expression.compile(fnCode, ["element"], {sanitize: false, ctxName: this._ctxName});
this.listenOnPath(value.properties, this._eventHandler);
}
propertyChanged() {
crsbinding.idleTaskManager.add(this._expObj.function(this._context, this._element));
}
}
class IfStylesProvider extends ProviderBase {
constructor(element, context, property, value, ctxName) {
super(element, context, property, value, ctxName);
}
dispose() {
crsbinding.expression.release(this._expObj);
delete this._expObj;
this._eventHandler = null;
super.dispose();
}
async initialize() {
this._eventHandler = this.propertyChanged.bind(this);
const value = crsbinding.expression.sanitize(this._value, this._ctxName);
const parts = value.expression.split("?");
const condition = parts[0].trim();
const values = parts[1].split(":");
const trueValue = values[0].trim();
const falseValue = values.length > 1 ? values[1].trim() : '""';
const fnCode = setElementConditional
.split("__property__").join(this._property)
.split("__exp__").join(condition)
.split("__true__").join(trueValue)
.split("__false__").join(falseValue);
this._expObj = crsbinding.expression.compile(fnCode, ["element"], {sanitize: false, ctxName: this._ctxName});
this.listenOnPath(value.properties, this._eventHandler);
}
propertyChanged() {
crsbinding.idleTaskManager.add(this._expObj.function(this._context, this._element));
}
}
class ProviderFactory {
static "bind"(element, context, property, value, ctxName) {
if (["value", "checked"].indexOf(property) != -1) {
return new BindProvider(element, context, property, value, ctxName)
}
else {
return this["one-way"](element, context, property, value, ctxName);
}
}
static "two-way"(element, context, property, value, ctxName) {
return this.bind(element, context, property, value, ctxName);
}
static "one-way"(element, context, property, value, ctxName) {
return new OneWayProvider(element, context, property, value, ctxName);
}
static "once"(element, context, property, value, ctxName) {
return OnceProvider(element, context, property, value, ctxName);
}
static "call"(element, context, property, value, ctxName) {
return new CallProvider(element, context, property, value, ctxName);
}
static "delegate"(element, context, property, value, ctxName) {
return new CallProvider(element, context, property, value, ctxName);
}
static "inner"(element, context, property, value, ctxName) {
return new InnerProvider(element, context, property, value, ctxName);
}
static "for"(element, context, property, value, ctxName) {
return new ForProvider(element, context, property, value, ctxName);
}
static "if"(element, context, property, value, ctxName) {
if (property.toLowerCase() == "classlist") {
return new IfClassProvider(element, context, property, value, ctxName);
}
if (property.toLowerCase().indexOf("style.") != -1) {
return new IfStylesProvider(element, context, property, value, ctxName);
}
return new IfProvider(element, context, property, value, ctxName);
}
static "attr"(element, context, property, value, ctxName) {
return new AttrProvider(element, context, property, value, ctxName);
}
}
function parseElements(collection, context, ctxName = "context") {
for (let element of collection || []) {
parseElement(element, context, ctxName);
}
}
function parseElement(element, context, ctxName = "context") {
parseElements(element.children, context, ctxName);
const attributes = Array.from(element.attributes || []);
const boundAttributes = attributes.filter(attr =>
(attr.ownerElement.tagName == "TEMPLATE" && attr.name == "for") ||
(attr.name.indexOf(".") != -1) ||
((attr.value || "").indexOf("${") == 0)
);
parseAttributes(boundAttributes, context, ctxName);
if (element.children && element.children.length == 0 && (element.innerText || "").indexOf("${") != -1) {
ProviderFactory["inner"](element, context, null, null, ctxName);
}
}
function parseAttributes(collection, context, ctxName) {
for (let attr of collection) {
parseAttribute(attr, context, ctxName);
}
}
function parseAttribute(attr, context, ctxName) {
const parts = attr.name.split(".");
let prop = parts.length == 2 ? parts[0] : parts.slice(0, parts.length -1).join(".");
let prov = prop == "for" ? prop : parts[parts.length - 1];
if (prop.length == 0 && attr.value[0] == "$") {
prop = prov;
prov = "attr";
}
const provider = ProviderFactory[prov](attr.ownerElement, context, prop, attr.value, ctxName);
attr.ownerElement.removeAttribute(attr.nodeName);
// used for testing
return provider;
}
function releaseBinding(element) {
crsbinding.providerManager.releaseElement(element);
}
function releaseChildBinding(element) {
for (let child of element.children) {
releaseBinding(child);
}
}
class ProviderManager {
constructor() {
this._nextId = 0;
this.items = new Map();
}
async register(provider) {
provider.id = this._nextId;
if (provider._element.__providers == null) {
Reflect.set(provider._element, "__providers", []);
}
provider._element.__providers.push(this._nextId);
this.items.set(this._nextId, provider);
this._nextId += 1;
}
async releaseElement(element) {
for (let child of element.children || []) {
await this.releaseElement(child);
}
if (element.__providers == null) return;
for (let id of element.__providers) {
const provider = this.items.get(id);
this.items.delete(id);
provider && provider.dispose();
}
element.__providers = null;
if (this.items.size == 0) {
this._nextId = 0;
}
}
}
globalThis.requestIdleCallback =
globalThis.requestIdleCallback ||
function (cb) {
const start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
}
});
}, 1);
};
globalThis.cancelIdleCallback =
globalThis.cancelIdleCallback ||
function (id) {
clearTimeout(id);
};
class IdleTaskManager {
constructor() {
this.processing = false;
this._list = [];
}
dispose() {
this._list = null;
}
/**
* Add a function to the manager to call once the system is idle
* @param fn {Function}
*/
add(fn) {
fn && this._list.push(fn);
!this.processing && this._processQueue();
}
/**
* Loop through the required functions and execute them in turn.
* @private
*/
_processQueue() {
if (requestIdleCallback == null) return this._runNextFunction();
this.processing = true;
requestIdleCallback(deadline => {
while((deadline.timeRemaining() > 0 || deadline.didTimeout) && this._list.length) {
this._runNextFunction();
}
this.processing = false;
}, {timeout: 1000});
}
/**
* Shift the list and run the function
* @private
*/
_runNextFunction() {
let fn = this._list.shift();
fn && fn();
}
}
function updateUI(context) {
if (context.__isProxy == false) return;
if (Array.isArray(context)) return updateUIArray(context);
const keys = context.constructor.properties || Object.keys(context).filter(item => item.indexOf("__") == -1 && item != "__isProxy");
for (let key of keys) {
crsbinding.events.notifyPropertyChanged(context, key);
if (Array.isArray(context[key])) {
updateUIArray(context[key]);
}
}
}
function updateUIArray (context) {
context.forEach(item => updateUI(item));
}
function listenOnPath(context, value, callback) {
let obj = context;
const parts = value.split(".");
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
if (i == parts.length -1) {
listenOn(obj, part, callback);
}
else {
if (obj[part] == null) {
// actual vs empty object
obj[part] = crsbinding.observation.observe({});
}
listenOn(obj, part, callback);
obj = obj[part];
}
}
}
function listenOn(context, property, callback) {
crsbinding.events.on(context, property.trim(), callback);
}
function domEnableEvents(element) {
element._domEvents = [];
element.registerEvent = registerEvent;
element.unregisterEvent = unregisterEvent;
}
function domDisableEvents(element) {
if (element._domEvents == null) return;
for (let event of element._domEvents) {
event.callback = null;
event.event = null;
}
element._domEvents.length = 0;
delete element._domEvents;
delete element.registerEvent;
delete element.unregisterEvent;
}
function registerEvent(event, callback) {
this.addEventListener(event, callback);
this._domEvents.push({
event: event,
callback: callback
});
}
function unregisterEvent(event, callback) {
const item = this._domEvents.find(item => item.event == event && item.callback == callback);
if (item == null) return;
this.removeEventListener(item.event, item.callback);
this._domEvents.splice(this._domEvents.indexOf(item), 1);
item.callback = null;
item.event = null;
}
class InflationManager {
constructor() {
this._items = new Map();
}
dispose() {
this._items.clear();
this._items = null;
}
/**
* This function registers a template for creating elements using the get function
* @param id
* @param template
*/
register(id, template) {
const generator = new InflationCodeGenerator();
const result = generator.generateCodeFor(template);
generator.dispose();
this._items.set(id, {
template: template,
inflate: result.inflate,
deflate: result.deflate
});
}
/**
* Remove the template from the inflation manager as we are longer going to use it anymore
* @param id
*/
unregister(id) {
const item = this._items.get(id);
if (item != null) {
item.template = null;
item.inflate = null;
item.defaulte = null;
this._items.delete(id);
}
}
/**
* Get a element or elements and inflate it with the data
* @param id
* @param data
*/
get(id, data) {
const item = this._items.get(id);
if (item == null) return null;
const fragment = document.createDocumentFragment();
for (let d of data) {
const element = item.template.content.cloneNode(true);
this.inflate(id, element.children[0], d, item.inflate);
fragment.appendChild(element);
}
return fragment;
}
/**
* Inflate a element
* @param id
* @param element
* @param data
*/
inflate(id, element, data, inflate = null) {
const fn = inflate || this._items.get(id).inflate;
fn(element, data);
}
/**
* Deflate a element
* @param id
* @param element
*/
deflate(id, elements) {
const fn = this._items.get(id).deflate;
if (Array.isArray(elements)) {
for (let element of elements) {
fn(element);
}
}
else {
fn(elements);
}
}
}
class InflationCodeGenerator {
constructor() {
this.inflateSrc = [];
this.deflateSrc = [];
}
dispose() {
this.inflateSrc = null;
this.deflateSrc = null;
};
generateCodeFor(template) {
const element = template.content.children[0];
this.path = "element";
this._processElement(element);
const inflateCode = this.inflateSrc.join("\n");
const deflateCode = this.deflateSrc.join("\n");
return {
inflate: new Function("element", "context", inflateCode),
deflate: new Function("element", "context", deflateCode)
}
}
_processElement(element) {
this._processInnerText(element);
this._processAttributes(element);
const path = this.path;
for (let i = 0; i < element.children.length; i++) {
this.path = `${path}.children[${i}]`;
this._processElement(element.children[i]);
}
}
_processInnerText(element) {
const text = (element.innerHTML || "").trim();
if (text.indexOf("${") == 0) {
let exp = text.substr(2, text.length - 3);
exp = crsbinding.expression.sanitize(exp).expression;
this.inflateSrc.push(`${this.path}.innerText = ${exp};`);
this.deflateSrc.push(`${this.path}.innerText = "";`);
}
}
_processAttributes(element) {
const attributes = Array.from(element.attributes).filter(attr => attr.value.indexOf("${") != -1 || attr.name.indexOf(".if") != -1);
for (let attr of attributes) {
if (attr.value.indexOf("${") != -1) {
this._processAttrValue(attr);
}
else {
this._processAttrCondition(attr);
}
}
}
_processAttrValue(attr) {
const text = attr.value.trim();
let exp = text.substr(2, text.length - 3);
exp = crsbinding.expression.sanitize(exp).expression;
this.inflateSrc.push(`${this.path}.setAttribute("${attr.name}", ${exp});`);
this.deflateSrc.push(`${this.path}.removeAttribute("${attr.name}");`);
attr.ownerElement.removeAttribute(attr.name);
}
_processAttrCondition(attr) {
if (attr.name.trim().indexOf("style") == 0) {
return this._processStyle(attr);
}
if (attr.name.trim().indexOf("classlist") == 0) {
return this._processClassList(attr);
}
if (attr.name.trim().indexOf(".if") != -1) {
return this._processConditional(attr);
}
}
_processStyle(attr) {
const parts = attr.name.split(".");
const prop = parts[1];
const value = crsbinding.expression.sanitize(attr.value.trim()).expression;
this.inflateSrc.push(`${this.path}.style.${prop} = ${value};`);
this.deflateSrc.push(`${this.path}.style.${prop} = "";`);
attr.ownerElement.removeAttribute(attr.name);
}
_processClassList(attr) {
const parts = attr.value.split("?");
const condition = crsbinding.expression.sanitize(parts[0]).expression;
const values = parts[1].split(":");
const trueValue = values[0].trim();
const falseValue = values.length > 1 ? values[1].trim() : "";
const trueCode = trueValue.indexOf("[") == -1 ? trueValue : `...${trueValue}`;
let code = `if (${condition}) {${this.path}.classList.add(${trueCode});}`;
if (falseValue.length > 0) {
let falseCode = falseValue.indexOf("[") == -1 ? falseValue : `...${falseValue}`;
code += `else {${this.path}.classList.add(${falseCode});}`;
}
const deflateCode = `while (${this.path}.classList.length > 0) {${this.path}.classList.remove(${this.path}.classList.item(0));}`;
this.inflateSrc.push(code);
this.deflateSrc.push(deflateCode);
attr.ownerElement.removeAttribute(attr.name);
}
_processConditional(attr) {
const attrName = attr.name.split(".if")[0].trim();
const expParts = attr.value.split("?");
const condition = crsbinding.expression.sanitize(expParts[0].trim()).expression;
let code = [`if(${condition})`];
const expValue = expParts.length > 1 ? expParts[1].trim() : `"${attrName}"`;
if (expValue.indexOf(":") == -1) {
code.push("{");
code.push(`${this.path}.setAttribute("${attrName}", ${expValue});`);
code.push("}");
code.push(`else {${this.path}.removeAttribute("${attrName}")}`);
}
else {
const condParts = expParts[1].split(":");
code.push("{");
code.push(`${this.path}.setAttribute("${attrName}", ${condParts[0].trim()});`);
code.push("}");
code.push(`else {${this.path}.setAttribute("${attrName}", ${condParts[1].trim()})}`);
}
this.inflateSrc.push(code.join(""));
this.deflateSrc.push(`${this.path}.removeAttribute("${attrName}")`);
attr.ownerElement.removeAttribute(attr.name);
}
}
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1)
};
function capitalizePropertyPath(str) {
const parts = str.split("-");
for (let i = 1; i < parts.length; i++) {
parts[i] = parts[i].capitalize();
}
return parts.join("");
}
const crsbinding$1 = {
_expFn: new Map(),
idleTaskManager: new IdleTaskManager(),
providerManager: new ProviderManager(),
inflationManager: new InflationManager(),
expression: {
sanitize: sanitizeExp,
compile: compileExp,
release: releaseExp,
updateUI: updateUI,
},
observation: {
observe: observe,
releaseObserved: releaseObserved,
releaseBinding: releaseBinding,
releaseChildBinding: releaseChildBinding
},
parsers: {
parseElement: parseElement,
parseElements: parseElements,
},
events: {
enableEvents: enableEvents,
disableEvents: disableEvents,
when: when,
on: on,
notifyPropertyChanged: notifyPropertyChanged,
removeOn: removeOn,
removeWhen: removeWhen,
listenOn: listenOn,
listenOnPath: listenOnPath
},
dom: {
enableEvents: domEnableEvents,
disableEvents: domDisableEvents
},
utils: {
capitalizePropertyPath: capitalizePropertyPath
}
};
globalThis.crsbinding = crsbinding$1;
export { crsbinding$1 as crsbinding };

@@ -1,1 +0,166 @@

const e=Object.getPrototypeOf((async function(){})).constructor;function n(e){e.__events=new Map,e.__conditions=new Map}function t(e){null!=e.__events&&(e.__events.forEach(e=>{e.length=0}),e.__events.clear(),delete e.__events),e.__conditions&&(e.__conditions.forEach(e=>{delete e.fn,delete e.properties}),e.__conditions.clear(),delete e.__conditions)}function s(n,t,s){let i=n.__events.get(t)||[];i=[...i,s],n.__events.set(t,i);const o=function(n,t,s){t=t||[];let i=!0,o=!1,r="context";if(null!=s&&(null!=s.sanitize&&(i=s.sanitize),null!=s.async&&(o=s.async),null!=s.ctxName&&(r=s.ctxName)),crsbinding._expFn.has(n)){const e=crsbinding._expFn.get(n);return e.count+=1,e}let c,_=n;if(1==i){if(c=crsbinding.expression.sanitize(n,r),crsbinding._expFn.has(c.expression)){const e=crsbinding._expFn.get(c.expression);return e.count+=1,e}_=!0===c.isLiteral?["return `",c.expression,"`"].join(""):`return ${c.expression}`,c.expression.split(".").length>2&&(_=`try { ${_} } catch(error) { return null }`)}else c={expression:n};const l={function:1==o?new e(r,...t,_):new Function(r,...t,_),parameters:c,count:1};return crsbinding._expFn.set(c.expression,l),l}(t);let r=n.__conditions.get(t);if(null==r){r={fn:()=>{if(1==o.function(n))for(let e of i)e()},properties:o.parameters.properties.slice(0)},n.__conditions.set(t,r)}const c=o.parameters.properties;for(let e of c)crsbinding.events.on(n,e,r.fn)}function i(e,n,t){crsbinding.events.removeOn(e,n,t);const s=e.__conditions.get(n);for(let n of s.properties)crsbinding.events.removeOn(e,n,s.fn);delete s.fn,delete s.properties,e.__conditions.delete(n)}function o(e,n,t){if(null==e||null==e.__events)return;let s=e.__events.get(n)||[];s=[...s,t],e.__events.set(n,s)}function r(e,n,t){if(null==e||null==e.__events)return;const s=e.__events.get(n)||[],i=s.indexOf(t);-1!=i&&(s.splice(i,1),e.__events.set(n,s)),0==s.length&&e.__events.delete(n)}function c(e,n,t){if(null==e.__events||0==e.__events.has(n))return;const s=e.__events.get(n);for(let i of s)i(n,e[n],t);const i=`${n}Changed`;null!=e[i]&&e[i].call(e,t)}export{t as disableEvents,n as enableEvents,c as notifyPropertyChanged,o as on,r as removeOn,i as removeWhen,s as when};
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
function compileExp(exp, parameters, options) {
parameters = parameters || [];
let sanitize = true;
let async = false;
let ctxName = "context";
if (options != null) {
if (options.sanitize != null) sanitize = options.sanitize;
if (options.async != null) async = options.async;
if (options.ctxName != null) ctxName = options.ctxName;
}
if (crsbinding._expFn.has(exp)) {
const x = crsbinding._expFn.get(exp);
x.count += 1;
return x;
}
let src = exp;
let san;
if (sanitize == true) {
san = crsbinding.expression.sanitize(exp, ctxName);
if (crsbinding._expFn.has(san.expression)) {
const x = crsbinding._expFn.get(san.expression);
x.count += 1;
return x;
}
src = san.isLiteral === true ? ["return `", san.expression, "`"].join("") : `return ${san.expression}`;
const parts = san.expression.split(".");
if (parts.length > 2) {
src = `try { ${src} } catch(error) { return null }`;
}
}
else {
san = {
expression: exp
};
}
const fn = async == true ? new AsyncFunction(ctxName, ...parameters, src) : new Function(ctxName, ...parameters, src);
const result = {
function: fn,
parameters: san,
count: 1
};
crsbinding._expFn.set(san.expression, result);
return result;
}
function enableEvents(obj) {
obj.__events = new Map();
obj.__conditions = new Map();
}
function disableEvents(obj) {
if (obj.__events != null) {
obj.__events.forEach((ev) => {
ev.length = 0;
});
obj.__events.clear();
delete obj.__events;
}
if (obj.__conditions) {
obj.__conditions.forEach((cnd) => {
delete cnd.fn;
delete cnd.properties;
});
obj.__conditions.clear();
delete obj.__conditions;
}
}
function when(obj, exp, callback) {
let functions = obj.__events.get(exp) || [];
functions = [...functions, callback];
obj.__events.set(exp, functions);
const cmp = compileExp(exp);
let cond = obj.__conditions.get(exp);
if (cond == null) {
const fn = () => {
if (cmp.function(obj) == true) {
for (let call of functions) {
call();
}
}
};
cond = {fn: fn, properties: cmp.parameters.properties.slice(0)};
obj.__conditions.set(exp, cond);
}
const properties = cmp.parameters.properties;
for (let property of properties) {
crsbinding.events.on(obj, property, cond.fn);
}
}
function removeWhen(obj, exp, callback) {
crsbinding.events.removeOn(obj, exp, callback);
const cnd = obj.__conditions.get(exp);
for (let property of cnd.properties) {
crsbinding.events.removeOn(obj, property, cnd.fn);
}
delete cnd.fn;
delete cnd.properties;
obj.__conditions.delete(exp);
}
function on(obj, property, callback) {
if (obj == null || obj.__events == null) return;
let functions = obj.__events.get(property) || [];
functions = [...functions, callback];
obj.__events.set(property, functions);
}
function removeOn(obj, property, callback) {
if (obj == null || obj.__events == null) return;
const functions = obj.__events.get(property) || [];
const index = functions.indexOf(callback);
if (index != -1) {
functions.splice(index, 1);
obj.__events.set(property, functions);
}
if (functions.length == 0) {
obj.__events.delete(property);
}
}
function notifyPropertyChanged(obj, property, args) {
if (obj.__events == null || obj.__events.has(property) == false) return;
callFunctions(obj.__events.get(property), obj, property, args);
if (obj.__elEvents) {
callFunctions(obj.__elEvents.get(property), obj, property, args);
}
const changedFnName = `${property}Changed`;
if (obj[changedFnName] != null) {
obj[changedFnName].call(obj, args);
}
}
function callFunctions(functions, obj, property, args) {
for(let fn of functions) {
fn(property, obj[property], args);
}
}
export { disableEvents, enableEvents, notifyPropertyChanged, on, removeOn, removeWhen, when };

@@ -1,1 +0,61 @@

class e{static get properties(){return["title"]}get title(){return this._title}set title(e){this._title=e}get element(){return this._element}set element(e){null!=e&&(e.style.display="none"),this._element=e}constructor(e){this.element=e}async connectedCallback(){this.__isProxy=!0,crsbinding.events.enableEvents(this),crsbinding.parsers.parseElement(this.element,this),this._loaded()}async disconnectedCallback(){crsbinding.observation.releaseBinding(this.element),crsbinding.events.disableEvents(this)}getProperty(e){let t=this[`_${e}`];return null==t&&null!=this.getAttribute&&(t=this.getAttribute(e)),t}setProperty(e,t){this[`_${e}`]=t,crsbinding.events.notifyPropertyChanged(this,e)}_loaded(){crsbinding.expression.updateUI(this),this.element.style.display="block"}}export{e as ViewBase};
class ViewBase {
static get properties() {
return ["title"]
}
get title() {
return this._title;
}
set title(newValue) {
this._title = newValue;
}
get element() {
return this._element;
}
set element(newValue) {
if (newValue != null) {
newValue.style.display = "none";
}
this._element = newValue;
}
constructor(element) {
this.element = element;
}
async connectedCallback() {
this.__isProxy = true;
crsbinding.events.enableEvents(this);
crsbinding.parsers.parseElement(this.element, this);
this._loaded();
}
async disconnectedCallback() {
crsbinding.observation.releaseBinding(this.element);
crsbinding.events.disableEvents(this);
}
getProperty(prop) {
let result = this[`_${prop}`];
if (result == null && this.getAttribute != null) {
result = this.getAttribute(prop);
}
return result;
}
setProperty(prop, value) {
this[`_${prop}`] = value;
// this is a proxy and the notification of property change happens in the observer
}
_loaded() {
crsbinding.expression.updateUI(this);
this.element.style.display = "block";
}
}
export { ViewBase };

2

package.json
{
"name": "crs-binding",
"version": "0.0.90",
"version": "0.0.91",
"description": "zero dependency binding engine",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -416,2 +416,4 @@ Currently as BETA

//////
##View base

@@ -563,2 +565,76 @@ View base is much like bindable element in that it provides you with base features.

This is a bit different to having the expression between the tags in that there is no listener for this.
Once the value is copied over that is it, it does not change again.
Once the value is copied over that is it, it does not change again.
# Inflating UI
Let me start by describing what this is and where you would use it before we get into the details.
Binding engines operate on ui and data and creating a relationship between the two.
Sometimes you need to keep the connection alive so that updates on one reflects on the other.
Inflation is the opposite of this.
Using a template as a reference we want to populate the template with data from the model and forget about it.
This sounds very much like populating data with the once operation except this applies to the entire template and all the binding expressions are evaluated once only.
To this end you can also use an array of data and ask for all the items back, populated with it's data and decorated according to it's attribute, style and classlist expressions.
The result is static so any changes you make to the data has no effect.
This is a great way to generate UI for virtualized lists or static information.
So here is a list of usable expression types.
1. Attributes ```data-id="${id}"```
1. Conditional Attributes ```hidden.if="isActive == false"```
1. Conditional ClassList ```classlist.if="isReady == true ? ['ready', 'italic'] : 'notReady'"```
1. Conditional Styles ```style.background.if="isActive == true ? 'green' : 'red'"```
How to use this?
<strong>Step 1</strong>: create an template and register it with the inflation manager giving a unique id for later use
```html
<template id="my-template">
<li data-id="${id}" classlist.if="isReady == true ? ['ready', 'italic'] : 'notReady'">
<div class="icon" style.background.if="isActive == true ? 'green' : 'red'"></div>
<div>${caption}</div>
<div hidden.if="isActive == false" data-hidden.if="isActive == false ? 'yes' : 'no'" data-description.if="isActive == false ? 'this not is active'">I am active</div>
</li>
</template>
```
```js
const template = this._element.querySelector("#my-template");
crsbinding.inflationManager.register("list-item", template);
```
<strong>Step 2:</strong> when you have your data you can use the get function.
```js
const fragment = crsbinding.inflationManager.get("list-item", template);
```
<strong>Finally</strong> When you are done clean up after yourself by un-registering the template
```js
crsbinding.inflationManager.unregister("list-item");
```
In some cases you may want to reuse a element and add it to a element store.
Doing this prevents it from being picked up by the garbage collection.
You don't want to store it with all the inflated information though so there are two functions that allow you too use it this way.
1. deflate: clean up the element for storgate
1. inflate: populate a given element with the information on the model.
```js
store.add(crsbinding.inflationManager.deflate("list-item", element));
```
```js
const element = store.getElement();
crsbinding.inflationManager.deflate("list-item", element, model);
```
For performance reasons the function generated to perform this task does not do checks on the model or element.
Thus, please keep this min mind:
1. Only use elements you got origionally from the inflation manager.
1. The models you use as part of the inflation process must have the paths structures as defined in your expression.
1. The expressions you define in the template is relative with the model being the root. So if you have a property called isActive on the item you can start the expression with isActive.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc