diff --git a/public/dist/scripts/app-all.js b/public/dist/scripts/app-all.js index 6edbe37a0e..2fce7ece17 100644 --- a/public/dist/scripts/app-all.js +++ b/public/dist/scripts/app-all.js @@ -1961,7 +1961,8 @@ if(service.instance){return service.instance;} let instance=(typeof service.object==='function')?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=='window'&&name!=='document'&&name!=='element'&&typeof instance==='object'&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;} if(key==="__watch"){return this.watch;} if(key==="__proxy"){return true;} -if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)}else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;} +if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)} +else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;} if(key==="__watch"){return this.watch=value;} target[key]=value;let path=receiver.__name+'.'+key;document.dispatchEvent(new CustomEvent(path+'.changed'));if(skip){return true;} skip=true;container.set('$prop',key,true);container.set('$value',value,true);container.resolve(this.watch);container.set('$key',null,true);container.set('$value',null,true);skip=false;return true;},};instance=new Proxy(instance,handler);} @@ -1978,7 +1979,8 @@ object[shift].unshift(value);break;case'splice':if(!Array.isArray(object[shift]) object[shift].splice(value,1);break;default:object[shift]=value;} return true;} if(!object){return null;} -if(!shift){result=object;}else{return object[shift];} +if(!shift){result=object;} +else{return object[shift];} return result;};let bind=function(element,path,callback){let event=container.scope(path)+'.changed';let service=event.split('.').slice(0,1).pop();let debug=element.getAttribute('data-debug')||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;} let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;}}(Object.assign({},namespaces)));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;} let removeNamespace=function(key){delete namespaces[key];return this;} @@ -1989,9 +1991,10 @@ if(typeof url!=='string'){throw new Error('var url must be of type string');} if(typeof headers!=='object'){throw new Error('var headers must be of type object');} if(typeof url!=='string'){throw new Error('var url must be of type string');} for(i=0;i-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;}else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];} -if(!index){result[key].push(val);}else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];} +part=part.split('+').join(' ');let eq=part.indexOf('=');let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;} +else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];} +if(!index){result[key].push(val);} +else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];} return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=='string'){throw new Error('path must be of type string');} if(typeof view!=='object'){throw new Error('view must be of type object');} states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split('/').length-a.path.split('/').length;if(n!==0){return n;} return b.path.length-a.path.length;});for(let i=0;i{let reference=match.substring(2,match.length-2).replace('[\'','.').replace('\']','').trim();reference=reference.split('|');let path=container.scope((reference[0]||''));let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);} if(reference.length>=2){for(let i=1;ipaths,}},true,false);window.ls.container.set('filter',function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set('$value',value,true,false);return container.resolve(filters[name]);};add('uppercase',($value)=>{if(typeof $value!=='string'){return $value;} return $value.toUpperCase();});add('lowercase',($value)=>{if(typeof $value!=='string'){return $value;} return $value.toLowerCase();});return{add:add,apply:apply}},true,false);window.ls.container.get('filter').add('escape',value=>{if(typeof value!=='string'){return value;} -return value.replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',repeat:false,controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);} +return value.replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);} +catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);} router.reset();if(null===route){return;} -scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));}else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;} +scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));} +else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});} +else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;} while(el=el.parentNode){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}} return null;};element.removeAttribute('data-ls-router');element.setAttribute('data-ls-scope','');element.setAttribute('data-ls-scope-count',1);view.add(scope);document.addEventListener('click',function(event){let target=findParent('a',event.target);if(!target){return false;} if(!target.href){return false;} @@ -2043,32 +2054,40 @@ window.history.pushState({},'Unknown',target.href);} init(route);return true;});window.addEventListener('popstate',function(){init(router.match(window.location));});window.addEventListener('hashchange',function(){init(router.match(window.location));});init(router.match(window.location));}});window.ls.container.get('view').add({selector:'data-ls-attrs',controller:function(element,expression,container){let attrs=element.getAttribute('data-ls-attrs').trim().split(',');let paths=[];let debug=element.getAttribute('data-debug')||false;let check=()=>{container.set('element',element,true,false);if(debug){console.info('debug-ls-attrs attributes:',attrs);} for(let i=0;i{for(let i=0;i-1));value=element.value;}catch{return null;}} +if('checkbox'===type){if(typeof value==='boolean'||value==='true'||value==='false'){if(value===true||value==='true'){element.setAttribute('checked','checked');element.checked=true;} +else{element.removeAttribute('checked');element.checked=false;}} +else{try{value=JSON.parse(value);element.checked=(Array.isArray(value)&&(value.indexOf(element.value)>-1));value=element.value;} +catch{return null;}} if(bind){element.addEventListener('change',()=>{for(let i=0;i-1){value.splice(index,1);} container.path(paths[i],value);}});} return;} if(element.value!==value){element.value=value;element.dispatchEvent(new Event('change'));} -if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}}else{if(element.textContent!=value){element.innerHTML=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);} +if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}} +else{if(element.innerHTML!=value){element.innerHTML=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);} for(let i=0;i{echo(expression.parse(parsedSyntax),false);});path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-if',controller:function(element,expression,container,view){let result='';let syntax=element.getAttribute('data-ls-if')||'';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=()=>{if(debug){console.info('debug-ls-if',expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true));} -try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));}catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);} +try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));} +catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);} if(debug){console.info('debug-ls-if result:',result);} -paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility='hidden';element.style.display='none';}else{element.style.removeProperty('display');element.style.removeProperty('visibility');} -if(prv===true&&element.$lsSkip===false){view.render(element)}};check();for(let i=0;i{let context=expr+'.'+index;container.addNamespace(as,context);if(debug){console.info('debug-ls-loop','index',index);console.info('debug-ls-loop','context',context);console.info('debug-ls-loop','context-path',container.path(context).name);console.info('debug-ls-loop','namespaces',container.namespaces);} container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);} -element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,repeat:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}else{if(debug){console.error('Missing template "'+source+'"');}} +element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));} +else{if(debug){console.error('Missing template "'+source+'"');}} if(!init){view.render(element);} return;} http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;iscope.max){scope.list.pop();scope.counter--;} diff --git a/public/dist/scripts/app.js b/public/dist/scripts/app.js index 2c73bc0649..63fed54b1b 100644 --- a/public/dist/scripts/app.js +++ b/public/dist/scripts/app.js @@ -8,7 +8,8 @@ if(service.instance){return service.instance;} let instance=(typeof service.object==='function')?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=='window'&&name!=='document'&&name!=='element'&&typeof instance==='object'&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;} if(key==="__watch"){return this.watch;} if(key==="__proxy"){return true;} -if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)}else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;} +if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)} +else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;} if(key==="__watch"){return this.watch=value;} target[key]=value;let path=receiver.__name+'.'+key;document.dispatchEvent(new CustomEvent(path+'.changed'));if(skip){return true;} skip=true;container.set('$prop',key,true);container.set('$value',value,true);container.resolve(this.watch);container.set('$key',null,true);container.set('$value',null,true);skip=false;return true;},};instance=new Proxy(instance,handler);} @@ -25,7 +26,8 @@ object[shift].unshift(value);break;case'splice':if(!Array.isArray(object[shift]) object[shift].splice(value,1);break;default:object[shift]=value;} return true;} if(!object){return null;} -if(!shift){result=object;}else{return object[shift];} +if(!shift){result=object;} +else{return object[shift];} return result;};let bind=function(element,path,callback){let event=container.scope(path)+'.changed';let service=event.split('.').slice(0,1).pop();let debug=element.getAttribute('data-debug')||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;} let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;}}(Object.assign({},namespaces)));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;} let removeNamespace=function(key){delete namespaces[key];return this;} @@ -36,9 +38,10 @@ if(typeof url!=='string'){throw new Error('var url must be of type string');} if(typeof headers!=='object'){throw new Error('var headers must be of type object');} if(typeof url!=='string'){throw new Error('var url must be of type string');} for(i=0;i-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;}else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];} -if(!index){result[key].push(val);}else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];} +part=part.split('+').join(' ');let eq=part.indexOf('=');let key=eq>-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;} +else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];} +if(!index){result[key].push(val);} +else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];} return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=='string'){throw new Error('path must be of type string');} if(typeof view!=='object'){throw new Error('view must be of type object');} states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split('/').length-a.path.split('/').length;if(n!==0){return n;} return b.path.length-a.path.length;});for(let i=0;i{let reference=match.substring(2,match.length-2).replace('[\'','.').replace('\']','').trim();reference=reference.split('|');let path=container.scope((reference[0]||''));let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);} if(reference.length>=2){for(let i=1;ipaths,}},true,false);window.ls.container.set('filter',function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set('$value',value,true,false);return container.resolve(filters[name]);};add('uppercase',($value)=>{if(typeof $value!=='string'){return $value;} return $value.toUpperCase();});add('lowercase',($value)=>{if(typeof $value!=='string'){return $value;} return $value.toLowerCase();});return{add:add,apply:apply}},true,false);window.ls.container.get('filter').add('escape',value=>{if(typeof value!=='string'){return value;} -return value.replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);}catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',repeat:false,controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);} +return value.replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);} +catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);} router.reset();if(null===route){return;} -scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));}else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;} +scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));} +else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});} +else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;} while(el=el.parentNode){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}} return null;};element.removeAttribute('data-ls-router');element.setAttribute('data-ls-scope','');element.setAttribute('data-ls-scope-count',1);view.add(scope);document.addEventListener('click',function(event){let target=findParent('a',event.target);if(!target){return false;} if(!target.href){return false;} @@ -90,32 +101,40 @@ window.history.pushState({},'Unknown',target.href);} init(route);return true;});window.addEventListener('popstate',function(){init(router.match(window.location));});window.addEventListener('hashchange',function(){init(router.match(window.location));});init(router.match(window.location));}});window.ls.container.get('view').add({selector:'data-ls-attrs',controller:function(element,expression,container){let attrs=element.getAttribute('data-ls-attrs').trim().split(',');let paths=[];let debug=element.getAttribute('data-debug')||false;let check=()=>{container.set('element',element,true,false);if(debug){console.info('debug-ls-attrs attributes:',attrs);} for(let i=0;i{for(let i=0;i-1));value=element.value;}catch{return null;}} +if('checkbox'===type){if(typeof value==='boolean'||value==='true'||value==='false'){if(value===true||value==='true'){element.setAttribute('checked','checked');element.checked=true;} +else{element.removeAttribute('checked');element.checked=false;}} +else{try{value=JSON.parse(value);element.checked=(Array.isArray(value)&&(value.indexOf(element.value)>-1));value=element.value;} +catch{return null;}} if(bind){element.addEventListener('change',()=>{for(let i=0;i-1){value.splice(index,1);} container.path(paths[i],value);}});} return;} if(element.value!==value){element.value=value;element.dispatchEvent(new Event('change'));} -if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}}else{if(element.textContent!=value){element.innerHTML=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);} +if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}} +else{if(element.innerHTML!=value){element.innerHTML=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);} for(let i=0;i{echo(expression.parse(parsedSyntax),false);});path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-if',controller:function(element,expression,container,view){let result='';let syntax=element.getAttribute('data-ls-if')||'';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=()=>{if(debug){console.info('debug-ls-if',expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true));} -try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));}catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);} +try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));} +catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);} if(debug){console.info('debug-ls-if result:',result);} -paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility='hidden';element.style.display='none';}else{element.style.removeProperty('display');element.style.removeProperty('visibility');} -if(prv===true&&element.$lsSkip===false){view.render(element)}};check();for(let i=0;i{let context=expr+'.'+index;container.addNamespace(as,context);if(debug){console.info('debug-ls-loop','index',index);console.info('debug-ls-loop','context',context);console.info('debug-ls-loop','context-path',container.path(context).name);console.info('debug-ls-loop','namespaces',container.namespaces);} container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);} -element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,repeat:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}else{if(debug){console.error('Missing template "'+source+'"');}} +element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));} +else{if(debug){console.error('Missing template "'+source+'"');}} if(!init){view.render(element);} return;} http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;iscope.max){scope.list.pop();scope.counter--;} diff --git a/public/scripts/dependencies/litespeed.js b/public/scripts/dependencies/litespeed.js index 57557f7c68..4ea4c8784e 100644 --- a/public/scripts/dependencies/litespeed.js +++ b/public/scripts/dependencies/litespeed.js @@ -1,1091 +1,140 @@ -window.ls = window.ls || {}; -window.ls.container = function() { - let stock = {}; - let listeners = {}; - let namespaces = {}; - let set = function(name, object, singleton, watch = true) { - if (typeof name !== 'string') { - throw new Error('var name must be of type string'); - } - if (typeof singleton !== 'boolean') { - throw new Error('var singleton "' + singleton + '" of service "' + name + '" must be of type boolean'); - } - stock[name] = { - name: name, - object: object, - singleton: singleton, - instance: null, - watch: watch, - }; - if (!watch) { - return this; - } - let binds = listeners[name] || {}; - for (let key in binds) { - if (binds.hasOwnProperty(key)) { - document.dispatchEvent(new CustomEvent(key)); - } - } - return this; - }; - let get = function(name) { - let service = (undefined !== stock[name]) ? stock[name] : null; - if (null == service) { - return null; - } - if (service.instance) { - return service.instance; - } - let instance = (typeof service.object === 'function') ? this.resolve(service.object) : service.object; - let skip = false; - if (service.watch && name !== 'window' && name !== 'document' && name !== 'element' && typeof instance === 'object' && instance !== null) { - let handler = { - name: service.name, - watch: function() {}, - get: function(target, key) { - if (key === "__name") { - return this.name; - } - if (key === "__watch") { - return this.watch; - } - if (key === "__proxy") { - return true; - } - if (typeof target[key] === 'object' && target[key] !== null && !target[key].__proxy) { - let handler = Object.assign({}, this); - handler.name = handler.name + '.' + key; - return new Proxy(target[key], handler) - } else { - return target[key]; - } - }, - set: function(target, key, value, receiver) { - if (key === "__name") { - return this.name = value; - } - if (key === "__watch") { - return this.watch = value; - } - target[key] = value; - let path = receiver.__name + '.' + key; - document.dispatchEvent(new CustomEvent(path + '.changed')); - if (skip) { - return true; - } - skip = true; - container.set('$prop', key, true); - container.set('$value', value, true); - container.resolve(this.watch); - container.set('$key', null, true); - container.set('$value', null, true); - skip = false; - return true; - }, - }; - instance = new Proxy(instance, handler); - } - if (service.singleton) { - service.instance = instance; - } - return instance; - }; - let resolve = function(target) { - if (!target) { - return () => {}; - } - let self = this; - const REGEX_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; - const REGEX_FUNCTION_PARAMS = /(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m; - const REGEX_PARAMETERS_VALUES = /\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm; - function getParams(func) { - let functionAsString = func.toString(); - let params = []; - let match; - functionAsString = functionAsString.replace(REGEX_COMMENTS, ''); - functionAsString = functionAsString.match(REGEX_FUNCTION_PARAMS)[1]; - if (functionAsString.charAt(0) === '(') { - functionAsString = functionAsString.slice(1, -1); - } - while (match = REGEX_PARAMETERS_VALUES.exec(functionAsString)) { - params.push(match[1]); - } - return params; - } - let args = getParams(target); - return target.apply(target, args.map(function(value) { - return self.get(value.trim()); - })); - }; - let path = function(path, value, type) { - type = (type) ? type : 'assign'; - path = container.scope(path).split('.'); - let name = path.shift(); - let object = container.get(name); - let result = null; - while (path.length > 1) { - if (!object) { - return null; - } - object = object[path.shift()]; - } - let shift = path.shift(); - if (value !== null && value !== undefined && object && shift && (object[shift] !== undefined || object[shift] !== null)) { - switch (type) { - case 'append': - if (!Array.isArray(object[shift])) { - object[shift] = []; - } - object[shift].push(value); - break; - case 'prepend': - if (!Array.isArray(object[shift])) { - object[shift] = []; - } - object[shift].unshift(value); - break; - case 'splice': - if (!Array.isArray(object[shift])) { - object[shift] = []; - } - object[shift].splice(value, 1); - break; - default: - object[shift] = value; - } - return true; - } - if (!object) { - return null; - } - if (!shift) { - result = object; - } else { - return object[shift]; - } - return result; - }; - let bind = function(element, path, callback) { - let event = container.scope(path) + '.changed'; - let service = event.split('.').slice(0, 1).pop(); - let debug = element.getAttribute('data-debug') || false; - listeners[service] = listeners[service] || {}; - listeners[service][event] = true; - let printer = (function(x) { - return function() { - if (!document.body.contains(element)) { - element = null; - document.removeEventListener(event, printer, false); - return false; - } - let oldNamespaces = namespaces; - namespaces = x; - callback(); - namespaces = oldNamespaces; - } - }(Object.assign({}, namespaces))); - document.addEventListener(event, printer); - }; - let addNamespace = function(key, scope) { - namespaces[key] = scope; - return this; - } - let removeNamespace = function(key) { - delete namespaces[key]; - return this; - } - let scope = function(path) { - for (let [key, value] of Object.entries(namespaces)) { - path = (path.indexOf('.') > -1) ? path.replace(key + '.', value + '.') : path.replace(key, value); - } - return path; - } - let container = { - set: set, - get: get, - resolve: resolve, - path: path, - bind: bind, - scope: scope, - addNamespace: addNamespace, - removeNamespace: removeNamespace, - stock: stock, - listeners: listeners, - namespaces: namespaces, - }; - set('container', container, true, false); - return container; -}(); -window.ls.container.set('http', function(document) { - let globalParams = [], - globalHeaders = []; - let addParam = function(url, param, value) { - param = encodeURIComponent(param); - let a = document.createElement('a'); - param += (value ? "=" + encodeURIComponent(value) : ""); - a.href = url; - a.search += (a.search ? "&" : "") + param; - return a.href; - }; - let request = function(method, url, headers, payload, progress) { - let i; - if (-1 === ['GET', 'POST', 'PUT', 'DELETE', 'TRACE', 'HEAD', 'OPTIONS', 'CONNECT', 'PATCH'].indexOf(method)) { - throw new Error('var method must contain a valid HTTP method name'); - } - if (typeof url !== 'string') { - throw new Error('var url must be of type string'); - } - if (typeof headers !== 'object') { - throw new Error('var headers must be of type object'); - } - if (typeof url !== 'string') { - throw new Error('var url must be of type string'); - } - for (i = 0; i < globalParams.length; i++) { - url = addParam(url, globalParams[i].key, globalParams[i].value); - } - return new Promise(function(resolve, reject) { - let xmlhttp = new XMLHttpRequest(); - xmlhttp.open(method, url, true); - xmlhttp.setRequestHeader('Ajax', '1'); - for (i = 0; i < globalHeaders.length; i++) { - xmlhttp.setRequestHeader(globalHeaders[i].key, globalHeaders[i].value); - } - for (let key in headers) { - if (headers.hasOwnProperty(key)) { - xmlhttp.setRequestHeader(key, headers[key]); - } - } - xmlhttp.onload = function() { - if (4 === xmlhttp.readyState && 200 === xmlhttp.status) { - resolve(xmlhttp.response); - } else { - document.dispatchEvent(new CustomEvent('http-' + method.toLowerCase() + '-' + xmlhttp.status)); - reject(new Error(xmlhttp.statusText)); - } - }; - if (progress) { - xmlhttp.addEventListener('progress', progress); - xmlhttp.upload.addEventListener('progress', progress, false); - } - xmlhttp.onerror = function() { - reject(new Error("Network Error")); - }; - xmlhttp.send(payload); - }) - }; - return { - 'get': function(url) { - return request('GET', url, {}, '') - }, - 'post': function(url, headers, payload) { - return request('POST', url, headers, payload) - }, - 'put': function(url, headers, payload) { - return request('PUT', url, headers, payload) - }, - 'patch': function(url, headers, payload) { - return request('PATCH', url, headers, payload) - }, - 'delete': function(url) { - return request('DELETE', url, {}, '') - }, - 'addGlobalParam': function(key, value) { - globalParams.push({ - key: key, - value: value - }); - }, - 'addGlobalHeader': function(key, value) { - globalHeaders.push({ - key: key, - value: value - }); - } - } -}, true, false); -window.ls.container.set('cookie', function(document) { - function get(name) { - let value = "; " + document.cookie, - parts = value.split("; " + name + "="); - if (parts.length === 2) { - return parts.pop().split(";").shift(); - } - return null; - } - - function set(name, value, days) { - let date = new Date(); - date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); - let expires = (0 < days) ? 'expires=' + date.toUTCString() : 'expires=0'; - document.cookie = name + "=" + value + ";" + expires + ";path=/"; - return this; - } - return { - 'get': get, - 'set': set - } -}, true, false); -window.ls.container.set('view', function(http, container) { - let stock = {}; - let execute = function(view, node, container) { - container.set('element', node, true, false); - container.resolve(view.controller); - if (true !== view.repeat) { - node.removeAttribute(view.selector); - } - }; - let parse = function(node, skip, callback) { - if (node.tagName === 'SCRIPT') { - return; - } - if (node.attributes && skip !== true) { - let attrs = []; - let attrsLen = node.attributes.length; - for (let x = 0; x < attrsLen; x++) { - attrs.push(node.attributes[x].nodeName); - } - if (1 !== node.nodeType) { - return; - } - if (attrs && attrsLen) { - for (let x = 0; x < attrsLen; x++) { - if (node.$lsSkip === true) { - break; - } - let pointer = (!/Edge/.test(navigator.userAgent)) ? x : (attrsLen - 1) - x; - let length = attrsLen; - let attr = attrs[pointer]; - if (!stock[attr]) { - continue; - } - let comp = stock[attr]; - if (typeof comp.template === "function") { - comp.template = container.resolve(comp.template); - } - if (!comp.template) { - (function(comp, node, container) { - execute(comp, node, container); - })(comp, node, container); - if (length !== attrsLen) { - x--; - } - if (callback) { - callback(); - } - continue; - } - node.classList.remove('load-end'); - node.classList.add('load-start'); - node.$lsSkip = true; - http.get(comp.template).then(function(node, comp) { - return function(data) { - node.$lsSkip = false; - node.innerHTML = data; - node.classList.remove('load-start'); - node.classList.add('load-end'); - (function(comp, node, container) { - execute(comp, node, container); - })(comp, node, container); - parse(node, true); - if (callback) { - callback(); - } - } - }(node, comp), function(error) { - throw new Error('Failed to load comp template: ' + error.message); - }); - } - } - } - if (true === node.$lsSkip) { - return; - } - let list = (node) ? node.childNodes : []; - if (node.$lsSkip === true) { - list = []; - } - for (let i = 0; i < list.length; i++) { - let child = list[i]; - parse(child); - } - }; - return { - stock: stock, - add: function(object) { - if (typeof object !== 'object') { - throw new Error('object must be of type object'); - } - let defaults = { - 'selector': '', - 'controller': function() {}, - 'template': '', - 'repeat': false, - 'protected': false - }; - for (let prop in defaults) { - if (!defaults.hasOwnProperty(prop)) { - continue; - } - if (prop in object) { - continue; - } - object[prop] = defaults[prop]; - } - if (!object.selector) { - throw new Error('View component is missing a selector attribute'); - } - stock[object.selector] = object; - return this; - }, - render: function(element, callback) { - parse(element, false, callback); - element.dispatchEvent(new window.Event('rendered', { - bubbles: false - })); - } - } -}, true, false); -window.ls.container.set('router', function(window) { - let getJsonFromUrl = function(URL) { - let query; - if (URL) { - let pos = location.search.indexOf('?'); - if (pos === -1) return []; - query = location.search.substr(pos + 1); - } else { - query = location.search.substr(1); - } - let result = {}; - query.split('&').forEach(function(part) { - if (!part) { - return; - } - part = part.split('+').join(' '); - let eq = part.indexOf('='); - let key = eq > -1 ? part.substr(0, eq) : part; - let val = eq > -1 ? decodeURIComponent(part.substr(eq + 1)) : ''; - let from = key.indexOf('['); - if (from === -1) { - result[decodeURIComponent(key)] = val; - } else { - let to = key.indexOf(']'); - let index = decodeURIComponent(key.substring(from + 1, to)); - key = decodeURIComponent(key.substring(0, from)); - if (!result[key]) { - result[key] = []; - } - if (!index) { - result[key].push(val); - } else { - result[key][index] = val; - } - } - }); - return result; - }; - let states = []; - let params = getJsonFromUrl(window.location.search); - let hash = window.location.hash; - let current = null; - let previous = null; - let getPrevious = () => previous; - let getCurrent = () => current; - let setPrevious = (value) => { - previous = value; - return this; - }; - let setCurrent = (value) => { - current = value; - return this; - }; - let setParam = function(key, value) { - params[key] = value; - return this; - }; - let getParam = function(key, def) { - if (key in params) { - return params[key]; - } - return def; - }; - let getParams = function() { - return params; - }; - let getURL = function() { - return window.location.href; - }; - let add = function(path, view) { - if (typeof path !== 'string') { - throw new Error('path must be of type string'); - } - if (typeof view !== 'object') { - throw new Error('view must be of type object'); - } - states[states.length++] = { - path: path, - view: view - }; - return this; - }; - let match = function(location) { - let url = location.pathname; - states.sort(function(a, b) { - return b.path.length - a.path.length; - }); - states.sort(function(a, b) { - let n = b.path.split('/').length - a.path.split('/').length; - if (n !== 0) { - return n; - } - return b.path.length - a.path.length; - }); - for (let i = 0; i < states.length; i++) { - let value = states[i]; - value.path = (value.path.substring(0, 1) !== '/') ? location.pathname + value.path : value.path; - let match = new RegExp("^" + value.path.replace(/:[^\s/]+/g, '([\\w-]+)') + "$"); - let found = url.match(match); - if (found) { - previous = current; - current = value; - return value; - } - } - return null - }; - let change = function(URL, replace) { - if (!replace) { - window.history.pushState({}, '', URL); - } else { - window.history.replaceState({}, '', URL); - } - window.dispatchEvent(new PopStateEvent('popstate', {})); - return this; - }; - let reload = function() { - return change(window.location.href); - }; - return { - setParam: setParam, - getParam: getParam, - getParams: getParams, - getURL: getURL, - add: add, - change: change, - reload: reload, - match: match, - getCurrent: getCurrent, - setCurrent: setCurrent, - getPrevious: getPrevious, - setPrevious: setPrevious, - params: params, - hash: hash, - reset: function() { - this.params = getJsonFromUrl(window.location.search); - this.hash = window.location.hash; - } - }; -}, true, true); -window.ls.container.set('expression', function(container, filter) { - let paths = []; - return { - regex: /(\{{.*?\}})/gi, - parse: function(string, def, cast = false) { - def = def || ''; - paths = []; - return string.replace(this.regex, match => { - let reference = match.substring(2, match.length - 2).replace('[\'', '.').replace('\']', '').trim(); - reference = reference.split('|'); - let path = container.scope((reference[0] || '')); - let result = container.path(path); - path = container.scope(path); - if (!paths.includes(path)) { - paths.push(path); - } - if (reference.length >= 2) { - for (let i = 1; i < reference.length; i++) { - result = filter.apply(reference[i], result); - } - } - if (null === result || undefined === result) { - result = def; - } else if (typeof result === 'object') { - result = JSON.stringify(result, null, 4); - } else if (((typeof result === 'object') || (typeof result === 'string')) && cast) { - result = '\'' + result + '\''; - } - return result; - }).replace(/\\{/g, "{").replace(/\\}/g, "}"); - }, - getPaths: () => paths, - } -}, true, false); -window.ls.container.set('filter', function(container) { - let filters = {}; - let add = function(name, callback) { - filters[name] = callback; - return this; - }; - let apply = function(name, value) { - container.set('$value', value, true, false); - return container.resolve(filters[name]); - }; - add('uppercase', ($value) => { - if (typeof $value !== 'string') { - return $value; - } - return $value.toUpperCase(); - }); - add('lowercase', ($value) => { - if (typeof $value !== 'string') { - return $value; - } - return $value.toLowerCase(); - }); - return { - add: add, - apply: apply - } -}, true, false); -window.ls.container.get('filter').add('escape', value => { - if (typeof value !== 'string') { - return value; - } - return value.replace(/&/g, '&').replace(//g, '>').replace(/\"/g, '"').replace(/\'/g, ''').replace(/\//g, '/'); -}); -window.ls = window.ls || {}; -window.ls.container.set('window', window, true, false).set('document', window.document, true, false).set('element', window.document, true, false); -window.ls.run = function(window) { - try { - this.view.render(window.document); - } catch (error) { - let handler = window.ls.container.resolve(this.error); - handler(error); - } -}; -window.ls.error = () => { - return error => { - console.error('ls-error', error.message, error.stack, error.toString()); - } -}; -window.ls.router = window.ls.container.get('router'); -window.ls.view = window.ls.container.get('view'); -window.ls.filter = window.ls.container.get('filter'); -window.ls.container.get('view').add({ - selector: 'data-ls-router', - repeat: false, - controller: function(element, window, document, view, router) { - let firstFromServer = (element.getAttribute('data-first-from-server') === 'true'); - let scope = { - selector: 'data-ls-scope', - template: false, - repeat: true, - controller: function() {}, - }; - let init = function(route) { - let count = parseInt(element.getAttribute('data-ls-scope-count') || 0); - element.setAttribute('data-ls-scope-count', count + 1); - window.scrollTo(0, 0); - if (window.document.body.scrollTo) { - window.document.body.scrollTo(0, 0); - } - router.reset(); - if (null === route) { - return; - } - scope.template = (undefined !== route.view.template) ? route.view.template : null; - scope.controller = (undefined !== route.view.controller) ? route.view.controller : function() {}; - document.dispatchEvent(new CustomEvent('state-change')); - if (firstFromServer && null === router.getPrevious()) { - scope.template = ''; - document.dispatchEvent(new CustomEvent('state-changed')); - } else if (count === 1) { - view.render(element, function() { - document.dispatchEvent(new CustomEvent('state-changed')); - }); - } else if (null !== router.getPrevious()) { - view.render(element, function() { - document.dispatchEvent(new CustomEvent('state-changed')); - }); - } - }; - let findParent = function(tagName, el) { - if ((el.nodeName || el.tagName).toLowerCase() === tagName.toLowerCase()) { - return el; - } - while (el = el.parentNode) { - if ((el.nodeName || el.tagName).toLowerCase() === tagName.toLowerCase()) { - return el; - } - } - return null; - }; - element.removeAttribute('data-ls-router'); - element.setAttribute('data-ls-scope', ''); - element.setAttribute('data-ls-scope-count', 1); - view.add(scope); - document.addEventListener('click', function(event) { - let target = findParent('a', event.target); - if (!target) { - return false; - } - if (!target.href) { - return false; - } - if ((event.metaKey)) { - return false; - } - if ((target.hasAttribute('target')) && ('_blank' === target.getAttribute('target'))) { - return false; - } - if (target.hostname !== window.location.hostname) { - return false; - } - let route = router.match(target); - if (null === route) { - return false; - } - event.preventDefault(); - if (window.location === target.href) { - return false; - } - route.view.state = (undefined === route.view.state) ? true : route.view.state; - if (true === route.view.state) { - if (router.getPrevious() && router.getPrevious().view && (router.getPrevious().view.scope !== route.view.scope)) { - window.location.href = target.href; - return false; - } - window.history.pushState({}, 'Unknown', target.href); - } - init(route); - return true; - }); - window.addEventListener('popstate', function() { - init(router.match(window.location)); - }); - window.addEventListener('hashchange', function() { - init(router.match(window.location)); - }); - init(router.match(window.location)); - } -}); -window.ls.container.get('view').add({ - selector: 'data-ls-attrs', - controller: function(element, expression, container) { - let attrs = element.getAttribute('data-ls-attrs').trim().split(','); - let paths = []; - let debug = element.getAttribute('data-debug') || false; - let check = () => { - container.set('element', element, true, false); - if (debug) { - console.info('debug-ls-attrs attributes:', attrs); - } - for (let i = 0; i < attrs.length; i++) { - let attr = attrs[i]; - let key = expression.parse((attr.substring(0, attr.indexOf('=')) || attr)); - paths = paths.concat(expression.getPaths()); - let value = ''; - if (attr.indexOf('=') > -1) { - value = expression.parse(attr.substring(attr.indexOf('=') + 1)) || ''; - paths = paths.concat(expression.getPaths()); - } - if (!key) { - return null; - } - element.setAttribute(key, value); - } - }; - check(); - for (let i = 0; i < paths.length; i++) { - let path = paths[i].split('.'); - while (path.length) { - container.bind(element, path.join('.'), check); - path.pop(); - } - } - } -}); -window.ls.container.get('view').add({ - selector: 'data-ls-bind', - controller: function(element, expression, container) { - let debug = element.getAttribute('data-debug') || false; - let echo = function(value, bind = true) { - if (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'BUTTON' || element.tagName === 'TEXTAREA') { - let type = element.getAttribute('type'); - if ('radio' === type) { - if (value.toString() === element.value) { - element.setAttribute('checked', 'checked'); - } else { - element.removeAttribute('checked'); - } - if (bind) { - element.addEventListener('change', () => { - for (let i = 0; i < paths.length; i++) { - if (element.checked) { - value = element.value; - } - container.path(paths[i], value); - } - }); - } - return; - } - if ('checkbox' === type) { - if (typeof value === 'boolean' || value === 'true' || value === 'false') { - if (value === true || value === 'true') { - element.setAttribute('checked', 'checked'); - element.checked = true; - } else { - element.removeAttribute('checked'); - element.checked = false; - } - } else { - try { - value = JSON.parse(value); - element.checked = (Array.isArray(value) && (value.indexOf(element.value) > -1)); - value = element.value; - } catch { - return null; - } - } - if (bind) { - element.addEventListener('change', () => { - for (let i = 0; i < paths.length; i++) { - let value = container.path(paths[i]); - let index = value.indexOf(element.value); - if (element.checked && index < 0) { - value.push(element.value); - } - if (!element.checked && index > -1) { - value.splice(index, 1); - } - container.path(paths[i], value); - } - }); - } - return; - } - if (element.value !== value) { - element.value = value; - element.dispatchEvent(new Event('change')); - } - if (bind) { - element.addEventListener('input', sync); - element.addEventListener('change', sync); - } - } else { - if (element.textContent != value) { - element.innerHTML = value; - } - } - }; - let sync = (() => { - return () => { - if (debug) { - console.info('debug-ls-bind', 'sync-path', paths); - console.info('debug-ls-bind', 'sync-syntax', syntax); - console.info('debug-ls-bind', 'sync-syntax-parsed', parsedSyntax); - console.info('debug-ls-bind', 'sync-value', element.value); - } - for (let i = 0; i < paths.length; i++) { - if ('{{' + paths[i] + '}}' !== parsedSyntax) { - if (debug) { - console.info('debug-ls-bind', 'sync-skipped-path', paths[i]); - console.info('debug-ls-bind', 'sync-skipped-syntax', syntax); - console.info('debug-ls-bind', 'sync-skipped-syntax-parsed', parsedSyntax); - } - continue; - } - if (debug) { - console.info('debug-ls-bind', 'sync-loop-path', paths[i]); - console.info('debug-ls-bind', 'sync-loop-syntax', parsedSyntax); - } - container.path(paths[i], element.value); - } - } - })(); - let syntax = element.getAttribute('data-ls-bind'); - let parsedSyntax = container.scope(syntax); - let unsync = (!!element.getAttribute('data-unsync')) || false; - let result = expression.parse(syntax); - let paths = expression.getPaths(); - echo(result, !unsync); - element.addEventListener('looped', function() { - echo(expression.parse(parsedSyntax), false); - }); - for (let i = 0; i < paths.length; i++) { - let path = paths[i].split('.'); - if (debug) { - console.info('debug-ls-bind', 'bind-path', path); - console.info('debug-ls-bind', 'bind-syntax', syntax); - } - while (path.length) { - container.bind(element, path.join('.'), () => { - echo(expression.parse(parsedSyntax), false); - }); - path.pop(); - } - } - } -}); -window.ls.container.get('view').add({ - selector: 'data-ls-if', - controller: function(element, expression, container, view) { - let result = ''; - let syntax = element.getAttribute('data-ls-if') || ''; - let debug = element.getAttribute('data-debug') || false; - let paths = []; - let check = () => { - if (debug) { - console.info('debug-ls-if', expression.parse(syntax.replace(/(\r\n|\n|\r)/gm, ' '), 'undefined', true)); - } - try { - result = (eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm, ' '), 'undefined', true))); - } catch (error) { - throw new Error('Failed to evaluate expression "' + syntax + ' (resulted with: "' + result + '")": ' + error); - } - if (debug) { - console.info('debug-ls-if result:', result); - } - paths = expression.getPaths(); - let prv = element.$lsSkip; - element.$lsSkip = !result; - if (!result) { - element.style.visibility = 'hidden'; - element.style.display = 'none'; - } else { - element.style.removeProperty('display'); - element.style.removeProperty('visibility'); - } - if (prv === true && element.$lsSkip === false) { - view.render(element) - } - }; - check(); - for (let i = 0; i < paths.length; i++) { - let path = paths[i].split('.'); - while (path.length) { - container.bind(element, path.join('.'), check); - path.pop(); - } - } - } -}); -window.ls.container.get('view').add({ - selector: 'data-ls-loop', - template: false, - repeat: false, - nested: false, - controller: function(element, view, container, window, expression) { - let expr = expression.parse(element.getAttribute('data-ls-loop')); - let as = element.getAttribute('data-ls-as'); - let key = element.getAttribute('data-ls-key') || '$index'; - let limit = parseInt(expression.parse(element.getAttribute('data-limit') || '') || -1); - let debug = element.getAttribute('data-debug') || false; - let echo = function() { - let array = container.path(expr); - let counter = 0; - array = (!array) ? [] : array; - let watch = !!(array && array.__proxy); - while (element.hasChildNodes()) { - element.removeChild(element.lastChild); - element.lastChild = null; - } - if (array instanceof Array && typeof array !== 'object') { - throw new Error('Reference value must be array or object. ' + (typeof array) + ' given'); - } - let children = []; - element.$lsSkip = true; - element.style.visibility = (0 === array.length) ? 'hidden' : 'visible'; - for (let prop in array) { - if (counter == limit) { - break; - } - counter++; - if (!array.hasOwnProperty(prop)) { - continue; - } - children[prop] = template.cloneNode(true); - element.appendChild(children[prop]); - (index => { - let context = expr + '.' + index; - container.addNamespace(as, context); - if (debug) { - console.info('debug-ls-loop', 'index', index); - console.info('debug-ls-loop', 'context', context); - console.info('debug-ls-loop', 'context-path', container.path(context).name); - console.info('debug-ls-loop', 'namespaces', container.namespaces); - } - container.set(as, container.path(context), true, watch); - container.set(key, index, true, false); - view.render(children[prop]); - container.removeNamespace(as); - })(prop); - } - element.dispatchEvent(new Event('looped')); - }; - let template = (element.children.length === 1) ? element.children[0] : window.document.createElement('li'); - echo(); - container.bind(element, expr + '.length', echo); - let path = (expr + '.length').split('.'); - while (path.length) { - container.bind(element, path.join('.'), echo); - path.pop(); - } - } -}); -window.ls.container.get('view').add({ - selector: 'data-ls-template', - template: false, - repeat: false, - controller: function(element, view, http, expression, document, container) { - let template = element.getAttribute('data-ls-template') || ''; - let type = element.getAttribute('data-type') || 'url'; - let debug = element.getAttribute('data-debug') || false; - let paths = []; - let check = function(init = false) { - let source = expression.parse(template); - paths = expression.getPaths(); - element.innerHTML = ''; - if ('script' === type) { - let inlineTemplate = document.getElementById(source); - if (inlineTemplate && inlineTemplate.innerHTML) { - element.innerHTML = inlineTemplate.innerHTML; - element.dispatchEvent(new CustomEvent('template-loaded', { - bubbles: true, - cancelable: false - })); - } else { - if (debug) { - console.error('Missing template "' + source + '"'); - } - } - if (!init) { - view.render(element); - } - return; - } - http.get(source).then(function(element) { - return function(data) { - element.innerHTML = data; - view.render(element); - element.dispatchEvent(new CustomEvent('template-loaded', { - bubbles: true, - cancelable: false - })); - } - }(element), function() { - throw new Error('Failed loading template'); - }); - }; - check(true); - for (let i = 0; i < paths.length; i++) { - let path = paths[i].split('.'); - while (path.length) { - container.bind(element, path.join('.'), check); - path.pop(); - } - } - } -}); +window.ls=window.ls||{};window.ls.container=function(){let stock={};let listeners={};let namespaces={};let set=function(name,object,singleton,watch=true){if(typeof name!=='string'){throw new Error('var name must be of type string');} +if(typeof singleton!=='boolean'){throw new Error('var singleton "'+singleton+'" of service "'+name+'" must be of type boolean');} +stock[name]={name:name,object:object,singleton:singleton,instance:null,watch:watch,};if(!watch){return this;} +let binds=listeners[name]||{};for(let key in binds){if(binds.hasOwnProperty(key)){document.dispatchEvent(new CustomEvent(key));}} +return this;};let get=function(name){let service=(undefined!==stock[name])?stock[name]:null;if(null==service){return null;} +if(service.instance){return service.instance;} +let instance=(typeof service.object==='function')?this.resolve(service.object):service.object;let skip=false;if(service.watch&&name!=='window'&&name!=='document'&&name!=='element'&&typeof instance==='object'&&instance!==null){let handler={name:service.name,watch:function(){},get:function(target,key){if(key==="__name"){return this.name;} +if(key==="__watch"){return this.watch;} +if(key==="__proxy"){return true;} +if(typeof target[key]==='object'&&target[key]!==null&&!target[key].__proxy){let handler=Object.assign({},this);handler.name=handler.name+'.'+key;return new Proxy(target[key],handler)} +else{return target[key];}},set:function(target,key,value,receiver){if(key==="__name"){return this.name=value;} +if(key==="__watch"){return this.watch=value;} +target[key]=value;let path=receiver.__name+'.'+key;document.dispatchEvent(new CustomEvent(path+'.changed'));if(skip){return true;} +skip=true;container.set('$prop',key,true);container.set('$value',value,true);container.resolve(this.watch);container.set('$key',null,true);container.set('$value',null,true);skip=false;return true;},};instance=new Proxy(instance,handler);} +if(service.singleton){service.instance=instance;} +return instance;};let resolve=function(target){if(!target){return()=>{};} +let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;const REGEX_FUNCTION_PARAMS=/(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m;const REGEX_PARAMETERS_VALUES=/\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm;function getParams(func){let functionAsString=func.toString();let params=[];let match;functionAsString=functionAsString.replace(REGEX_COMMENTS,'');functionAsString=functionAsString.match(REGEX_FUNCTION_PARAMS)[1];if(functionAsString.charAt(0)==='('){functionAsString=functionAsString.slice(1,-1);} +while(match=REGEX_PARAMETERS_VALUES.exec(functionAsString)){params.push(match[1]);} +return params;} +let args=getParams(target);return target.apply(target,args.map(function(value){return self.get(value.trim());}));};let path=function(path,value,type){type=(type)?type:'assign';path=container.scope(path).split('.');let name=path.shift();let object=container.get(name);let result=null;while(path.length>1){if(!object){return null;} +object=object[path.shift()];} +let shift=path.shift();if(value!==null&&value!==undefined&&object&&shift&&(object[shift]!==undefined||object[shift]!==null)){switch(type){case'append':if(!Array.isArray(object[shift])){object[shift]=[];} +object[shift].push(value);break;case'prepend':if(!Array.isArray(object[shift])){object[shift]=[];} +object[shift].unshift(value);break;case'splice':if(!Array.isArray(object[shift])){object[shift]=[];} +object[shift].splice(value,1);break;default:object[shift]=value;} +return true;} +if(!object){return null;} +if(!shift){result=object;} +else{return object[shift];} +return result;};let bind=function(element,path,callback){let event=container.scope(path)+'.changed';let service=event.split('.').slice(0,1).pop();let debug=element.getAttribute('data-debug')||false;listeners[service]=listeners[service]||{};listeners[service][event]=true;let printer=(function(x){return function(){if(!document.body.contains(element)){element=null;document.removeEventListener(event,printer,false);return false;} +let oldNamespaces=namespaces;namespaces=x;callback();namespaces=oldNamespaces;}}(Object.assign({},namespaces)));document.addEventListener(event,printer);};let addNamespace=function(key,scope){namespaces[key]=scope;return this;} +let removeNamespace=function(key){delete namespaces[key];return this;} +let scope=function(path){for(let[key,value]of Object.entries(namespaces)){path=(path.indexOf('.')>-1)?path.replace(key+'.',value+'.'):path.replace(key,value);} +return path;} +let container={set:set,get:get,resolve:resolve,path:path,bind:bind,scope:scope,addNamespace:addNamespace,removeNamespace:removeNamespace,stock:stock,listeners:listeners,namespaces:namespaces,};set('container',container,true,false);return container;}();window.ls.container.set('http',function(document){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){param=encodeURIComponent(param);let a=document.createElement('a');param+=(value?"="+encodeURIComponent(value):"");a.href=url;a.search+=(a.search?"&":"")+param;return a.href;};let request=function(method,url,headers,payload,progress){let i;if(-1===['GET','POST','PUT','DELETE','TRACE','HEAD','OPTIONS','CONNECT','PATCH'].indexOf(method)){throw new Error('var method must contain a valid HTTP method name');} +if(typeof url!=='string'){throw new Error('var url must be of type string');} +if(typeof headers!=='object'){throw new Error('var headers must be of type object');} +if(typeof url!=='string'){throw new Error('var url must be of type string');} +for(i=0;i-1?part.substr(0,eq):part;let val=eq>-1?decodeURIComponent(part.substr(eq+1)):'';let from=key.indexOf('[');if(from===-1){result[decodeURIComponent(key)]=val;} +else{let to=key.indexOf(']');let index=decodeURIComponent(key.substring(from+1,to));key=decodeURIComponent(key.substring(0,from));if(!result[key]){result[key]=[];} +if(!index){result[key].push(val);} +else{result[key][index]=val;}}});return result;};let states=[];let params=getJsonFromUrl(window.location.search);let hash=window.location.hash;let current=null;let previous=null;let getPrevious=()=>previous;let getCurrent=()=>current;let setPrevious=(value)=>{previous=value;return this;};let setCurrent=(value)=>{current=value;return this;};let setParam=function(key,value){params[key]=value;return this;};let getParam=function(key,def){if(key in params){return params[key];} +return def;};let getParams=function(){return params;};let getURL=function(){return window.location.href;};let add=function(path,view){if(typeof path!=='string'){throw new Error('path must be of type string');} +if(typeof view!=='object'){throw new Error('view must be of type object');} +states[states.length++]={path:path,view:view};return this;};let match=function(location){let url=location.pathname;states.sort(function(a,b){return b.path.length-a.path.length;});states.sort(function(a,b){let n=b.path.split('/').length-a.path.split('/').length;if(n!==0){return n;} +return b.path.length-a.path.length;});for(let i=0;i{let reference=match.substring(2,match.length-2).replace('[\'','.').replace('\']','').trim();reference=reference.split('|');let path=container.scope((reference[0]||''));let result=container.path(path);path=container.scope(path);if(!paths.includes(path)){paths.push(path);} +if(reference.length>=2){for(let i=1;ipaths,}},true,false);window.ls.container.set('filter',function(container){let filters={};let add=function(name,callback){filters[name]=callback;return this;};let apply=function(name,value){container.set('$value',value,true,false);return container.resolve(filters[name]);};add('uppercase',($value)=>{if(typeof $value!=='string'){return $value;} +return $value.toUpperCase();});add('lowercase',($value)=>{if(typeof $value!=='string'){return $value;} +return $value.toLowerCase();});return{add:add,apply:apply}},true,false);window.ls.container.get('filter').add('escape',value=>{if(typeof value!=='string'){return value;} +return value.replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/\'/g,''').replace(/\//g,'/');});window.ls=window.ls||{};window.ls.container.set('window',window,true,false).set('document',window.document,true,false).set('element',window.document,true,false);window.ls.run=function(window){try{this.view.render(window.document);} +catch(error){let handler=window.ls.container.resolve(this.error);handler(error);}};window.ls.error=()=>{return error=>{console.error('ls-error',error.message,error.stack,error.toString());}};window.ls.router=window.ls.container.get('router');window.ls.view=window.ls.container.get('view');window.ls.filter=window.ls.container.get('filter');window.ls.container.get('view').add({selector:'data-ls-router',controller:function(element,window,document,view,router){let firstFromServer=(element.getAttribute('data-first-from-server')==='true');let scope={selector:'data-ls-scope',template:false,repeat:true,controller:function(){},};let init=function(route){let count=parseInt(element.getAttribute('data-ls-scope-count')||0);element.setAttribute('data-ls-scope-count',count+1);window.scrollTo(0,0);if(window.document.body.scrollTo){window.document.body.scrollTo(0,0);} +router.reset();if(null===route){return;} +scope.template=(undefined!==route.view.template)?route.view.template:null;scope.controller=(undefined!==route.view.controller)?route.view.controller:function(){};document.dispatchEvent(new CustomEvent('state-change'));if(firstFromServer&&null===router.getPrevious()){scope.template='';document.dispatchEvent(new CustomEvent('state-changed'));} +else if(count===1){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});} +else if(null!==router.getPrevious()){view.render(element,function(){document.dispatchEvent(new CustomEvent('state-changed'));});}};let findParent=function(tagName,el){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;} +while(el=el.parentNode){if((el.nodeName||el.tagName).toLowerCase()===tagName.toLowerCase()){return el;}} +return null;};element.removeAttribute('data-ls-router');element.setAttribute('data-ls-scope','');element.setAttribute('data-ls-scope-count',1);view.add(scope);document.addEventListener('click',function(event){let target=findParent('a',event.target);if(!target){return false;} +if(!target.href){return false;} +if((event.metaKey)){return false;} +if((target.hasAttribute('target'))&&('_blank'===target.getAttribute('target'))){return false;} +if(target.hostname!==window.location.hostname){return false;} +let route=router.match(target);if(null===route){return false;} +event.preventDefault();if(window.location===target.href){return false;} +route.view.state=(undefined===route.view.state)?true:route.view.state;if(true===route.view.state){if(router.getPrevious()&&router.getPrevious().view&&(router.getPrevious().view.scope!==route.view.scope)){window.location.href=target.href;return false;} +window.history.pushState({},'Unknown',target.href);} +init(route);return true;});window.addEventListener('popstate',function(){init(router.match(window.location));});window.addEventListener('hashchange',function(){init(router.match(window.location));});init(router.match(window.location));}});window.ls.container.get('view').add({selector:'data-ls-attrs',controller:function(element,expression,container){let attrs=element.getAttribute('data-ls-attrs').trim().split(',');let paths=[];let debug=element.getAttribute('data-debug')||false;let check=()=>{container.set('element',element,true,false);if(debug){console.info('debug-ls-attrs attributes:',attrs);} +for(let i=0;i{for(let i=0;i-1));value=element.value;} +catch{return null;}} +if(bind){element.addEventListener('change',()=>{for(let i=0;i-1){value.splice(index,1);} +container.path(paths[i],value);}});} +return;} +if(element.value!==value){element.value=value;element.dispatchEvent(new Event('change'));} +if(bind){element.addEventListener('input',sync);element.addEventListener('change',sync);}} +else{if(element.innerHTML!=value){element.innerHTML=value;}}};let sync=(()=>{return()=>{if(debug){console.info('debug-ls-bind','sync-path',paths);console.info('debug-ls-bind','sync-syntax',syntax);console.info('debug-ls-bind','sync-syntax-parsed',parsedSyntax);console.info('debug-ls-bind','sync-value',element.value);} +for(let i=0;i{echo(expression.parse(parsedSyntax),false);});path.pop();}}}});window.ls.container.get('view').add({selector:'data-ls-if',controller:function(element,expression,container,view){let result='';let syntax=element.getAttribute('data-ls-if')||'';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=()=>{if(debug){console.info('debug-ls-if',expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true));} +try{result=(eval(expression.parse(syntax.replace(/(\r\n|\n|\r)/gm,' '),'undefined',true)));} +catch(error){throw new Error('Failed to evaluate expression "'+syntax+' (resulted with: "'+result+'")": '+error);} +if(debug){console.info('debug-ls-if result:',result);} +paths=expression.getPaths();let prv=element.$lsSkip;element.$lsSkip=!result;if(!result){element.style.visibility='hidden';element.style.display='none';} +else{element.style.removeProperty('display');element.style.removeProperty('visibility');} +if(prv===true&&element.$lsSkip===false){view.render(element)}};check();for(let i=0;i{let context=expr+'.'+index;container.addNamespace(as,context);if(debug){console.info('debug-ls-loop','index',index);console.info('debug-ls-loop','context',context);console.info('debug-ls-loop','context-path',container.path(context).name);console.info('debug-ls-loop','namespaces',container.namespaces);} +container.set(as,container.path(context),true,watch);container.set(key,index,true,false);view.render(children[prop]);container.removeNamespace(as);})(prop);} +element.dispatchEvent(new Event('looped'));};let template=(element.children.length===1)?element.children[0]:window.document.createElement('li');echo();container.bind(element,expr+'.length',echo);let path=(expr+'.length').split('.');while(path.length){container.bind(element,path.join('.'),echo);path.pop();}}});window.ls.container.get('view').add({selector:'data-ls-template',template:false,controller:function(element,view,http,expression,document,container){let template=element.getAttribute('data-ls-template')||'';let type=element.getAttribute('data-type')||'url';let debug=element.getAttribute('data-debug')||false;let paths=[];let check=function(init=false){let source=expression.parse(template);paths=expression.getPaths();element.innerHTML='';if('script'===type){let inlineTemplate=document.getElementById(source);if(inlineTemplate&&inlineTemplate.innerHTML){element.innerHTML=inlineTemplate.innerHTML;element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));} +else{if(debug){console.error('Missing template "'+source+'"');}} +if(!init){view.render(element);} +return;} +http.get(source).then(function(element){return function(data){element.innerHTML=data;view.render(element);element.dispatchEvent(new CustomEvent('template-loaded',{bubbles:true,cancelable:false}));}}(element),function(){throw new Error('Failed loading template');});};check(true);for(let i=0;i