1
0
Fork 0
mirror of synced 2024-05-17 19:22:34 +12:00

Merge pull request #1220 from appwrite/fix-user-empty-name

Fix user empty name
This commit is contained in:
Eldad A. Fux 2021-06-01 18:17:01 +03:00 committed by GitHub
commit f5ac40e576
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1425 additions and 342 deletions

View file

@ -57,6 +57,8 @@
- Fixed incorrect audit worker event names (#1143)
- Increased limit of memberships fetched in `createTeamMembership` to 2000 (#1143)
- Fixed exception thrown when SSL certificate is already stored in the database (#1151)
- Fixed user delete button in the Appwrite console (#1216)
- Fixed missing placeholder for user name when empty (#1220)
## Breaking Changes (Read before upgrading!)

View file

@ -77,8 +77,8 @@ $auth = $this->getParam('auth', []);
<td data-title="Name: ">
<a data-ls-attrs="href=/console/users/user?id={{user.$id}}&project={{router.params.project}}">
<span data-ls-bind="{{user.name}}"></span>
<span data-ls-if="{{user.name|escape}} === ''">-----</span>
<span data-ls-if="{{user.email}} === ''">Anonymous User</span>
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} !== ''">Unknown</span>
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === ''">Anonymous User</span>
</a>
</td>
<td data-title="Email: ">

View file

@ -12,7 +12,7 @@
<br />
<span data-ls-bind="{{team.name}}">&nbsp;</span>
<span data-ls-if="{{team.name}} === ''">Unknown</span>
<span data-ls-if="{{team.name|escape}} === ''">Unknown</span>
</h1>
</div>

View file

@ -12,8 +12,8 @@
<br />
<span data-ls-bind="{{user.name}}">&nbsp;</span>
<span data-ls-if="{{user.name}} === '' && {{user.email}} !== ''">Unknown</span>
<span data-ls-if="{{user.name}} === '' && {{user.email}} === ''">Anonymous User</span>
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} !== ''">Unknown</span>
<span data-ls-if="{{user.name|escape}} === '' && {{user.email}} === ''">Anonymous User</span>
</h1>
</div>
@ -97,7 +97,7 @@
<h3 class="text-danger">Danger Zone</h3>
<div class="box danger">
<div class="box danger margin-bottom">
<p>This is the area where you can delete this user.</p>
<p>By deleting this user you will lose all data associated with this user.</p>
@ -218,7 +218,7 @@
<button class="danger">Logout</button>
</form>
<div class="pull-start margin-end avatar-container">
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=60&height=60&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar" loading="lazy" width="60" height="60" />
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-attrs="src={{env.API}}/avatars/browsers/{{session.clientCode|lowercase}}?width=120&height=120&project={{env.PROJECT}},title={{session.clientName}},alt={{session.clientName}}" class="avatar" loading="lazy" width="60" height="60" />
<div data-ls-if="{{session.provider}} !== 'email'" class="corner">
<img data-ls-attrs="src=/images/users/{{session.provider}}.png?buster=<?php echo APP_CACHE_BUSTER; ?>,title={{session.provider}},alt={{session.provider}}" class="avatar xs" loading="lazy" width="30" height="30" />
@ -228,7 +228,7 @@
<span data-ls-bind="{{session.clientName}}"></span> <span data-ls-bind="{{session.clientVersion}}"></span> on <span data-ls-bind="{{session.deviceModel}}"></span> <span data-ls-bind="{{session.osName}}"></span> <span data-ls-bind="{{session.osVersion}}"></span>
<div class="margin-top-small">
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
<img onerror="this.onerror=null;this.src='/images/unknown.svg'" data-ls-if="{{session.countryCode}} !== '--'" data-ls-attrs="src={{env.API}}/avatars/flags/{{session.countryCode}}?width=120&height=120&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.countryName}}"></small>
</div>
</li>
@ -265,11 +265,11 @@
data-param-user-id="{{router.params.id}}"
data-event="load,logs-load">
<div data-ls-if="{{logs.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
<div data-ls-if="{{logs.logs.length}} === 0" style="display: none" class="margin-top-xxl margin-bottom-xxl text-align-center">
No logs available.
</div>
<div class="box" data-ls-if="{{logs.length}} !== 0" style="display: none">
<div class="box" data-ls-if="{{logs.logs.length}} !== 0" style="display: none">
<table class="vertical small">
<thead>
<tr>

View file

@ -1960,145 +1960,128 @@ function join(string1,string2){var separator=separatingNewlines(string1,string2)
function canConvert(input){return(input!=null&&(typeof input==='string'||(input.nodeType&&(input.nodeType===1||input.nodeType===9||input.nodeType===11))))}
return TurndownService;}());
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');}
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;}
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;}
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(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]);}
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;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;}
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]=[];}
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');}
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);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();}
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;}
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 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);});}}}
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;}
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(!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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;').replace(/\'/g,'&#39;').replace(/\//g,'&#x2F;');});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);}
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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/\'/g,"&#39;").replace(/\//g,"&#x2F;");});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;}
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(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());}
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;}
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("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.textContent=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);}
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.textContent=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,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&&element.style.visibility=='')?'hidden':'visible';for(let prop in array){if(counter==limit){break;}
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,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&&element.style.visibility==""?"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);}
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,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;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
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.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&amp;|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}

View file

@ -1,143 +1,126 @@
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');}
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;}
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;}
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(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]);}
let self=this;const REGEX_COMMENTS=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;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;}
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]=[];}
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');}
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);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();}
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;}
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 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);});}}}
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;}
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(!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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;').replace(/\'/g,'&#39;').replace(/\//g,'&#x2F;');});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);}
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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;").replace(/\'/g,"&#39;").replace(/\//g,"&#x2F;");});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;}
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(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());}
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;}
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("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.textContent=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);}
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.textContent=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,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&&element.style.visibility=='')?'hidden':'visible';for(let prop in array){if(counter==limit){break;}
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,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&&element.style.visibility==""?"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);}
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,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;i<paths.length;i++){let path=paths[i].split('.');while(path.length){container.bind(element,path.join('.'),check);path.pop();}}}});window.ls.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
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.error=function(){return function(error){window.console.error(error);if(window.location.pathname!=='/console'){window.location='/console';}};};window.addEventListener("error",function(event){console.error("ERROR-EVENT:",event.error.message,event.error.stack);});document.addEventListener("account.deleteSession",function(){window.location="/auth/signin";});document.addEventListener("account.create",function(){let container=window.ls.container;let form=container.get('serviceForm');let sdk=container.get('console');let promise=sdk.account.createSession(form.email,form.password);container.set("serviceForm",{},true,true);promise.then(function(){var subscribe=document.getElementById('newsletter').checked;if(subscribe){let alerts=container.get('alerts');let loaderId=alerts.add({text:'Loading...',class:""},0);fetch('https://appwrite.io/v1/newsletter/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:form.name,email:form.email,}),}).finally(function(){alerts.remove(loaderId);window.location='/console';});}else{window.location='/console';}},function(error){window.location='/auth/signup?failure=1';});});(function(window){"use strict";window.ls.container.set('alerts',function(window){return{list:[],ids:0,counter:0,max:5,add:function(message,time){var scope=this;message.id=scope.ids++;message.remove=function(){scope.remove(message.id);};scope.counter++;scope.list.unshift(message);if(scope.counter>scope.max){scope.list.pop();scope.counter--;}
if(time>0){window.setTimeout(function(message){return function(){scope.remove(message.id)}}(message),time);}
return message.id;},remove:function(id){let scope=this;for(let index=0;index<scope.list.length;index++){let obj=scope.list[index];if(obj.id===parseInt(id)){scope.counter--;if(typeof obj.callback==="function"){obj.callback();}
scope.list.splice(index,1);};}}};},true,true);})(window);(function(window){"use strict";window.ls.container.set('appwrite',function(window,env){let config={endpoint:'https://appwrite.io/v1',};let http=function(document,env){let globalParams=[],globalHeaders=[];let addParam=function(url,param,value){let a=document.createElement('a'),regex=/(?:\?|&amp;|&)+([^=]+)(?:=([^&]*))*/g;let match,str=[];a.href=url;param=encodeURIComponent(param);while(match=regex.exec(a.search))if(param!==match[1])str.push(match[1]+(match[2]?"="+match[2]:""));str.push(param+(value?"="+encodeURIComponent(value):""));a.search=str.join("&");return a.href;};let buildQuery=function(params){let str=[];for(let p in params){if(params.hasOwnProperty(p)){str.push(encodeURIComponent(p)+"="+encodeURIComponent(params[p]));}}

File diff suppressed because it is too large Load diff