2019-05-09 18:54:39 +12:00
2020-03-17 07:41:56 +13:00
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' ) ; }
2019-05-10 04:15:51 +12:00
if ( typeof singleton !== 'boolean' ) { throw new Error ( 'var singleton "' + singleton + '" of service "' + name + '" must be of type boolean' ) ; }
2019-08-06 16:19:16 +12:00
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 ) ) ; } }
2019-05-12 23:20:51 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
if ( key === "__watch" ) { return this . watch ; }
if ( key === "__proxy" ) { return true ; }
2020-09-24 18:40:41 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
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 ; }
2019-06-08 08:52:38 +12:00
return instance ; } ; let resolve = function ( target ) { if ( ! target ) { return ( ) => { } ; }
let self = this ; const REGEX _COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg ; const REGEX _FUNCTION _PARAMS = /(?:\s*(?:function\s*[^(]*)?\s*)((?:[^'"]|(?:(?:(['"])(?:(?:.*?[^\\]\2)|\2))))*?)\s*(?=(?:=>)|{)/m ; const REGEX _PARAMETERS _VALUES = /\s*([\w\\$]+)\s*(?:=\s*((?:(?:(['"])(?:\3|(?:.*?[^\\]\3)))((\s*\+\s*)(?:(?:(['"])(?:\6|(?:.*?[^\\]\6)))|(?:[\w$]*)))*)|.*?))?\s*(?:,|$)/gm ; function getParams ( func ) { let functionAsString = func . toString ( ) ; let params = [ ] ; let match ; functionAsString = functionAsString . replace ( REGEX _COMMENTS , '' ) ; functionAsString = functionAsString . match ( REGEX _FUNCTION _PARAMS ) [ 1 ] ; if ( functionAsString . charAt ( 0 ) === '(' ) { functionAsString = functionAsString . slice ( 1 , - 1 ) ; }
while ( match = REGEX _PARAMETERS _VALUES . exec ( functionAsString ) ) { params . push ( match [ 1 ] ) ; }
return params ; }
2020-03-17 07:41:56 +13:00
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 ; }
2019-05-10 04:15:51 +12:00
object = object [ path . shift ( ) ] ; }
2020-03-15 17:54:55 +13:00
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 ] = [ ] ; }
2020-04-28 06:38:06 +12:00
object [ shift ] . unshift ( value ) ; break ; case 'splice' : if ( ! Array . isArray ( object [ shift ] ) ) { object [ shift ] = [ ] ; }
2020-05-18 04:12:48 +12:00
object [ shift ] . splice ( value , 1 ) ; break ; default : object [ shift ] = value ; }
2020-03-15 17:54:55 +13:00
return true ; }
2019-05-12 23:20:51 +12:00
if ( ! object ) { return null ; }
2020-09-24 18:40:41 +12:00
if ( ! shift ) { result = object ; }
else { return object [ shift ] ; }
2020-03-17 07:41:56 +13:00
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' ) ; }
2019-05-10 04:15:51 +12:00
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 ) ; }
2020-09-24 18:40:41 +12:00
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 ) ; }
2019-05-10 04:15:51 +12:00
for ( let key in headers ) { if ( headers . hasOwnProperty ( key ) ) { xmlhttp . setRequestHeader ( key , headers [ key ] ) ; } }
2020-09-24 18:40:41 +12:00
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 ) ; }
2019-05-12 23:20:51 +12:00
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 ( ) ; }
2019-05-10 04:15:51 +12:00
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 ; }
2020-02-03 11:17:24 +13:00
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 ; }
2019-08-06 16:19:16 +12:00
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 ) ; }
2019-05-10 04:15:51 +12:00
if ( 1 !== node . nodeType ) { return ; }
if ( attrs && attrsLen ) { for ( let x = 0 ; x < attrsLen ; x ++ ) { if ( node . $lsSkip === true ) { break ; }
let pointer = ( ! /Edge/ . test ( navigator . userAgent ) ) ? x : ( attrsLen - 1 ) - x ; let length = attrsLen ; let attr = attrs [ pointer ] ; if ( ! stock [ attr ] ) { continue ; }
let comp = stock [ attr ] ; if ( typeof comp . template === "function" ) { comp . template = container . resolve ( comp . template ) ; }
if ( ! comp . template ) { ( function ( comp , node , container ) { execute ( comp , node , container ) ; } ) ( comp , node , container ) ; if ( length !== attrsLen ) { x -- ; }
2020-02-03 11:17:24 +13:00
if ( callback ) { callback ( ) ; }
2019-05-10 04:15:51 +12:00
continue ; }
2020-02-03 11:17:24 +13:00
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 ) ; } ) ; } } }
2019-05-10 04:15:51 +12:00
if ( true === node . $lsSkip ) { return ; }
let list = ( node ) ? node . childNodes : [ ] ; if ( node . $lsSkip === true ) { list = [ ] ; }
for ( let i = 0 ; i < list . length ; i ++ ) { let child = list [ i ] ; parse ( child ) ; } } ; return { stock : stock , add : function ( object ) { if ( typeof object !== 'object' ) { throw new Error ( 'object must be of type object' ) ; }
let defaults = { 'selector' : '' , 'controller' : function ( ) { } , 'template' : '' , 'repeat' : false , 'protected' : false } ; for ( let prop in defaults ) { if ( ! defaults . hasOwnProperty ( prop ) ) { continue ; }
if ( prop in object ) { continue ; }
object [ prop ] = defaults [ prop ] ; }
if ( ! object . selector ) { throw new Error ( 'View component is missing a selector attribute' ) ; }
2020-02-10 20:58:27 +13:00
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 ) ; }
2019-08-13 02:19:54 +12:00
let result = { } ; query . split ( '&' ) . forEach ( function ( part ) { if ( ! part ) { return ; }
2020-09-24 18:40:41 +12:00
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 ] ; }
2019-08-13 02:19:54 +12:00
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' ) ; }
2019-05-10 04:15:51 +12:00
if ( typeof view !== 'object' ) { throw new Error ( 'view must be of type object' ) ; }
2019-08-25 19:42:10 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
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 ; } }
2020-09-24 18:40:41 +12:00
return null } ; let change = function ( URL , replace ) { if ( ! replace ) { window . history . pushState ( { } , '' , URL ) ; }
else { window . history . replaceState ( { } , '' , URL ) ; }
2020-05-01 04:35:22 +12:00
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 ) ; }
2019-08-06 16:19:16 +12:00
if ( reference . length >= 2 ) { for ( let i = 1 ; i < reference . length ; i ++ ) { result = filter . apply ( reference [ i ] , result ) ; } }
2020-09-24 18:40:41 +12:00
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 + '\'' ; }
2020-04-16 16:58:27 +12:00
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 ; }
2019-08-20 22:10:32 +12:00
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 ; }
2020-09-24 18:40:41 +12:00
return value . replace ( /&/g , '&' ) . replace ( /</g , '<' ) . replace ( />/g , '>' ) . replace ( /\"/g , '"' ) . replace ( /\'/g , ''' ) . replace ( /\//g , '/' ) ; } ) ; window . ls = window . ls || { } ; window . ls . container . set ( 'window' , window , true , false ) . set ( 'document' , window . document , true , false ) . set ( 'element' , window . document , true , false ) ; window . ls . run = function ( window ) { try { this . view . render ( window . document ) ; }
catch ( error ) { let handler = window . ls . container . resolve ( this . error ) ; handler ( error ) ; } } ; window . ls . error = ( ) => { return error => { console . error ( 'ls-error' , error . message , error . stack , error . toString ( ) ) ; } } ; window . ls . router = window . ls . container . get ( 'router' ) ; window . ls . view = window . ls . container . get ( 'view' ) ; window . ls . filter = window . ls . container . get ( 'filter' ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-router' , controller : function ( element , window , document , view , router ) { let firstFromServer = ( element . getAttribute ( 'data-first-from-server' ) === 'true' ) ; let scope = { selector : 'data-ls-scope' , template : false , repeat : true , controller : function ( ) { } , } ; let init = function ( route ) { let count = parseInt ( element . getAttribute ( 'data-ls-scope-count' ) || 0 ) ; element . setAttribute ( 'data-ls-scope-count' , count + 1 ) ; window . scrollTo ( 0 , 0 ) ; if ( window . document . body . scrollTo ) { window . document . body . scrollTo ( 0 , 0 ) ; }
2019-05-10 04:15:51 +12:00
router . reset ( ) ; if ( null === route ) { return ; }
2020-09-24 18:40:41 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
while ( el = el . parentNode ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; } }
2019-08-06 16:19:16 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
if ( ! target . href ) { return false ; }
if ( ( event . metaKey ) ) { return false ; }
if ( ( target . hasAttribute ( 'target' ) ) && ( '_blank' === target . getAttribute ( 'target' ) ) ) { return false ; }
if ( target . hostname !== window . location . hostname ) { return false ; }
let route = router . match ( target ) ; if ( null === route ) { return false ; }
event . preventDefault ( ) ; if ( window . location === target . href ) { return false ; }
route . view . state = ( undefined === route . view . state ) ? true : route . view . state ; if ( true === route . view . state ) { if ( router . getPrevious ( ) && router . getPrevious ( ) . view && ( router . getPrevious ( ) . view . scope !== route . view . scope ) ) { window . location . href = target . href ; return false ; }
window . history . pushState ( { } , 'Unknown' , target . href ) ; }
2020-03-17 07:41:56 +13:00
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 ( ) ) ; }
2019-08-14 09:07:41 +12:00
if ( ! key ) { return null ; }
2020-09-24 18:40:41 +12:00
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' ) ; }
2019-08-06 16:19:16 +12:00
if ( bind ) { element . addEventListener ( 'change' , ( ) => { for ( let i = 0 ; i < paths . length ; i ++ ) { if ( element . checked ) { value = element . value ; }
2020-03-17 07:41:56 +13:00
container . path ( paths [ i ] , value ) ; } } ) ; }
2019-08-06 16:19:16 +12:00
return ; }
2020-09-24 18:40:41 +12:00
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 ; } }
2020-03-17 07:41:56 +13:00
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 ) ; }
2019-08-06 16:19:16 +12:00
if ( ! element . checked && index > - 1 ) { value . splice ( index , 1 ) ; }
2020-03-17 07:41:56 +13:00
container . path ( paths [ i ] , value ) ; } } ) ; }
2019-08-06 16:19:16 +12:00
return ; }
2019-08-21 23:00:32 +12:00
if ( element . value !== value ) { element . value = value ; element . dispatchEvent ( new Event ( 'change' ) ) ; }
2020-09-24 18:40:41 +12:00
if ( bind ) { element . addEventListener ( 'input' , sync ) ; element . addEventListener ( 'change' , sync ) ; } }
else { if ( element . innerHTML != value ) { element . innerHTML = value ; } } } ; let sync = ( ( ) => { return ( ) => { if ( debug ) { console . info ( 'debug-ls-bind' , 'sync-path' , paths ) ; console . info ( 'debug-ls-bind' , 'sync-syntax' , syntax ) ; console . info ( 'debug-ls-bind' , 'sync-syntax-parsed' , parsedSyntax ) ; console . info ( 'debug-ls-bind' , 'sync-value' , element . value ) ; }
2020-03-13 20:21:33 +13:00
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 ) ; }
2020-03-17 07:41:56 +13:00
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 ) ) ; }
2020-09-24 18:40:41 +12:00
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 ) ; }
2019-05-10 07:30:30 +12:00
if ( debug ) { console . info ( 'debug-ls-if result:' , result ) ; }
2020-09-24 18:40:41 +12:00
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 ; }
2019-05-10 04:15:51 +12:00
if ( array instanceof Array && typeof array !== 'object' ) { throw new Error ( 'Reference value must be array or object. ' + ( typeof array ) + ' given' ) ; }
2021-01-19 06:12:02 +13:00
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 ; }
2020-04-16 16:58:27 +12:00
counter ++ ; if ( ! array . hasOwnProperty ( prop ) ) { continue ; }
2020-03-17 07:41:56 +13:00
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 ) ; }
2020-04-28 06:38:06 +12:00
container . set ( as , container . path ( context ) , true , watch ) ; container . set ( key , index , true , false ) ; view . render ( children [ prop ] ) ; container . removeNamespace ( as ) ; } ) ( prop ) ; }
2020-09-24 18:40:41 +12:00
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 + '"' ) ; } }
2020-04-04 08:26:52 +13:00
if ( ! init ) { view . render ( element ) ; }
2019-05-10 04:15:51 +12:00
return ; }
2020-06-07 02:04:18 +12:00
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 ( ) { 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 -- ; }
2019-12-17 09:30:14 +13:00
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 ( ) ; }
2021-01-19 06:02:48 +13:00
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 = /(?:\?|&|&)+([^=]+)(?:=([^&]*))*/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 ] ) ) ; } }
2021-01-18 19:29:26 +13:00
return str . join ( "&" ) ; } ; let addGlobalHeader = function ( key , value ) { globalHeaders [ key ] = { key : key . toLowerCase ( ) , value : value . toLowerCase ( ) } ; } ; let addGlobalParam = function ( key , value ) { globalParams . push ( { key : key , value : value } ) ; } ; addGlobalHeader ( 'content-type' , '' ) ; let call = function ( method , path , headers = { } , params = { } , progress = null ) { let i ; path = config . endpoint + path ; 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 path !== 'string' ) { throw new Error ( 'var path must be of type string' ) ; }
if ( typeof headers !== 'object' ) { throw new Error ( 'var headers must be of type object' ) ; }
for ( i = 0 ; i < globalParams . length ; i ++ ) { path = addParam ( path , globalParams [ i ] . key , globalParams [ i ] . value ) ; }
for ( let key in globalHeaders ) { if ( globalHeaders . hasOwnProperty ( key ) ) { if ( ! headers [ globalHeaders [ key ] . key ] ) { headers [ globalHeaders [ key ] . key ] = globalHeaders [ key ] . value ; } } }
if ( method === 'GET' ) { for ( let param in params ) { if ( param . hasOwnProperty ( key ) ) { path = addParam ( path , key , params [ key ] ) ; } } }
switch ( headers [ 'content-type' ] ) { case 'application/json' : params = JSON . stringify ( params ) ; break ; case 'multipart/form-data' : let formData = new FormData ( ) ; for ( let param in params ) { if ( param . hasOwnProperty ( key ) ) { formData . append ( key , param [ key ] ) ; } }
params = formData ; break ; }
return new Promise ( function ( resolve , reject ) { let request = new XMLHttpRequest ( ) , key ; request . withCredentials = true ; request . open ( method , path , true ) ; for ( key in headers ) { if ( headers . hasOwnProperty ( key ) ) { request . setRequestHeader ( key , headers [ key ] ) ; } }
request . onload = function ( ) { if ( 4 === request . readyState && 399 >= request . status ) { let data = request . response ; let contentType = this . getResponseHeader ( 'content-type' ) ; contentType = contentType . substring ( 0 , contentType . indexOf ( ';' ) ) ; switch ( contentType ) { case 'application/json' : data = JSON . parse ( data ) ; break ; }
resolve ( data ) ; } else { reject ( new Error ( request . statusText ) ) ; } } ; if ( progress ) { request . addEventListener ( 'progress' , progress ) ; request . upload . addEventListener ( 'progress' , progress , false ) ; }
2021-01-19 06:02:48 +13:00
request . onerror = function ( ) { reject ( new Error ( "Network Error" ) ) ; } ; request . send ( params ) ; } ) } ; return { 'get' : function ( path , headers = { } , params = { } ) { return call ( 'GET' , path + ( ( params . length > 0 ) ? '?' + buildQuery ( params ) : '' ) , headers , { } ) ; } , 'post' : function ( path , headers = { } , params = { } , progress = null ) { return call ( 'POST' , path , headers , params , progress ) ; } , 'put' : function ( path , headers = { } , params = { } , progress = null ) { return call ( 'PUT' , headers , params , progress ) ; } , 'patch' : function ( path , headers = { } , params = { } , progress = null ) { return call ( 'PATCH' , path , headers , params , progress ) ; } , 'delete' : function ( path , headers = { } , params = { } , progress = null ) { return call ( 'DELETE' , path , headers , params , progress ) ; } , 'addGlobalParam' : addGlobalParam , 'addGlobalHeader' : addGlobalHeader } } ( window . document ) ; let analytics = { create : function ( id , source , activity , url ) { return http . post ( '/analytics' , { 'content-type' : 'application/json' } , { id : id , source : source , activity : activity , url : url , version : env . VERSION , setup : env . SETUP } ) ; } , } ; return { analytics : analytics , } ; } , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'console' , function ( window ) { var sdk = new window . Appwrite ( ) ; sdk . setEndpoint ( APP _ENV . API ) . setProject ( 'console' ) . setLocale ( APP _ENV . LOCALE ) ; return sdk ; } , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'date' , function ( ) { function format ( format , timestamp ) { var jsdate , f
2019-05-09 18:54:39 +12:00
var txtWords = [ 'Sun' , 'Mon' , 'Tues' , 'Wednes' , 'Thurs' , 'Fri' , 'Satur' , 'January' , 'February' , 'March' , 'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' ]
var formatChr = /\\?(.?)/gi
var formatChrCb = function ( t , s ) { return f [ t ] ? f [ t ] ( ) : s }
var _pad = function ( n , c ) { n = String ( n )
while ( n . length < c ) { n = '0' + n }
return n }
f = { d : function ( ) { return _pad ( f . j ( ) , 2 ) } , D : function ( ) { return f . l ( ) . slice ( 0 , 3 ) } , j : function ( ) { return jsdate . getDate ( ) } , l : function ( ) { return txtWords [ f . w ( ) ] + 'day' } , N : function ( ) { return f . w ( ) || 7 } , S : function ( ) { var j = f . j ( )
var i = j % 10
if ( i <= 3 && parseInt ( ( j % 100 ) / 10 , 10 ) === 1 ) { i = 0 }
return [ 'st' , 'nd' , 'rd' ] [ i - 1 ] || 'th' } , w : function ( ) { return jsdate . getDay ( ) } , z : function ( ) { var a = new Date ( f . Y ( ) , f . n ( ) - 1 , f . j ( ) )
var b = new Date ( f . Y ( ) , 0 , 1 )
return Math . round ( ( a - b ) / 864e5 ) } , W : function ( ) { var a = new Date ( f . Y ( ) , f . n ( ) - 1 , f . j ( ) - f . N ( ) + 3 )
var b = new Date ( a . getFullYear ( ) , 0 , 4 )
return _pad ( 1 + Math . round ( ( a - b ) / 864e5 / 7 ) , 2 ) } , F : function ( ) { return txtWords [ 6 + f . n ( ) ] } , m : function ( ) { return _pad ( f . n ( ) , 2 ) } , M : function ( ) { return f . F ( ) . slice ( 0 , 3 ) } , n : function ( ) { return jsdate . getMonth ( ) + 1 } , t : function ( ) { return ( new Date ( f . Y ( ) , f . n ( ) , 0 ) ) . getDate ( ) } , L : function ( ) { var j = f . Y ( )
return j % 4 === 0 & j % 100 !== 0 | j % 400 === 0 } , o : function ( ) { var n = f . n ( )
var W = f . W ( )
var Y = f . Y ( )
return Y + ( n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? - 1 : 0 ) } , Y : function ( ) { return jsdate . getFullYear ( ) } , y : function ( ) { return f . Y ( ) . toString ( ) . slice ( - 2 ) } , a : function ( ) { return jsdate . getHours ( ) > 11 ? 'pm' : 'am' } , A : function ( ) { return f . a ( ) . toUpperCase ( ) } , B : function ( ) { var H = jsdate . getUTCHours ( ) * 36e2
var i = jsdate . getUTCMinutes ( ) * 60
var s = jsdate . getUTCSeconds ( )
return _pad ( Math . floor ( ( H + i + s + 36e2 ) / 86.4 ) % 1e3 , 3 ) } , g : function ( ) { return f . G ( ) % 12 || 12 } , G : function ( ) { return jsdate . getHours ( ) } , h : function ( ) { return _pad ( f . g ( ) , 2 ) } , H : function ( ) { return _pad ( f . G ( ) , 2 ) } , i : function ( ) { return _pad ( jsdate . getMinutes ( ) , 2 ) } , s : function ( ) { return _pad ( jsdate . getSeconds ( ) , 2 ) } , u : function ( ) { return _pad ( jsdate . getMilliseconds ( ) * 1000 , 6 ) } , e : function ( ) { var msg = 'Not supported (see source code of date() for timezone on how to add support)'
throw new Error ( msg ) } , I : function ( ) { var a = new Date ( f . Y ( ) , 0 )
var c = Date . UTC ( f . Y ( ) , 0 )
var b = new Date ( f . Y ( ) , 6 )
var d = Date . UTC ( f . Y ( ) , 6 )
return ( ( a - c ) !== ( b - d ) ) ? 1 : 0 } , O : function ( ) { var tzo = jsdate . getTimezoneOffset ( )
var a = Math . abs ( tzo )
return ( tzo > 0 ? '-' : '+' ) + _pad ( Math . floor ( a / 60 ) * 100 + a % 60 , 4 ) } , P : function ( ) { var O = f . O ( )
return ( O . substr ( 0 , 3 ) + ':' + O . substr ( 3 , 2 ) ) } , T : function ( ) { return 'UTC' } , Z : function ( ) { return - jsdate . getTimezoneOffset ( ) * 60 } , c : function ( ) { return 'Y-m-d\\TH:i:sP' . replace ( formatChr , formatChrCb ) } , r : function ( ) { return 'D, d M Y H:i:s O' . replace ( formatChr , formatChrCb ) } , U : function ( ) { return jsdate / 1000 | 0 } }
var _date = function ( format , timestamp ) { jsdate = ( timestamp === undefined ? new Date ( ) : ( timestamp instanceof Date ) ? new Date ( timestamp ) : new Date ( timestamp * 1000 ) )
return format . replace ( formatChr , formatChrCb ) }
return _date ( format , timestamp ) }
function strtotime ( text , now ) { var parsed
var match
var today
var year
var date
var days
var ranges
var len
var times
var regex
var i
var fail = false
if ( ! text ) { return fail }
text = text . replace ( /^\s+|\s+$/g , '' ) . replace ( /\s{2,}/g , ' ' ) . replace ( /[\t\r\n]/g , '' ) . toLowerCase ( )
var pattern = new RegExp ( [ '^(\\d{1,4})' , '([\\-\\.\\/:])' , '(\\d{1,2})' , '([\\-\\.\\/:])' , '(\\d{1,4})' , '(?:\\s(\\d{1,2}):(\\d{2})?:?(\\d{2})?)?' , '(?:\\s([A-Z]+)?)?$' ] . join ( '' ) )
match = text . match ( pattern )
if ( match && match [ 2 ] === match [ 4 ] ) { if ( match [ 1 ] > 1901 ) { switch ( match [ 2 ] ) { case '-' : if ( match [ 3 ] > 12 || match [ 5 ] > 31 ) { return fail }
return new Date ( match [ 1 ] , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 5 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000
case '.' : return fail
case '/' : if ( match [ 3 ] > 12 || match [ 5 ] > 31 ) { return fail }
return new Date ( match [ 1 ] , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 5 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000 } } else if ( match [ 5 ] > 1901 ) { switch ( match [ 2 ] ) { case '-' : if ( match [ 3 ] > 12 || match [ 1 ] > 31 ) { return fail }
return new Date ( match [ 5 ] , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 1 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000
case '.' : if ( match [ 3 ] > 12 || match [ 1 ] > 31 ) { return fail }
return new Date ( match [ 5 ] , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 1 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000
case '/' : if ( match [ 1 ] > 12 || match [ 3 ] > 31 ) { return fail }
return new Date ( match [ 5 ] , parseInt ( match [ 1 ] , 10 ) - 1 , match [ 3 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000 } } else { switch ( match [ 2 ] ) { case '-' : if ( match [ 3 ] > 12 || match [ 5 ] > 31 || ( match [ 1 ] < 70 && match [ 1 ] > 38 ) ) { return fail }
year = match [ 1 ] >= 0 && match [ 1 ] <= 38 ? + match [ 1 ] + 2000 : match [ 1 ]
return new Date ( year , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 5 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000
case '.' : if ( match [ 5 ] >= 70 ) { if ( match [ 3 ] > 12 || match [ 1 ] > 31 ) { return fail }
return new Date ( match [ 5 ] , parseInt ( match [ 3 ] , 10 ) - 1 , match [ 1 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000 }
if ( match [ 5 ] < 60 && ! match [ 6 ] ) { if ( match [ 1 ] > 23 || match [ 3 ] > 59 ) { return fail }
today = new Date ( )
return new Date ( today . getFullYear ( ) , today . getMonth ( ) , today . getDate ( ) , match [ 1 ] || 0 , match [ 3 ] || 0 , match [ 5 ] || 0 , match [ 9 ] || 0 ) / 1000 }
return fail
case '/' : if ( match [ 1 ] > 12 || match [ 3 ] > 31 || ( match [ 5 ] < 70 && match [ 5 ] > 38 ) ) { return fail }
year = match [ 5 ] >= 0 && match [ 5 ] <= 38 ? + match [ 5 ] + 2000 : match [ 5 ]
return new Date ( year , parseInt ( match [ 1 ] , 10 ) - 1 , match [ 3 ] , match [ 6 ] || 0 , match [ 7 ] || 0 , match [ 8 ] || 0 , match [ 9 ] || 0 ) / 1000
case ':' : if ( match [ 1 ] > 23 || match [ 3 ] > 59 || match [ 5 ] > 59 ) { return fail }
today = new Date ( )
return new Date ( today . getFullYear ( ) , today . getMonth ( ) , today . getDate ( ) , match [ 1 ] || 0 , match [ 3 ] || 0 , match [ 5 ] || 0 ) / 1000 } } }
if ( text === 'now' ) { return now === null || isNaN ( now ) ? new Date ( ) . getTime ( ) / 1000 | 0 : now | 0 }
if ( ! isNaN ( parsed = Date . parse ( text ) ) ) { return parsed / 1000 | 0 }
pattern = new RegExp ( [ '^([0-9]{4}-[0-9]{2}-[0-9]{2})' , '[ t]' , '([0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?)' , '([\\+-][0-9]{2}(:[0-9]{2})?|z)' ] . join ( '' ) )
match = text . match ( pattern )
if ( match ) { if ( match [ 4 ] === 'z' ) { match [ 4 ] = 'Z' } else if ( match [ 4 ] . match ( /^([+-][0-9]{2})$/ ) ) { match [ 4 ] = match [ 4 ] + ':00' }
if ( ! isNaN ( parsed = Date . parse ( match [ 1 ] + 'T' + match [ 2 ] + match [ 4 ] ) ) ) { return parsed / 1000 | 0 } }
date = now ? new Date ( now * 1000 ) : new Date ( )
days = { 'sun' : 0 , 'mon' : 1 , 'tue' : 2 , 'wed' : 3 , 'thu' : 4 , 'fri' : 5 , 'sat' : 6 }
ranges = { 'yea' : 'FullYear' , 'mon' : 'Month' , 'day' : 'Date' , 'hou' : 'Hours' , 'min' : 'Minutes' , 'sec' : 'Seconds' }
function lastNext ( type , range , modifier ) { var diff
var day = days [ range ]
if ( typeof day !== 'undefined' ) { diff = day - date . getDay ( )
if ( diff === 0 ) { diff = 7 * modifier } else if ( diff > 0 && type === 'last' ) { diff -= 7 } else if ( diff < 0 && type === 'next' ) { diff += 7 }
date . setDate ( date . getDate ( ) + diff ) } }
function process ( val ) { var splt = val . split ( ' ' )
var type = splt [ 0 ]
var range = splt [ 1 ] . substring ( 0 , 3 )
var typeIsNumber = /\d+/ . test ( type )
var ago = splt [ 2 ] === 'ago'
var num = ( type === 'last' ? - 1 : 1 ) * ( ago ? - 1 : 1 )
if ( typeIsNumber ) { num *= parseInt ( type , 10 ) }
if ( ranges . hasOwnProperty ( range ) && ! splt [ 1 ] . match ( /^mon(day|\.)?$/i ) ) { return date [ 'set' + ranges [ range ] ] ( date [ 'get' + ranges [ range ] ] ( ) + num ) }
if ( range === 'wee' ) { return date . setDate ( date . getDate ( ) + ( num * 7 ) ) }
if ( type === 'next' || type === 'last' ) { lastNext ( type , range , num ) } else if ( ! typeIsNumber ) { return false }
return true }
times = '(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec' + '|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?' + '|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)'
regex = '([+-]?\\d+\\s' + times + '|' + '(last|next)\\s' + times + ')(\\sago)?'
match = text . match ( new RegExp ( regex , 'gi' ) )
if ( ! match ) { return fail }
for ( i = 0 , len = match . length ; i < len ; i ++ ) { if ( ! process ( match [ i ] ) ) { return fail } }
return ( date . getTime ( ) / 1000 ) }
2020-06-10 15:11:53 +12:00
return { format : format , strtotime : strtotime } } ( ) , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'env' , function ( ) { return APP _ENV ; } , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'form' , function ( ) { function cast ( value , to ) { switch ( to ) { case 'int' : case 'integer' : value = parseInt ( value ) ; break ; case 'numeric' : value = Number ( value ) ; break ; case 'string' : value = value . toString ( ) ; break ; case 'json' : value = ( value ) ? JSON . parse ( value ) : [ ] ; break ; case 'array' : value = ( value && value . constructor && value . constructor === Array ) ? value : [ value ] ; break ; case 'array-empty' : value = [ ] ; break ; case 'bool' : case 'boolean' : value = ( value === 'false' ) ? false : value ; value = ! ! value ; break ; }
2019-05-13 06:15:19 +12:00
return value ; }
function toJson ( element , json ) { json = json || { } ; let name = element . getAttribute ( 'name' ) ; let type = element . getAttribute ( 'type' ) ; let castTo = element . getAttribute ( 'data-cast-to' ) ; let ref = json ; if ( name && 'FORM' !== element . tagName ) { if ( 'FIELDSET' === element . tagName ) { if ( castTo === 'object' ) { if ( json [ name ] === undefined ) { json [ name ] = { } ; }
ref = json [ name ] ; }
else { if ( ! Array . isArray ( json [ name ] ) ) { json [ name ] = [ ] ; }
json [ name ] . push ( { } ) ; ref = json [ name ] [ json [ name ] . length - 1 ] ; } }
else if ( undefined !== element . value ) { if ( 'SELECT' === element . tagName && element . children > 0 ) { json [ name ] = element . children [ element . selectedIndex ] . value ; }
else if ( 'radio' === type ) { if ( element . checked ) { json [ name ] = element . value ; } }
else if ( 'checkbox' === type ) { if ( ! Array . isArray ( json [ name ] ) ) { json [ name ] = [ ] ; }
if ( element . checked ) { json [ name ] . push ( element . value ) ; } }
2019-08-24 17:00:40 +12:00
else if ( 'file' === type ) { json [ name ] = element . files [ 0 ] ; }
2019-05-13 06:15:19 +12:00
else if ( undefined !== element . value ) { if ( ( json [ name ] !== undefined ) && ( ! Array . isArray ( json [ name ] ) ) ) { json [ name ] = [ json [ name ] ] ; }
if ( Array . isArray ( json [ name ] ) ) { json [ name ] . push ( element . value ) ; }
else { json [ name ] = element . value ; } }
json [ name ] = cast ( json [ name ] , castTo ) ; } }
for ( let i = 0 ; i < element . children . length ; i ++ ) { if ( Array . isArray ( ref ) ) { ref . push ( { } ) ; toJson ( element . children [ i ] , ref [ ref . length ] ) ; }
else { toJson ( element . children [ i ] , ref ) ; } }
return json ; }
return { 'toJson' : toJson } } , true , false ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'markdown' , function ( window ) { var md = window . markdownit ( ) ; function renderEm ( tokens , idx , opts , _ , slf ) { var token = tokens [ idx ] ; if ( token . markup === '__' ) { token . tag = 'u' ; }
2019-05-09 18:54:39 +12:00
return slf . renderToken ( tokens , idx , opts ) ; }
2020-05-01 04:35:22 +12:00
md . renderer . rules . strong _open = renderEm ; md . renderer . rules . strong _close = renderEm ; return md ; } , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'rtl' , function ( ) { var rtlStock = "^ا ^ب^ت^ث^ج^ح^خ^د^ذ^ر^ز^س^ش^ص^ض^ط^ظ^ع^غ^ف^ق^ك^ل^م^ن^ه ^و^ي^א^ב^ג^ד^ה^ו ^ז^ח^ט ^י ^כ^ך^ל^מ^ם^נ^ן ^ס ^ע^פ^ף^צ^ץ^ק^ר^ש^ת^" ; var special = [ "\n" , " " , " " , "״" , '"' , "_" , "'" , "!" , "@" , "#" , "$" , "^" , "&" , "%" , "*" , "(" , ")" , "+" , "=" , "-" , "[" , "]" , "\\" , "/" , "{" , "}" , "|" , ":" , "<" , ">" , "?" , "," , "." , "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" ] ; var isRTL = function ( value ) { for ( var i = 0 ; i < value . length ; i ++ ) { if ( /\s/g . test ( value [ i ] ) ) { continue ; }
if ( - 1 === special . indexOf ( value [ i ] ) ) { var firstChar = value [ i ] ; break ; } }
if ( - 1 < rtlStock . indexOf ( "^" + firstChar + "^" ) ) { return true ; }
2020-08-18 17:26:28 +12:00
return false ; } ; return { isRTL : isRTL , } ; } , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'sdk' , function ( window , router ) { var sdk = new window . Appwrite ( ) ; sdk . setEndpoint ( APP _ENV . API ) . setProject ( router . params . project || '' ) . setLocale ( APP _ENV . LOCALE ) . setMode ( 'admin' ) ; return sdk ; } , false ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'search' , function ( window ) { return { params : { } , path : '' , pointer : '' , selected : '' , } ; } , true , true ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'timezone' , function ( ) { return { convert : function ( unixTime ) { var timezoneMinutes = new Date ( ) . getTimezoneOffset ( ) ; timezoneMinutes = ( timezoneMinutes === 0 ) ? 0 : - timezoneMinutes ; return parseInt ( unixTime ) + ( timezoneMinutes * 60 ) ; } } ; } , true ) ; } ) ( window ) ; window . ls . router . add ( "/auth/signin" , { template : "/auth/signin?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/signup" , { template : "/auth/signup?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/recovery" , { template : "/auth/recovery?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/recovery/reset" , { template : "/auth/recovery/reset?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/confirm" , { template : "/auth/confirm?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/join" , { template : "/auth/join?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/oauth2/success" , { template : "/auth/oauth2/success?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/auth/oauth2/failure" , { template : "/auth/oauth2/failure?version=" + APP _ENV . CACHEBUSTER , scope : "home" } ) . add ( "/console" , { template : "/console?version=" + APP _ENV . CACHEBUSTER , scope : "console" } ) . add ( "/console/account" , { template : "/console/account?version=" + APP _ENV . CACHEBUSTER , scope : "console" } ) . add ( "/console/account/:tab" , { template : "/console/account?version=" + APP _ENV . CACHEBUSTER , scope : "console" } ) . add ( "/console/home" , { template : "/console/home?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/home/:tab" , { template : "/console/home?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/platforms/:platform" , { template : function ( window ) { return window . location . pathname + "?version=" + APP _ENV . CACHEBUSTER ; } , scope : "console" , project : true } ) . add ( "/console/notifications" , { template : "/console/notifications?version=" + APP _ENV . CACHEBUSTER , scope : "console" } ) . add ( "/console/settings" , { template : "/console/settings?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/settings/:tab" , { template : "/console/settings?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/webhooks" , { template : "/console/webhooks?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/webhooks/:tab" , { template : "/console/webhooks?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/keys" , { template : "/console/keys?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/keys/:tab" , { template : "/console/keys?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/tasks" , { template : "/console/tasks?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/tasks/:tab" , { template : "/console/tasks?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/database" , { template : "/console/database?version=" + APP _ENV . CACHEBUSTER , scope : "console" , project : true } ) . add ( "/console/database/collection" , { template : function ( window ) { return window . location . pathname + window . location . search + '&version=' + APP _ENV . CACHEBUSTER ; } , scope : "console" , project : true } ) . add ( "/console/database/collection/:tab" , { template : function ( window ) { return window . location . pathname + window . location . search + '&version=' + APP _ENV . CACHEBUSTER ; } , scope : "console" , project : true } ) . add ( "/console/database/document" , { template : function ( window ) { return window . location . pathname + window . location . search + '&version=' + APP _ENV . CACHEBUSTER ; } , scope : "console" , project : true } ) . add ( "/console/database/document/:tab" , { template : function ( window ) { return window . location . pathname + window . location . search + '&version=' + APP _ENV . CACHEBUSTER ; } , scope : "console" , project : true } ) . add ( "/console/storage" , { template : " / console / st
2020-06-11 20:58:53 +12:00
let size = element . dataset [ "size" ] || 80 ; let name = $value . name || $value || "" ; name = ( typeof name !== 'string' ) ? '--' : name ; return def = "/v1/avatars/initials?project=console" + "&name=" +
2020-06-10 09:31:15 +12:00
encodeURIComponent ( name ) + "&width=" +
size + "&height=" +
2020-07-18 18:16:34 +12:00
size ; } ) . add ( "selectedCollection" , function ( $value , router ) { return $value === router . params . collectionId ? "selected" : "" ; } ) . add ( "selectedDocument" , function ( $value , router ) { return $value === router . params . documentId ? "selected" : "" ; } ) . add ( "localeString" , function ( $value ) { $value = parseInt ( $value ) ; return ! Number . isNaN ( $value ) ? $value . toLocaleString ( ) : "" ; } ) . add ( "date" , function ( $value , date ) { return date . format ( "Y-m-d" , $value ) ; } ) . add ( "dateTime" , function ( $value , date ) { return date . format ( "Y-m-d H:i" , $value ) ; } ) . add ( "dateText" , function ( $value , date ) { return date . format ( "d M Y" , $value ) ; } ) . add ( "timeSince" , function ( $value ) { $value = $value * 1000 ; let seconds = Math . floor ( ( Date . now ( ) - $value ) / 1000 ) ; let unit = "second" ; let direction = "ago" ; if ( seconds < 0 ) { seconds = - seconds ; direction = "from now" ; }
let value = seconds ; if ( seconds >= 31536000 ) { value = Math . floor ( seconds / 31536000 ) ; unit = "year" ; }
else if ( seconds >= 86400 ) { value = Math . floor ( seconds / 86400 ) ; unit = "day" ; }
else if ( seconds >= 3600 ) { value = Math . floor ( seconds / 3600 ) ; unit = "hour" ; }
else if ( seconds >= 60 ) { value = Math . floor ( seconds / 60 ) ; unit = "minute" ; }
if ( value != 1 ) { unit = unit + "s" ; }
return value + " " + unit + " " + direction ; } ) . add ( "ms2hum" , function ( $value ) { let temp = $value ; const years = Math . floor ( temp / 31536000 ) , days = Math . floor ( ( temp %= 31536000 ) / 86400 ) , hours = Math . floor ( ( temp %= 86400 ) / 3600 ) , minutes = Math . floor ( ( temp %= 3600 ) / 60 ) , seconds = temp % 60 ; if ( days || hours || seconds || minutes ) { return ( ( years ? years + "y " : "" ) +
2019-05-09 18:54:39 +12:00
( days ? days + "d " : "" ) +
( hours ? hours + "h " : "" ) +
( minutes ? minutes + "m " : "" ) +
2019-09-13 22:47:48 +12:00
Number . parseFloat ( seconds ) . toFixed ( 0 ) + "s" ) ; }
2020-07-18 20:13:15 +12:00
return "< 1s" ; } ) . add ( "seconds2hum" , function ( $value ) { var seconds = ( $value ) . toFixed ( 3 ) ; var minutes = ( $value / ( 60 ) ) . toFixed ( 1 ) ; var hours = ( $value / ( 60 * 60 ) ) . toFixed ( 1 ) ; var days = ( $value / ( 60 * 60 * 24 ) ) . toFixed ( 1 ) ; if ( seconds < 60 ) { return seconds + "s" ; } else if ( minutes < 60 ) { return minutes + "m" ; } else if ( hours < 24 ) { return hours + "h" ; } else { return days + "d" } } ) . add ( "markdown" , function ( $value , markdown ) { return markdown . render ( $value ) ; } ) . add ( "pageCurrent" , function ( $value , env ) { return Math . ceil ( parseInt ( $value || 0 ) / env . PAGING _LIMIT ) + 1 ; } ) . add ( "pageTotal" , function ( $value , env ) { let total = Math . ceil ( parseInt ( $value || 0 ) / env . PAGING _LIMIT ) ; return total ? total : 1 ; } ) . add ( "humanFileSize" , function ( $value ) { if ( ! $value ) { return 0 ; }
2019-09-13 22:47:48 +12:00
let thresh = 1000 ; if ( Math . abs ( $value ) < thresh ) { return $value + " B" ; }
let units = [ "kB" , "MB" , "GB" , "TB" , "PB" , "EB" , "ZB" , "YB" ] ; let u = - 1 ; do { $value /= thresh ; ++ u ; } while ( Math . abs ( $value ) >= thresh && u < units . length - 1 ) ; return ( $value . toFixed ( 1 ) + '<span class="text-size-small unit">' +
units [ u ] + "</span>" ) ; } ) . add ( "statsTotal" , function ( $value ) { if ( ! $value ) { return 0 ; }
2020-05-30 00:02:53 +12:00
$value = abbreviate ( $value , 0 , false , false ) ; return $value === "0" ? "N/A" : $value ; } ) . add ( "isEmpty" , function ( $value ) { return ( ! ! $value ) ; } ) . add ( "isEmptyObject" , function ( $value ) { return ( ( Object . keys ( $value ) . length === 0 && $value . constructor === Object ) || $value . length === 0 ) } ) . add ( "activeDomainsCount" , function ( $value ) { let result = [ ] ; if ( Array . isArray ( $value ) ) { result = $value . filter ( function ( node ) { return ( node . verification && node . certificateId ) ; } ) ; }
2020-05-03 21:50:23 +12:00
return result . length ; } ) . add ( "documentAction" , function ( container ) { let collection = container . get ( 'project-collection' ) ; let document = container . get ( 'project-document' ) ; if ( collection && document && ! document . $id ) { return 'database.createDocument' ; }
2020-04-26 08:33:35 +12:00
return 'database.updateDocument' ; } ) . add ( "documentSuccess" , function ( container ) { let document = container . get ( 'project-document' ) ; if ( document && ! document . $id ) { return ',redirect' ; }
return '' ; } ) . add ( "firstElement" , function ( $value ) { if ( $value && $value [ 0 ] ) { return $value [ 0 ] ; }
2020-06-08 16:38:39 +12:00
return $value ; } ) . add ( "platformsLimit" , function ( $value ) { return $value ; } ) . add ( "limit" , function ( $value ) { let postfix = ( $value . length >= 50 ) ? '...' : '' ; return $value . substring ( 0 , 50 ) + postfix ; ; } ) . add ( "arraySentence" , function ( $value ) { if ( ! Array . isArray ( $value ) ) { return '' ; }
2020-07-15 18:02:56 +12:00
return $value . join ( ", " ) . replace ( /,\s([^,]+)$/ , ' and $1' ) ; } ) . add ( "envName" , function ( $value , env ) { if ( env && env . ENVIRONMENTS && env . ENVIRONMENTS [ $value ] ) { return env . ENVIRONMENTS [ $value ] . name ; }
return '' ; } ) . add ( "envLogo" , function ( $value , env ) { if ( env && env . ENVIRONMENTS && env . ENVIRONMENTS [ $value ] ) { return env . ENVIRONMENTS [ $value ] . logo ; }
return '' ; } ) . add ( "envVersion" , function ( $value , env ) { if ( env && env . ENVIRONMENTS && env . ENVIRONMENTS [ $value ] ) { return env . ENVIRONMENTS [ $value ] . version ; }
2020-07-15 06:55:44 +12:00
return '' ; } ) ; function abbreviate ( number , maxPlaces , forcePlaces , forceLetter ) { number = Number ( number ) ; forceLetter = forceLetter || false ; if ( forceLetter !== false ) { return annotate ( number , maxPlaces , forcePlaces , forceLetter ) ; }
2019-09-13 22:47:48 +12:00
let abbr ; if ( number >= 1e12 ) { abbr = "T" ; } else if ( number >= 1e9 ) { abbr = "B" ; } else if ( number >= 1e6 ) { abbr = "M" ; } else if ( number >= 1e3 ) { abbr = "K" ; } else { abbr = "" ; }
2019-05-09 18:54:39 +12:00
return annotate ( number , maxPlaces , forcePlaces , abbr ) ; }
2019-09-13 22:47:48 +12:00
function annotate ( number , maxPlaces , forcePlaces , abbr ) { let rounded = 0 ; switch ( abbr ) { case "T" : rounded = number / 1e12 ; break ; case "B" : rounded = number / 1e9 ; break ; case "M" : rounded = number / 1e6 ; break ; case "K" : rounded = number / 1e3 ; break ; case "" : rounded = number ; break ; }
if ( maxPlaces !== false ) { let test = new RegExp ( "\\.\\d{" + ( maxPlaces + 1 ) + ",}$" ) ; if ( test . test ( "" + rounded ) ) { rounded = rounded . toFixed ( maxPlaces ) ; } }
if ( forcePlaces !== false ) { rounded = Number ( rounded ) . toFixed ( forcePlaces ) ; }
return rounded + abbr ; }
window . ls . container . get ( "view" ) . add ( { selector : "data-acl" , controller : function ( element , document , router , alerts ) { document . body . classList . remove ( "console" ) ; document . body . classList . remove ( "home" ) ; document . body . classList . add ( router . getCurrent ( ) . view . scope ) ; if ( ! router . getCurrent ( ) . view . project ) { document . body . classList . add ( "hide-nav" ) ; document . body . classList . remove ( "show-nav" ) ; } else { document . body . classList . add ( "show-nav" ) ; document . body . classList . remove ( "hide-nav" ) ; }
2020-05-11 16:39:00 +12:00
if ( "/console" === router . getCurrent ( ) . path ) { document . body . classList . add ( "index" ) ; } else { document . body . classList . remove ( "index" ) ; } } } ) . add ( { selector : "data-prism" , controller : function ( window , document , element , alerts ) { Prism . highlightElement ( element ) ; let copy = document . createElement ( "i" ) ; copy . className = "icon-docs copy" ; copy . title = "Copy to Clipboard" ; copy . textContent = "Click Here to Copy" ; copy . addEventListener ( "click" , function ( ) { window . getSelection ( ) . removeAllRanges ( ) ; let range = document . createRange ( ) ; range . selectNode ( element ) ; window . getSelection ( ) . addRange ( range ) ; try { document . execCommand ( "copy" ) ; alerts . add ( { text : "Copied to clipboard" , class : "" } , 3000 ) ; } catch ( err ) { alerts . add ( { text : "Failed to copy text " , class : "error" } , 3000 ) ; }
2020-05-13 08:15:36 +12:00
window . getSelection ( ) . removeAllRanges ( ) ; } ) ; element . parentNode . parentNode . appendChild ( copy ) ; } } ) ; ( function ( window ) { "use strict" ; window . ls . view . add ( { selector : "data-service" , controller : function ( element , view , container , form , alerts , expression , window ) { let action = element . dataset [ "service" ] ; let service = element . dataset [ "name" ] || null ; let event = expression . parse ( element . dataset [ "event" ] ) ; let confirm = element . dataset [ "confirm" ] || "" ; let loading = element . dataset [ "loading" ] || "" ; let loaderId = null ; let scope = element . dataset [ "scope" ] || "sdk" ; let success = element . dataset [ "success" ] || "" ; let failure = element . dataset [ "failure" ] || "" ; let running = false ; let callbacks = { hide : function ( ) { return function ( ) { return element . style . opacity = '0' ; } ; } , reset : function ( ) { return function ( ) { if ( "FORM" === element . tagName ) { return element . reset ( ) ; }
2019-10-11 06:32:41 +13:00
throw new Error ( "This callback is only valid for forms" ) ; } ; } , alert : function ( text , classname ) { return function ( alerts ) { alerts . add ( { text : text , class : classname || "success" } , 3000 ) ; } ; } , redirect : function ( url ) { return function ( router ) { window . location = url || "/" ; } ; } , reload : function ( ) { return function ( router ) { router . reload ( ) ; } ; } , state : function ( keys ) { let updateQueryString = function ( key , value , url ) { var re = new RegExp ( "([?&])" + key + "=.*?(&|#|$)(.*)" , "gi" ) , hash ; if ( re . test ( url ) ) { if ( typeof value !== "undefined" && value !== null ) { return url . replace ( re , "$1" + key + "=" + value + "$2$3" ) ; } else { hash = url . split ( "#" ) ; url = hash [ 0 ] . replace ( re , "$1$3" ) . replace ( /(&|\?)$/ , "" ) ; if ( typeof hash [ 1 ] !== "undefined" && hash [ 1 ] !== null ) { url += "#" + hash [ 1 ] ; }
2019-09-13 22:47:48 +12:00
return url ; } } else { if ( typeof value !== "undefined" && value !== null ) { var separator = url . indexOf ( "?" ) !== - 1 ? "&" : "?" ; hash = url . split ( "#" ) ; url = hash [ 0 ] + separator + key + "=" + value ; if ( typeof hash [ 1 ] !== "undefined" && hash [ 1 ] !== null ) { url += "#" + hash [ 1 ] ; }
return url ; } else { return url ; } } } ; keys = keys . split ( "," ) . map ( element => element . trim ( ) ) ; return function ( serviceForm , router , window ) { let url = window . location . href ; keys . map ( node => { node = node . split ( "=" ) ; let key = node [ 0 ] || "" ; let name = node [ 1 ] || key ; let value = getValue ( key , "param" , serviceForm ) ; url = updateQueryString ( name , value ? value : null , url ) ; } ) ; if ( url !== window . location . href ) { window . history . pushState ( { } , "" , url ) ; router . reset ( ) ; } } ; } , trigger : function ( events ) { return function ( document ) { events = events . trim ( ) . split ( "," ) ; for ( let i = 0 ; i < events . length ; i ++ ) { if ( "" === events [ i ] ) { continue ; }
2020-04-17 15:15:13 +12:00
document . dispatchEvent ( new CustomEvent ( events [ i ] ) ) ; } } ; } , setId : function name ( params ) { } , default : function ( ) { let collection = container . get ( 'project-collection' ) ; let document = container . get ( 'project-document' ) ; if ( collection && document && collection . $id === document . $id ) { for ( const [ key , value ] of Object . entries ( document ) ) { delete document [ key ] ; }
2020-04-26 08:33:35 +12:00
if ( collection . rules ) { for ( let index = 0 ; index < collection . rules . length ; index ++ ) { const element = collection . rules [ index ] ; switch ( element . type ) { case 'text' : case 'email' : case 'url' : case 'ip' : document [ element . key ] = element . default || '' ; break ; case 'numeric' : document [ element . key ] = element . default || '0' ; break ; case 'boolean' : document [ element . key ] = element . default || false ; break ; case 'document' : document [ element . key ] = element . default || { '$id' : '' , '$collection' : '' , '$permissions' : { } } ; break ; default : document [ element . key ] = null ; break ; }
2020-04-17 15:15:13 +12:00
if ( element . array ) { document [ element . key ] = [ ] ; } } } } } } ; let getParams = function getParams ( func ) { 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 ; 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 ) ; }
2019-09-13 22:47:48 +12:00
while ( ( match = REGEX _PARAMETERS _VALUES . exec ( functionAsString ) ) ) { params . push ( match [ 1 ] ) ; }
return params ; } ; let getValue = function ( key , prefix , data ) { let result = null ; if ( ! key ) { return null ; }
let attrKey = prefix + key . charAt ( 0 ) . toUpperCase ( ) + key . slice ( 1 ) ; if ( element . dataset [ attrKey ] ) { result = expression . parse ( element . dataset [ attrKey ] ) ; if ( element . dataset [ attrKey + "CastTo" ] === "array" ) { result = result . split ( "," ) ; } }
2019-08-12 09:18:05 +12:00
if ( data [ key ] ) { result = data [ key ] ; }
2019-09-13 22:47:48 +12:00
if ( ! result ) { result = "" ; }
return result ; } ; let resolve = function ( target , prefix = "param" , data = { } ) { if ( ! target ) { return function ( ) { } ; }
2020-04-18 10:19:02 +12:00
let args = getParams ( target ) ; return target . apply ( target , args . map ( function ( value ) { let result = getValue ( value , prefix , data ) ; return result ; } ) ) ; } ; let exec = function ( event ) { let parsedSuccess = expression . parse ( success ) ; let parsedFailure = expression . parse ( failure ) ; let parsedAction = expression . parse ( action ) ; parsedSuccess = parsedSuccess && parsedSuccess != "" ? parsedSuccess . split ( "," ) . map ( element => element . trim ( ) ) : [ ] ; parsedFailure = parsedFailure && parsedFailure != "" ? parsedFailure . split ( "," ) . map ( element => element . trim ( ) ) : [ ] ; element . $lsSkip = true ; element . classList . add ( "load-service-start" ) ; if ( ! document . body . contains ( element ) ) { element = undefined ; return false ; }
2019-05-09 18:54:39 +12:00
if ( event ) { event . preventDefault ( ) ; }
2020-04-02 10:41:29 +13:00
if ( running ) { return false ; }
2020-05-21 09:12:23 +12:00
running = true ; element . style . backgroud = 'red' ; if ( confirm ) { if ( window . confirm ( confirm ) !== true ) { element . classList . add ( "load-service-end" ) ; element . $lsSkip = false ; running = false ; return false ; } }
2019-09-13 22:47:48 +12:00
if ( loading ) { loaderId = alerts . add ( { text : loading , class : "" } , 0 ) ; }
2020-04-18 10:19:02 +12:00
let method = container . path ( scope + "." + parsedAction ) ; if ( ! method ) { throw new Error ( 'Method "' + scope + "." + parsedAction + '" not found' ) ; }
2019-09-13 22:47:48 +12:00
let formData = "FORM" === element . tagName ? form . toJson ( element ) : { } ; let result = resolve ( method , "param" , formData ) ; if ( ! result ) { return ; }
2020-03-15 17:54:55 +13:00
if ( Promise . resolve ( result ) != result ) { result = new Promise ( ( resolve , reject ) => { resolve ( result ) ; } ) ; }
2019-05-09 18:54:39 +12:00
result . then ( function ( data ) { if ( loaderId !== null ) { alerts . remove ( loaderId ) ; }
if ( ! element ) { return ; }
2020-04-18 10:19:02 +12:00
running = false ; element . style . backgroud = 'transparent' ; element . classList . add ( "load-service-end" ) ; if ( service ) { container . set ( service . replace ( "." , "-" ) , data , true , true ) ; }
container . set ( "serviceData" , data , true , true ) ; container . set ( "serviceForm" , formData , true , true ) ; for ( let i = 0 ; i < parsedSuccess . length ; i ++ ) { container . resolve ( resolve ( callbacks [ parsedSuccess [ i ] ] , "successParam" +
parsedSuccess [ i ] . charAt ( 0 ) . toUpperCase ( ) +
parsedSuccess [ i ] . slice ( 1 ) , { } ) ) ; }
2019-09-13 22:47:48 +12:00
container . set ( "serviceData" , null , true , true ) ; container . set ( "serviceForm" , null , true , true ) ; element . $lsSkip = false ; view . render ( element ) ; } , function ( exception ) { if ( loaderId !== null ) { alerts . remove ( loaderId ) ; }
2019-08-07 22:46:51 +12:00
if ( ! element ) { return ; }
2020-04-18 10:19:02 +12:00
running = false ; element . style . backgroud = 'transparent' ; element . classList . add ( "load-service-end" ) ; for ( let i = 0 ; i < parsedFailure . length ; i ++ ) { container . resolve ( resolve ( callbacks [ parsedFailure [ i ] ] , "failureParam" +
parsedFailure [ i ] . charAt ( 0 ) . toUpperCase ( ) +
parsedFailure [ i ] . slice ( 1 ) , { } ) ) ; }
2019-09-13 22:47:48 +12:00
element . $lsSkip = false ; view . render ( element ) ; } ) ; } ; let events = event . trim ( ) . split ( "," ) ; for ( let y = 0 ; y < events . length ; y ++ ) { if ( "" === events [ y ] ) { continue ; }
2021-01-18 23:29:05 +13:00
switch ( events [ y ] . trim ( ) ) { case "load" : exec ( ) ; break ; case "none" : break ; case "click" : case "change" : case "keypress" : case "keydown" : case "keyup" : case "input" : case "submit" : element . addEventListener ( events [ y ] , exec ) ; break ; default : document . addEventListener ( events [ y ] , exec ) ; } } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-analytics" , controller : function ( element ) { let action = element . getAttribute ( "data-analytics-event" ) || "click" ; let doNotTrack = window . navigator . doNotTrack ; if ( doNotTrack == '1' ) { return ; }
element . addEventListener ( action , function ( ) { let category = element . getAttribute ( "data-analytics-category" ) || "undefined" ; let label = element . getAttribute ( "data-analytics-label" ) || "undefined" ; if ( ! ga ) { console . error ( "Google Analytics ga object is not available" ) ; }
ga ( "send" , { hitType : "event" , eventCategory : category , eventAction : action , eventLabel : label } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-analytics-activity" , controller : function ( window , element , appwrite , account ) { let action = element . getAttribute ( "data-analytics-event" ) || "click" ; let activity = element . getAttribute ( "data-analytics-label" ) || "None" ; let doNotTrack = window . navigator . doNotTrack ; if ( doNotTrack == '1' ) { return ; }
element . addEventListener ( action , function ( ) { let email = account ? . email || element . elements [ 'email' ] . value || '' ; appwrite . analytics . create ( email , 'console' , activity , window . location . href ) } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-analytics-pageview" , controller : function ( window , router , env ) { if ( ! ga ) { console . error ( "Google Analytics ga object is not available" ) ; }
let doNotTrack = window . navigator . doNotTrack ; if ( doNotTrack == '1' ) { return ; }
let project = router . params [ "project" ] || 'None' ; ga ( "set" , "page" , window . location . pathname ) ; ga ( "set" , "dimension1" , project ) ; ga ( 'set' , 'dimension2' , env . VERSION ) ; ga ( 'set' , 'dimension3' , env . SETUP ) ; ga ( "send" , "pageview" ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-clone" , controller : function ( element , document , view ) { var template = element . innerHTML . toString ( ) ; var label = element . dataset [ "label" ] || "Add" ; var icon = element . dataset [ "icon" ] || null ; var target = element . dataset [ "target" ] || null ; var first = parseInt ( element . dataset [ "first" ] || 1 ) ; var button = document . createElement ( "button" ) ; button . type = "button" ; button . innerText = " " + label + " " ; button . classList . add ( "margin-end" ) ; button . classList . add ( "margin-bottom-small" ) ; button . classList . add ( "reverse" ) ; if ( icon ) { var iconElement = document . createElement ( "i" ) ; iconElement . className = icon ; button . insertBefore ( iconElement , button . firstChild ) ; }
2019-05-09 18:54:39 +12:00
if ( target ) { target = document . getElementById ( target ) ; }
2019-09-13 22:47:48 +12:00
button . addEventListener ( "click" , function ( ) { var clone = document . createElement ( element . tagName ) ; if ( element . name ) { clone . name = element . name ; }
clone . innerHTML = template ; clone . className = element . className ; view . render ( clone ) ; if ( target ) { target . appendChild ( clone ) ; } else { button . parentNode . insertBefore ( clone , button ) ; }
2020-07-24 02:59:44 +12:00
clone . querySelector ( "input" ) . focus ( ) ; Array . prototype . slice . call ( clone . querySelectorAll ( "[data-remove]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { clone . parentNode . removeChild ( clone ) ; obj . scrollIntoView ( { behavior : "smooth" } ) ; } ) ; } ) ; Array . prototype . slice . call ( clone . querySelectorAll ( "[data-up]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { if ( clone . previousElementSibling ) { clone . parentNode . insertBefore ( clone , clone . previousElementSibling ) ; obj . scrollIntoView ( { behavior : "smooth" } ) ; } } ) ; } ) ; Array . prototype . slice . call ( clone . querySelectorAll ( "[data-down]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { if ( clone . nextElementSibling ) { clone . parentNode . insertBefore ( clone . nextElementSibling , clone ) ; obj . scrollIntoView ( { behavior : "smooth" } ) ; } } ) ; } ) ; } ) ; element . parentNode . insertBefore ( button , element . nextSibling ) ; element . parentNode . removeChild ( element ) ; if ( first ) { button . click ( ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-add" , repeat : false , controller : function ( element , view , container , document ) { for ( var i = 0 ; i < element . children . length ; i ++ ) { let button = document . createElement ( "button" ) ; let template = element . children [ i ] . cloneNode ( true ) ; let as = element . getAttribute ( 'data-ls-as' ) ; let counter = 0 ; button . type = "button" ; button . innerText = "Add" ; button . classList . add ( "reverse" ) ; button . classList . add ( "margin-end-small" ) ; button . addEventListener ( 'click' , function ( ) { container . addNamespace ( as , 'new-' + counter ++ ) ; console . log ( container . namespaces , container . get ( as ) , as ) ; container . set ( as , null , true , true ) ; let child = template . cloneNode ( true ) ; view . render ( child ) ; element . appendChild ( child ) ; element . style . visibility = 'visible' ; let inputs = child . querySelectorAll ( 'input,textarea' ) ; for ( let index = 0 ; index < inputs . length ; ++ index ) { if ( inputs [ index ] . type !== 'hidden' ) { inputs [ index ] . focus ( ) ; break ; } } } ) ; element . after ( button ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-chart" , controller : function ( element , container , date , document ) { let wrapper = document . createElement ( "div" ) ; let child = document . createElement ( "canvas" ) ; let sources = element . getAttribute ( 'data-forms-chart' ) ; let width = element . getAttribute ( 'data-width' ) || 500 ; let height = element . getAttribute ( 'data-height' ) || 175 ; let colors = ( element . getAttribute ( 'data-colors' ) || 'blue,green,orange,red' ) . split ( ',' ) ; let themes = { 'blue' : '#29b5d9' , 'green' : '#4eb55b' , 'orange' : '#fba233' , 'red' : '#dc3232' , } ; let range = { '24h' : 'H:i' , '7d' : 'd F Y' , '30d' : 'd F Y' , '90d' : 'd F Y' }
element . parentNode . insertBefore ( wrapper , element . nextSibling ) ; wrapper . classList . add ( 'content' ) ; child . width = width ; child . height = height ; sources = sources . split ( ',' ) ; wrapper . appendChild ( child ) ; let chart = null ; let check = function ( ) { let config = { type : "line" , data : { labels : [ ] , datasets : [ ] } , options : { responsive : true , title : { display : false , text : "Stats" } , legend : { display : false } , tooltips : { mode : "index" , intersect : false , caretPadding : 0 } , hover : { mode : "nearest" , intersect : true } , scales : { xAxes : [ { display : false } ] , yAxes : [ { display : false } ] } } } ; for ( let i = 0 ; i < sources . length ; i ++ ) { let label = sources [ i ] . substring ( 0 , sources [ i ] . indexOf ( '=' ) ) ; let path = sources [ i ] . substring ( sources [ i ] . indexOf ( '=' ) + 1 ) ; let data = container . path ( path ) ; let value = JSON . parse ( element . value ) ; config . data . labels [ i ] = label ; config . data . datasets [ i ] = { } ; config . data . datasets [ i ] . label = label ; config . data . datasets [ i ] . borderColor = themes [ colors [ i ] ] ; config . data . datasets [ i ] . backgroundColor = themes [ colors [ i ] ] + '36' ; config . data . datasets [ i ] . borderWidth = 2 ; config . data . datasets [ i ] . data = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ; config . data . datasets [ i ] . fill = true ; if ( ! data ) { return ; }
let dateFormat = ( value . range && range [ value . range ] ) ? range [ value . range ] : 'd F Y' ; for ( let x = 0 ; x < data . length ; x ++ ) { config . data . datasets [ i ] . data [ x ] = data [ x ] . value ; config . data . labels [ x ] = date . format ( dateFormat , data [ x ] . date ) ; } }
if ( chart ) { chart . destroy ( ) ; }
else { }
chart = new Chart ( child . getContext ( "2d" ) , config ) ; wrapper . dataset [ "canvas" ] = true ; }
check ( ) ; element . addEventListener ( 'change' , check ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-code" , controller : function ( element , alerts ) { let lang = element . dataset [ "formsCode" ] || "json" ; let div = document . createElement ( "div" ) ; let pre = document . createElement ( "pre" ) ; let code = document . createElement ( "code" ) ; let copy = document . createElement ( "i" ) ; div . appendChild ( pre ) ; div . appendChild ( copy ) ; pre . appendChild ( code ) ; element . parentNode . appendChild ( div ) ; div . className = "ide" ; pre . className = "line-numbers" ; code . className = "prism language-" + lang ; copy . className = "icon-docs copy" ; copy . textContent = "Click Here to Copy" ; copy . title = "Copy to Clipboard" ; copy . addEventListener ( "click" , function ( ) { window . getSelection ( ) . removeAllRanges ( ) ; let range = document . createRange ( ) ; range . selectNode ( code ) ; window . getSelection ( ) . addRange ( range ) ; try { document . execCommand ( "copy" ) ; alerts . add ( { text : "Copied to clipboard" , class : "" } , 3000 ) ; } catch ( err ) { alerts . add ( { text : "Failed to copy text " , class : "error" } , 3000 ) ; }
2020-07-13 08:58:33 +12:00
window . getSelection ( ) . removeAllRanges ( ) ; } ) ; let check = function ( ) { if ( ! element . value ) { return ; }
2019-09-13 22:47:48 +12:00
let value = null ; try { value = JSON . stringify ( JSON . parse ( element . value ) , null , 4 ) ; } catch ( error ) { value = element . value ; }
code . innerHTML = value ; Prism . highlightElement ( code ) ; div . scrollTop = 0 ; } ; element . addEventListener ( "change" , check ) ; check ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-color" , controller : function ( element ) { var preview = document . createElement ( "div" ) ; var picker = document . createElement ( "input" ) ; picker . type = "color" ; preview . className = "color-preview" ; preview . appendChild ( picker ) ; picker . addEventListener ( "change" , syncA ) ; picker . addEventListener ( "input" , syncA ) ; element . addEventListener ( "input" , update ) ; element . addEventListener ( "change" , update ) ; function update ( ) { if ( element . validity . valid ) { preview . style . background = element . value ; syncB ( ) ; } }
2019-05-09 18:54:39 +12:00
function syncA ( ) { element . value = picker . value ; update ( ) ; }
function syncB ( ) { picker . value = element . value ; }
2020-03-13 20:21:33 +13:00
element . parentNode . insertBefore ( preview , element ) ; update ( ) ; syncB ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-copy" , controller : function ( element , alerts , document , window ) { var button = window . document . createElement ( "i" ) ; button . type = "button" ; button . className = "icon-docs note copy" ; button . style . cursor = "pointer" ; element . parentNode . insertBefore ( button , element . nextSibling ) ; var copy = function ( event ) { let disabled = element . disabled ; element . disabled = false ; element . focus ( ) ; element . select ( ) ; document . execCommand ( "Copy" ) ; if ( document . selection ) { document . selection . empty ( ) ; } else if ( window . getSelection ) { window . getSelection ( ) . removeAllRanges ( ) ; }
2021-01-19 06:12:02 +13:00
element . disabled = disabled ; element . blur ( ) ; alerts . add ( { text : "Copied to clipboard" , class : "" } ) ; } ; button . addEventListener ( "click" , copy ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-document" , controller : function ( element , container , search ) { var formsDocument = ( element . dataset [ "formsDocument" ] || '' ) ; var searchButton = ( element . dataset [ "search" ] || 0 ) ; let path = container . scope ( searchButton ) ; element . addEventListener ( 'click' , function ( ) { search . selected = element . value ; search . path = path ; document . dispatchEvent ( new CustomEvent ( formsDocument , { bubbles : false , cancelable : true } ) ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-document-preview" , controller : function ( element , container , search ) { element . addEventListener ( 'change' , function ( ) { console . log ( element . value ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-forms-filter" , controller : function ( document , container , expression , element , form , di ) { let name = element . dataset [ "formsFilter" ] || "" ; let events = element . dataset [ "event" ] || "" ; let serialize = function ( obj , prefix ) { let str = [ ] , p ; for ( p in obj ) { if ( obj . hasOwnProperty ( p ) ) { let k = prefix ? prefix + "[" + p + "]" : p , v = obj [ p ] ; if ( v === "" ) { continue ; }
2019-09-13 22:47:48 +12:00
str . push ( v !== null && typeof v === "object" ? serialize ( v , k ) : encodeURIComponent ( k ) + "=" + encodeURIComponent ( v ) ) ; } }
return str . join ( "&" ) ; } ; let parse = function ( filter ) { if ( filter === "" ) { return null ; }
2019-05-09 18:54:39 +12:00
let operatorsMap = [ "!=" , ">=" , "<=" , "=" , ">" , "<" ] ; let operator = null ; for ( let key = 0 ; key < operatorsMap . length ; key ++ ) { if ( filter . indexOf ( operatorsMap [ key ] ) > - 1 ) { operator = operatorsMap [ key ] ; } }
if ( operator === null ) { throw new Error ( "Invalid operator" ) ; }
filter = filter . split ( operator ) ; if ( filter . length !== 2 ) { throw new Error ( "Invalid filter expression" ) ; }
2019-09-13 22:47:48 +12:00
return { key : filter [ 0 ] , value : filter [ 1 ] , operator : operator } ; } ; let flatten = function ( params ) { let list = { } ; for ( let key in params ) { if ( params . hasOwnProperty ( key ) ) { if ( key !== "filters" ) { list [ key ] = params [ key ] ; } else { for ( let i = 0 ; i < params [ key ] . length ; i ++ ) { let filter = parse ( params [ key ] [ i ] ) ; if ( null === filter ) { continue ; }
list [ "filters-" + filter . key ] = params [ key ] [ i ] ; } } } }
return list ; } ; let apply = function ( params ) { let cached = container . get ( name ) ; cached = cached ? cached . params : [ ] ; params = Object . assign ( cached , params ) ; container . set ( name , { name : name , params : params , query : serialize ( params ) , forward : parseInt ( params . offset ) + parseInt ( params . limit ) , backward : parseInt ( params . offset ) - parseInt ( params . limit ) , keys : flatten ( params ) } , true , name ) ; document . dispatchEvent ( new CustomEvent ( name + "-changed" , { bubbles : false , cancelable : true } ) ) ; } ; switch ( element . tagName ) { case "INPUT" : break ; case "TEXTAREA" : break ; case "BUTTON" : element . addEventListener ( "click" , function ( ) { apply ( JSON . parse ( expression . parse ( element . dataset [ "params" ] || "{}" ) ) ) ; } ) ; break ; case "FORM" : element . addEventListener ( "input" , function ( ) { apply ( form . toJson ( element ) ) ; } ) ; element . addEventListener ( "change" , function ( ) { apply ( form . toJson ( element ) ) ; } ) ; element . addEventListener ( "reset" , function ( ) { setTimeout ( function ( ) { apply ( form . toJson ( element ) ) ; } , 0 ) ; } ) ; events = events . trim ( ) . split ( "," ) ; for ( let y = 0 ; y < events . length ; y ++ ) { if ( events [ y ] === "init" ) { element . addEventListener ( "rendered" , function ( ) { apply ( form . toJson ( element ) ) ; } , { once : true } ) ; } else { }
element . setAttribute ( "data-event" , "none" ) ; }
2020-06-14 06:44:50 +12:00
break ; default : break ; } } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-forms-headers" , controller : function ( element ) { let key = document . createElement ( "input" ) ; let value = document . createElement ( "input" ) ; let wrap = document . createElement ( "div" ) ; let cell1 = document . createElement ( "div" ) ; let cell2 = document . createElement ( "div" ) ; key . type = "text" ; key . className = "margin-bottom-no" ; key . placeholder = "Key" ; value . type = "text" ; value . className = "margin-bottom-no" ; value . placeholder = "Value" ; wrap . className = "row thin margin-bottom-small" ; cell1 . className = "col span-6" ; cell2 . className = "col span-6" ; element . parentNode . insertBefore ( wrap , element ) ; cell1 . appendChild ( key ) ; cell2 . appendChild ( value ) ; wrap . appendChild ( cell1 ) ; wrap . appendChild ( cell2 ) ; key . addEventListener ( "input" , function ( ) { syncA ( ) ; } ) ; value . addEventListener ( "input" , function ( ) { syncA ( ) ; } ) ; element . addEventListener ( "change" , function ( ) { syncB ( ) ; } ) ; let syncA = function ( ) { element . value = key . value . toLowerCase ( ) + ":" + value . value . toLowerCase ( ) ; } ; let syncB = function ( ) { let split = element . value . toLowerCase ( ) . split ( ":" ) ; key . value = split [ 0 ] || "" ; value . value = split [ 1 ] || "" ; key . value = key . value . trim ( ) ; value . value = value . value . trim ( ) ; } ; syncB ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-forms-key-value" , controller : function ( element ) { let key = document . createElement ( "input" ) ; let value = document . createElement ( "input" ) ; let wrap = document . createElement ( "div" ) ; let cell1 = document . createElement ( "div" ) ; let cell2 = document . createElement ( "div" ) ; key . type = "text" ; key . className = "margin-bottom-no" ; key . placeholder = "Key" ; value . type = "text" ; value . className = "margin-bottom-no" ; value . placeholder = "Value" ; wrap . className = "row thin margin-bottom-small" ; cell1 . className = "col span-6" ; cell2 . className = "col span-6" ; element . parentNode . insertBefore ( wrap , element ) ; cell1 . appendChild ( key ) ; cell2 . appendChild ( value ) ; wrap . appendChild ( cell1 ) ; wrap . appendChild ( cell2 ) ; key . addEventListener ( "input" , function ( ) { syncA ( ) ; } ) ; value . addEventListener ( "input" , function ( ) { syncA ( ) ; } ) ; element . addEventListener ( "change" , function ( ) { syncB ( ) ; } ) ; let syncA = function ( ) { element . name = key . value ; element . value = value . value ; } ; let syncB = function ( ) { key . value = element . name || "" ; value . value = element . value || "" ; } ; syncB ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-move-down" , controller : function ( element ) { Array . prototype . slice . call ( element . querySelectorAll ( "[data-move-down]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { if ( element . nextElementSibling ) { console . log ( 'down' , element . offsetHeight ) ; element . parentNode . insertBefore ( element . nextElementSibling , element ) ; element . scrollIntoView ( { block : 'center' } ) ; } } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-move-up" , controller : function ( element ) { Array . prototype . slice . call ( element . querySelectorAll ( "[data-move-up]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { if ( element . previousElementSibling ) { console . log ( 'up' , element ) ; element . parentNode . insertBefore ( element , element . previousElementSibling ) ; element . scrollIntoView ( { block : 'center' } ) ; } } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-nav" , repeat : false , controller : function ( element , view , container , document ) { let titles = document . querySelectorAll ( '[data-forms-nav-anchor]' ) ; let links = element . querySelectorAll ( '[data-forms-nav-link]' ) ; let minLink = null ; let check = function ( ) { let minDistance = null ; let minElement = null ; for ( let i = 0 ; i < titles . length ; ++ i ) { let title = titles [ i ] ; let distance = title . getBoundingClientRect ( ) . top ; console . log ( i ) ; if ( ( minDistance === null || minDistance >= distance ) && ( distance >= 0 ) ) { if ( minLink ) { minLink . classList . remove ( 'selected' ) ; }
2020-05-30 00:02:53 +12:00
console . log ( 'old' , minLink ) ; minDistance = distance ; minElement = title ; minLink = links [ i ] ; minLink . classList . add ( 'selected' ) ; console . log ( 'new' , minLink ) ; } } } ; window . addEventListener ( 'scroll' , check ) ; check ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-oauth-apple" , controller : function ( element ) { let container = document . createElement ( "div" ) ; let row = document . createElement ( "div" ) ; let col1 = document . createElement ( "div" ) ; let col2 = document . createElement ( "div" ) ; let keyID = document . createElement ( "input" ) ; let keyLabel = document . createElement ( "label" ) ; let teamID = document . createElement ( "input" ) ; let teamLabel = document . createElement ( "label" ) ; let p8 = document . createElement ( "textarea" ) ; let p8Label = document . createElement ( "label" ) ; keyLabel . textContent = 'Key ID' ; teamLabel . textContent = 'Team ID' ; p8Label . textContent = 'P8 File' ; row . classList . add ( 'row' ) ; row . classList . add ( 'thin' ) ; container . appendChild ( row ) ; container . appendChild ( p8Label ) ; container . appendChild ( p8 ) ; row . appendChild ( col1 ) ; row . appendChild ( col2 ) ; col1 . classList . add ( 'col' ) ; col1 . classList . add ( 'span-6' ) ; col1 . appendChild ( keyLabel ) ; col1 . appendChild ( keyID ) ; col2 . classList . add ( 'col' ) ; col2 . classList . add ( 'span-6' ) ; col2 . appendChild ( teamLabel ) ; col2 . appendChild ( teamID ) ; keyID . type = 'text' ; keyID . placeholder = 'SHAB13ROFN' ; teamID . type = 'text' ; teamID . placeholder = 'ELA2CD3AED' ; p8 . accept = '.p8' ; p8 . classList . add ( 'margin-bottom-no' ) ; element . parentNode . insertBefore ( container , element . nextSibling ) ; element . addEventListener ( 'change' , sync ) ; keyID . addEventListener ( 'change' , update ) ; teamID . addEventListener ( 'change' , update ) ; p8 . addEventListener ( 'change' , update ) ; function update ( ) { let json = { } ; json . keyID = keyID . value ; json . teamID = teamID . value ; json . p8 = p8 . value ; element . value = JSON . stringify ( json ) ; }
2020-06-07 15:33:36 +12:00
function sync ( ) { if ( ! element . value ) { return ; }
2020-05-30 00:02:53 +12:00
let json = { } ; try { json = JSON . parse ( element . value ) ; } catch ( error ) { console . error ( 'Failed to parse secret key' ) ; }
teamID . value = json . teamID || '' ; keyID . value = json . keyID || '' ; p8 . value = json . p8 || '' ; }
sync ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-password-meter" , controller : function ( element , window ) { var calc = function ( password ) { var score = 0 ; if ( ! password ) return score ; var letters = new window . Object ( ) ; for ( var i = 0 ; i < password . length ; i ++ ) { letters [ password [ i ] ] = ( letters [ password [ i ] ] || 0 ) + 1 ; score += 5.0 / letters [ password [ i ] ] ; }
2019-09-13 22:47:48 +12:00
var variations = { digits : /\d/ . test ( password ) , lower : /[a-z]/ . test ( password ) , upper : /[A-Z]/ . test ( password ) , nonWords : /\W/ . test ( password ) } ; var variationCount = 0 ; for ( var check in variations ) { if ( variations . hasOwnProperty ( check ) ) { variationCount += variations [ check ] === true ? 1 : 0 ; } }
2020-05-01 04:35:22 +12:00
score += ( variationCount - 1 ) * 10 ; return parseInt ( score ) ; } ; var callback = function ( ) { var score = calc ( this . value ) ; if ( "" === this . value ) return ( meter . className = "password-meter" ) ; if ( score > 60 ) return ( meter . className = "password-meter strong" ) ; if ( score > 30 ) return ( meter . className = "password-meter medium" ) ; if ( score >= 0 ) return ( meter . className = "password-meter weak" ) ; } ; var meter = window . document . createElement ( "div" ) ; meter . className = "password-meter" ; element . parentNode . insertBefore ( meter , element . nextSibling ) ; element . addEventListener ( "change" , callback ) ; element . addEventListener ( "keypress" , callback ) ; element . addEventListener ( "keyup" , callback ) ; element . addEventListener ( "keydown" , callback ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-pell" , controller : function ( element , window , document , markdown , rtl ) { var div = document . createElement ( "div" ) ; element . className = "pell hide" ; div . className = "input pell" ; element . parentNode . insertBefore ( div , element ) ; element . tabIndex = - 1 ; var turndownService = new TurndownService ( ) ; turndownService . addRule ( "underline" , { filter : [ "u" ] , replacement : function ( content ) { return "__" + content + "__" ; } } ) ; var editor = window . pell . init ( { element : div , onChange : function onChange ( html ) { alignText ( ) ; element . value = turndownService . turndown ( html ) ; } , defaultParagraphSeparator : "p" , actions : [ { name : "bold" , icon : '<i class="icon-bold"></i>' } , { name : "underline" , icon : '<i class="icon-underline"></i>' } , { name : "italic" , icon : '<i class="icon-italic"></i>' } , { name : "olist" , icon : '<i class="icon-list-numbered"></i>' } , { name : "ulist" , icon : '<i class="icon-list-bullet"></i>' } , { name : "link" , icon : '<i class="icon-link"></i>' } ] } ) ; var clean = function ( e ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; var clipboardData = e . clipboardData || window . clipboardData ; console . log ( clipboardData . getData ( "Text" ) ) ; window . pell . exec ( "insertText" , clipboardData . getData ( "Text" ) ) ; return true ; } ; var alignText = function ( ) { let paragraphs = editor . content . querySelectorAll ( 'p,li' ) ; let last = '' ; for ( let paragraph of paragraphs ) { var content = paragraph . textContent ; if ( content . trim ( ) === '' ) { content = last . textContent ; }
if ( rtl . isRTL ( content ) ) { paragraph . style . direction = 'rtl' ; paragraph . style . textAlign = 'right' ; }
else { paragraph . style . direction = 'ltr' ; paragraph . style . textAlign = 'left' ; }
2021-01-11 01:49:18 +13:00
last = paragraph ; } } ; var santize = function ( e ) { clean ( e ) ; alignText ( e ) ; } ; element . addEventListener ( "change" , function ( ) { editor . content . innerHTML = markdown . render ( element . value ) ; alignText ( ) ; } ) ; editor . content . setAttribute ( "placeholder" , element . placeholder ) ; editor . content . innerHTML = markdown . render ( element . value ) ; editor . content . tabIndex = 0 ; alignText ( ) ; editor . content . onkeydown = function preventTab ( event ) { if ( event . which === 9 ) { event . preventDefault ( ) ; if ( document . activeElement ) { var focussable = Array . prototype . filter . call ( document . querySelectorAll ( 'a:not([disabled]), button:not([disabled]), select:not([disabled]), input[type=text]:not([disabled]), input[type=checkbox]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])' ) , function ( element ) { return ( element . offsetWidth > 0 || element . offsetHeight > 0 || element === document . activeElement ) ; } ) ; var index = focussable . indexOf ( document . activeElement ) ; if ( index > - 1 ) { if ( event . shiftKey ) { var prevElement = focussable [ index - 1 ] || focussable [ focussable . length - 1 ] ; prevElement . focus ( ) ; } else { var nextElement = focussable [ index + 1 ] || focussable [ 0 ] ; nextElement . focus ( ) ; } } } } } ; div . addEventListener ( "paste" , santize ) ; div . addEventListener ( "drop" , santize ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-remove" , controller : function ( element ) { Array . prototype . slice . call ( element . querySelectorAll ( "[data-remove]" ) ) . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { element . parentNode . removeChild ( element ) ; } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-run" , repeat : false , controller : function ( element , expression , container ) { let action = expression . parse ( element . dataset [ "formsRun" ] || '' ) ; element . addEventListener ( 'click' , function ( ) { return container . path ( action ) ( ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-select-all" , controller : function ( element ) { let select = document . createElement ( "button" ) ; let unselect = document . createElement ( "button" ) ; select . textContent = 'Select All' ; unselect . textContent = 'Unselect All' ; select . classList . add ( 'link' ) ; select . classList . add ( 'margin-top-tiny' ) ; select . classList . add ( 'margin-start-small' ) ; select . classList . add ( 'text-size-small' ) ; select . classList . add ( 'pull-end' ) ; unselect . classList . add ( 'link' ) ; unselect . classList . add ( 'margin-top-tiny' ) ; unselect . classList . add ( 'margin-start-small' ) ; unselect . classList . add ( 'text-size-small' ) ; unselect . classList . add ( 'pull-end' ) ; select . type = 'button' ; unselect . type = 'button' ; element . parentNode . insertBefore ( select , element ) ; element . parentNode . insertBefore ( unselect , element ) ; select . addEventListener ( 'click' , function ( ) { let checkboxes = element . querySelectorAll ( "input[type='checkbox']" ) ; for ( var i = 0 ; i < checkboxes . length ; i ++ ) { checkboxes [ i ] . checked = true ; checkboxes [ i ] . dispatchEvent ( new Event ( 'change' ) ) ; } } )
2021-01-19 07:37:13 +13:00
unselect . addEventListener ( 'click' , function ( ) { let checkboxes = element . querySelectorAll ( "input[type='checkbox']" ) ; for ( var i = 0 ; i < checkboxes . length ; i ++ ) { checkboxes [ i ] . checked = false ; checkboxes [ i ] . dispatchEvent ( new Event ( 'change' ) ) ; } } ) } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-show-secret" , controller : function ( element , document ) { let button = document . createElement ( 'span' ) ; button . className = "link pull-end text-size-small margin-top-negative icon-eye" ; button . innerHTML = ( element . type == 'password' ) ? 'Show Secret' : 'Hide Secret' ; button . style . visibility = ( element . value == '' ) ? 'hidden' : 'visible' ; element . insertAdjacentElement ( "beforebegin" , button ) ; button . addEventListener ( "click" , function ( event ) { switch ( element . type ) { case "password" : element . type = "text" ; button . innerHTML = 'Hide Secret' ; break ; case "text" : element . type = "password" ; button . innerHTML = 'Show Secret' ; break ; default : console . warn ( "data-forms-show-secret: element.type NOT text NOR password" ) ; } } ) ; let sync = function ( event ) { button . style . visibility = ( element . value == '' ) ? 'hidden' : 'visible' ; } ; element . addEventListener ( "keyup" , sync ) ; element . addEventListener ( "change" , sync ) ; } , } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-switch" , controller : function ( element ) { let input = window . document . createElement ( "input" ) ; input . type = "checkbox" ; input . className = "button switch" ; let syncA = function ( ) { let value = input . checked ? "true" : "false"
2020-05-26 17:10:13 +12:00
let old = element . value ; element . value = value ; if ( value !== old ) { element . dispatchEvent ( new Event ( 'change' ) ) ; } } ; let syncB = function ( ) { input . checked = ( element . value === "true" ) ; } ; input . addEventListener ( "input" , syncA ) ; input . addEventListener ( "change" , syncA ) ; element . addEventListener ( "input" , syncB ) ; element . addEventListener ( "change" , syncB ) ; syncA ( ) ; element . parentNode . insertBefore ( input , element ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-tags" , controller : function ( element ) { let array = [ ] ; let tags = window . document . createElement ( "div" ) ; let preview = window . document . createElement ( "ul" ) ; let add = window . document . createElement ( "input" ) ; let listen = function ( event ) { if ( ( event . key === "Enter" || event . key === " " || event . key === "Tab" ) && add . value . length > 0 ) { array . push ( add . value ) ; add . value = "" ; element . value = JSON . stringify ( array ) ; check ( ) ; if ( event . key !== "Tab" ) { event . preventDefault ( ) ; } }
2019-09-13 22:47:48 +12:00
if ( ( event . key === "Backspace" || event . key === "Delete" ) && add . value === "" ) { array . splice ( - 1 , 1 ) ; element . value = JSON . stringify ( array ) ; check ( ) ; }
2020-05-26 17:10:13 +12:00
return false ; } ; let check = function ( ) { try { array = JSON . parse ( element . value ) || [ ] ; } catch ( error ) { array = [ ] ; }
2019-08-22 22:44:55 +12:00
if ( ! Array . isArray ( array ) ) { array = [ ] ; }
2020-04-28 06:38:06 +12:00
preview . innerHTML = "" ; for ( let index = 0 ; index < array . length ; index ++ ) { let value = array [ index ] ; let tag = window . document . createElement ( "li" ) ; if ( ! value || value === ' ' ) { continue ; }
tag . className = "tag" ; tag . textContent = value ; tag . addEventListener ( "click" , function ( ) { array . splice ( index , 1 ) ; element . value = JSON . stringify ( array ) ; check ( ) ; } ) ; preview . appendChild ( tag ) ; }
2020-05-26 17:10:13 +12:00
if ( element . required && array . length === 0 ) { add . setCustomValidity ( "Please add permissions" ) ; } else { add . setCustomValidity ( "" ) ; } } ; tags . className = "tags" ; preview . className = "tags-list" ; add . type = "text" ; add . className = "add" ; add . placeholder = element . placeholder ; tags . addEventListener ( "click" , function ( ) { add . focus ( ) ; } ) ; add . addEventListener ( "keydown" , listen ) ; add . addEventListener ( "blur" , function ( event ) { if ( add . value !== '' ) { array . push ( add . value ) ; add . value = "" ; element . value = JSON . stringify ( array ) ; check ( ) ; } } ) ; tags . appendChild ( preview ) ; tags . appendChild ( add ) ; element . parentNode . insertBefore ( tags , element ) ; element . addEventListener ( "change" , check ) ; check ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-text-count" , controller : function ( element ) { var counter = document . createElement ( "div" ) ; counter . className = "counter" ; element . parentNode . insertBefore ( counter , element . nextSibling ) ; var count = function ( ) { if ( 0 <= element . maxLength ) { counter . innerText = ( element . maxLength - element . value . length ) . toString ( ) + " / " +
2020-05-01 04:35:22 +12:00
element . maxLength ; } else { var words = element . value !== "" ? element . value . trim ( ) . split ( " " ) . length : 0 ; counter . innerText = words + " words and " + element . value . length . toString ( ) + " chars" ; } } ; element . addEventListener ( "keyup" , count ) ; element . addEventListener ( "change" , count ) ; element . addEventListener ( "cut" , count ) ; element . addEventListener ( "paste" , count ) ; element . addEventListener ( "drop" , count ) ; count ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-text-direction" , controller : function ( element , rtl ) { var setDirection = function ( ) { var value = element . value [ 0 ] ? element . value : "" ; var direction = "ltr" ; var align = "left" ; if ( rtl . isRTL ( value ) ) { direction = "rtl" ; align = "right" ; }
2019-09-13 22:47:48 +12:00
element . style . direction = direction ; element . style . textAlign = align ; } ; element . addEventListener ( "keyup" , setDirection ) ; element . addEventListener ( "change" , setDirection ) ; element . addEventListener ( "cut" , setDirection ) ; element . addEventListener ( "paste" , setDirection ) ; element . addEventListener ( "drop" , setDirection ) ; setDirection ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-text-resize" , controller : function ( element , window ) { function resize ( ) { var scrollLeft = window . pageXOffset || ( window . document . documentElement || window . document . body . parentNode || window . document . body ) . scrollLeft ; var scrollTop = window . pageYOffset || ( window . document . documentElement || window . document . body . parentNode || window . document . body ) . scrollTop ; var offset = element . offsetHeight - element . clientHeight ; element . style . height = "auto" ; element . style . height = element . scrollHeight + offset + "px" ; window . scrollTo ( scrollLeft , scrollTop ) ; }
2020-06-13 23:13:53 +12:00
element . addEventListener ( "keyup" , resize ) ; element . addEventListener ( "change" , resize ) ; element . addEventListener ( "cut" , resize ) ; element . addEventListener ( "paste" , resize ) ; element . addEventListener ( "drop" , resize ) ; window . addEventListener ( "resize" , resize ) ; resize ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-upload" , controller : function ( element , container , alerts , expression , env , search ) { var scope = element . dataset [ "scope" ] ; var project = expression . parse ( element . dataset [ "project" ] || "console" ) ; var labelButton = element . dataset [ "labelButton" ] || "Upload" ; var labelLoading = element . dataset [ "labelLoading" ] || "Uploading..." ; var previewWidth = element . dataset [ "previewWidth" ] || 200 ; var previewHeight = element . dataset [ "previewHeight" ] || 200 ; var previewAlt = element . dataset [ "previewAlt" ] || 200 ; var accept = element . dataset [ "accept" ] || "" ; var searchButton = ( element . dataset [ "search" ] || 0 ) ; var required = element . dataset [ "required" ] || false ; var className = element . dataset [ "class" ] || "upload" ; var max = parseInt ( element . dataset [ "max" ] || 4 ) ; var sdk = scope === "sdk" ? container . get ( "sdk" ) : container . get ( "console" ) ; var output = element . value || null ; var wrapper = document . createElement ( "div" ) ; var input = document . createElement ( "input" ) ; var upload = document . createElement ( "div" ) ; var preview = document . createElement ( "ul" ) ; var progress = document . createElement ( "div" ) ; var count = document . createElement ( "div" ) ; wrapper . className = className ; input . type = "file" ; input . accept = accept ; input . required = required ; input . tabIndex = - 1 ; count . className = "count" ; upload . className = "button reverse margin-bottom-small" ; upload . innerHTML = '<i class="icon icon-upload"></i> ' + labelButton ; upload . tabIndex = 0 ; preview . className = "preview" ; progress . className = "progress" ; progress . style . width = "0%" ; progress . style . display = "none" ; var onComplete = function ( message ) { alerts . remove ( message ) ; input . disabled = false ; upload . classList . remove ( "disabled" ) ; progress . style . width = "0%" ; progress . style . display = "none" ; } ; var render = function ( result ) { preview . innerHTML = "" ; count . innerHTML = "0 / " + max ; if ( ! result ) { return ; }
2020-02-01 00:57:25 +13:00
var file = document . createElement ( "li" ) ; var image = document . createElement ( "img" ) ; image . src = image . src = env . API + "/storage/files/" +
result + "/preview?width=" +
2019-09-13 22:47:48 +12:00
previewWidth + "&height=" +
2020-06-21 02:01:53 +12:00
previewHeight + "&project=" + project + "&mode=admin" ; image . alt = previewAlt ; file . className = "file avatar" ; file . tabIndex = 0 ; file . appendChild ( image ) ; preview . appendChild ( file ) ; var remove = ( function ( result ) { return function ( event ) { render ( result . $id ) ; element . value = '' ; } ; } ) ( result ) ; file . addEventListener ( "click" , remove ) ; file . addEventListener ( "keypress" , remove ) ; element . value = result ; } ; input . addEventListener ( "change" , function ( ) { var message = alerts . add ( { text : labelLoading , class : "" } , 0 ) ; var files = input . files ; var read = JSON . parse ( expression . parse ( element . dataset [ "read" ] || "[]" ) ) ; var write = JSON . parse ( expression . parse ( element . dataset [ "write" ] || "[]" ) ) ; sdk . storage . createFile ( files [ 0 ] , read , write , 1 ) . then ( function ( response ) { onComplete ( message ) ; render ( response . $id ) ; } , function ( error ) { alerts . add ( { text : "An error occurred!" , class : "" } , 3000 ) ; onComplete ( message ) ; } ) ; input . disabled = true ; } ) ; element . addEventListener ( "change" , function ( ) { if ( ! element . value ) { return ; }
2020-07-25 18:26:25 +12:00
render ( element . value ) ; wrapper . scrollIntoView ( ) ; } ) ; upload . addEventListener ( "keypress" , function ( ) { input . click ( ) ; } ) ; element . parentNode . insertBefore ( wrapper , element ) ; wrapper . appendChild ( preview ) ; wrapper . appendChild ( progress ) ; wrapper . appendChild ( upload ) ; upload . appendChild ( input ) ; render ( output ) ; if ( searchButton ) { let searchOpen = document . createElement ( "button" ) ; searchOpen . type = 'button' ; searchOpen . innerHTML = '<i class="icon icon-search"></i> Search' ; searchOpen . classList . add ( 'reverse' ) ; let path = container . scope ( searchButton ) ; searchOpen . addEventListener ( 'click' , function ( ) { search . selected = element . value ; search . path = path ; document . dispatchEvent ( new CustomEvent ( "open-file-serach" , { bubbles : false , cancelable : true } ) ) ; } ) ; wrapper . appendChild ( searchOpen ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-cookies" , controller : function ( element , alerts , cookie , env ) { if ( ! cookie . get ( "cookie-alert" ) ) { let text = element . dataset [ "cookies" ] || "" ; alerts . add ( { text : text , class : "cookie-alert" , link : env . HOME + "/policy/cookies" , label : 'Learn More' , callback : function ( ) { cookie . set ( "cookie-alert" , "true" , 365 * 10 ) ; } } , 0 ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-page-title" , repeat : true , controller : function ( element , document , expression ) { document . title = expression . parse ( element . getAttribute ( "data-page-title" ) ) || document . title ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . view . add ( { selector : 'data-general-scroll-to' , repeat : false , controller : function ( element , window ) { let button = window . document . createElement ( 'button' ) ; button . className = 'scroll-to icon-up-dir' ; button . alt = 'Back To Top' ; button . title = 'Back To Top' ; button . addEventListener ( 'click' , function ( ) { element . scrollIntoView ( true , { behavior : 'smooth' } ) ; button . blur ( ) ; } , false ) ; element . appendChild ( button ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . view . add ( { selector : 'data-general-scroll-direction' , repeat : false , controller : function ( element , window ) { let position = 0 ; let check = function ( ) { let direction = window . document . documentElement . scrollTop ; if ( direction > position ) { element . classList . remove ( 'scroll-to-top' )
2020-01-27 20:34:08 +13:00
element . classList . add ( 'scroll-to-bottom' ) }
else { element . classList . remove ( 'scroll-to-bottom' )
element . classList . add ( 'scroll-to-top' ) }
2020-01-27 21:21:34 +13:00
position = direction ; let current = Math . ceil ( direction / window . innerHeight ) ; element . setAttribute ( 'data-views-total' , Math . ceil ( element . scrollHeight / window . innerHeight ) ) ; element . setAttribute ( 'data-views-current' , current ) ; if ( element . scrollHeight <= ( direction + element . offsetHeight + 300 ) && direction > 0 ) { element . classList . add ( 'scroll-end' ) }
2020-02-19 11:13:09 +13:00
else { element . classList . remove ( 'scroll-end' ) } } ; window . addEventListener ( 'scroll' , check , false ) ; window . addEventListener ( 'resize' , check , false ) ; check ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-setup" , controller : function ( element , console , form , alerts , router ) { element . addEventListener ( "submit" , function ( event ) { event . preventDefault ( ) ; let loaderId = alerts . add ( { text : 'Creating new project...' , class : "" } , 0 ) ; let formData = form . toJson ( element ) ; formData [ "name" ] = formData [ "name" ] || ( element . dataset [ "defaultName" ] || "" ) ; console . teams . create ( formData [ "name" ] || "" ) . then ( function ( data ) { let team = data [ "$id" ] ; formData = JSON . parse ( JSON . stringify ( formData ) . replace ( new RegExp ( "{{teamId}}" , "g" ) , team ) ) ; console . projects . create ( formData [ "name" ] , team ) . then ( function ( project ) { alerts . remove ( loaderId ) ; window . location . href = "/console/home?project=" + project [ "$id" ] ; } , function ( ) { throw new Error ( "Failed to setup project" ) ; } ) ; } , function ( ) { throw new Error ( "Setup failed creating project team" ) ; } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-switch" , controller : function ( element , router , document ) { let check = function ( c ) { if ( ! element . value ) { return ; }
2019-08-22 07:22:48 +12:00
if ( element . value === router . params . project ) { return ; }
2020-02-12 00:55:57 +13:00
return router . change ( "/console/home?project=" + element . value ) ; } ; element . addEventListener ( "change" , function ( ) { check ( ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-general-theme" , controller : function ( element , router , document ) { let toggle = function ( c ) { if ( document . body . classList . contains ( 'theme-light' ) ) { document . body . classList . remove ( 'theme-light' ) ; document . body . classList . add ( 'theme-dark' ) ; window . localStorage . setItem ( 'user-theme' , 'theme-dark' ) }
2020-07-25 18:33:48 +12:00
else { document . body . classList . remove ( 'theme-dark' ) ; document . body . classList . add ( 'theme-light' ) ; window . localStorage . setItem ( 'user-theme' , 'theme-light' ) } } ; element . addEventListener ( "click" , function ( ) { toggle ( ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-version" , controller : function ( alerts , env , cookie ) { let cookieName = "version-update-" + env . VERSION . replace ( /\./g , "_" ) ; if ( ! cookie . get ( cookieName ) ) { var xhr = new XMLHttpRequest ( ) ; xhr . open ( 'GET' , '/console/version' , true ) ; xhr . onload = function ( ) { if ( this . readyState == 4 && this . status == 200 ) { let data = JSON . parse ( this . responseText ) ; let text = 'Appwrite version ' + data . version + ' is avaliable, check the' ; if ( isNewerVersion ( env . VERSION , data . version ) ) { alerts . add ( { text : text , class : "success" , link : "https://github.com/appwrite/appwrite/releases" , label : 'release notes' , callback : function ( ) { cookie . set ( cookieName , "true" , 365 * 10 ) ; } } , 0 ) ; } } } ; xhr . send ( null ) ; function isNewerVersion ( oldVer , newVer ) { const oldParts = oldVer . split ( '.' )
2020-07-25 18:26:25 +12:00
const newParts = newVer . split ( '.' )
for ( var i = 0 ; i < newParts . length ; i ++ ) { const a = parseInt ( newParts [ i ] ) || 0
const b = parseInt ( oldParts [ i ] ) || 0
if ( a > b ) return true
if ( a < b ) return false }
return false } } } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-paging-back" , controller : function ( element , container , expression , env ) { let paths = [ ] ; let limit = env . PAGING _LIMIT ; let check = function ( ) { let offset = parseInt ( expression . parse ( element . dataset [ "offset" ] ) || "0" ) ; paths = paths . concat ( expression . getPaths ( ) ) ; if ( offset - limit < 0 ) { element . disabled = true ; } else { element . disabled = false ; element . value = offset - limit ; } } ; 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 ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-paging-next" , controller : function ( element , container , expression , env ) { let paths = [ ] ; let limit = env . PAGING _LIMIT ; let check = function ( ) { let offset = parseInt ( expression . parse ( element . dataset [ "offset" ] ) || "0" ) ; paths = paths . concat ( expression . getPaths ( ) ) ; let sum = parseInt ( expression . parse ( element . dataset [ "sum" ] ) || "0" ) ; paths = paths . concat ( expression . getPaths ( ) ) ; if ( offset + limit >= sum ) { element . disabled = true ; } else { element . disabled = false ; element . value = offset + limit ; } } ; 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 ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ui-highlight" , controller : function ( element , expression , document ) { let check = function ( ) { let links = element . getElementsByTagName ( "a" ) ; let selected = null ; let list = [ ] ; for ( let i = 0 ; i < links . length ; i ++ ) { list . push ( links [ i ] ) ; }
2020-06-06 20:40:33 +12:00
list . sort ( function ( a , b ) { return a . pathname . length - b . pathname . length ; } ) ; if ( selected && list [ selected ] . dataset [ "selected" ] ) { let parent = element . querySelector ( "a[href='" + list [ selected ] . dataset [ "selected" ] + "']" ) ; if ( parent ) { parent . classList . remove ( "selected" ) ; } }
for ( let i = 0 ; i < list . length ; i ++ ) { let path = list [ i ] . pathname ; if ( path === window . location . pathname . substring ( 0 , path . length ) ) { list [ i ] . classList . add ( "selected" ) ; if ( selected !== null ) { list [ selected ] . classList . remove ( "selected" ) ; }
selected = i ; } else { list [ i ] . classList . remove ( "selected" ) ; } }
if ( selected && list [ selected ] . dataset [ "selected" ] ) { let parent = element . querySelector ( "a[href='" + list [ selected ] . dataset [ "selected" ] + "']" ) ; if ( parent ) { parent . classList . add ( "selected" ) ; } } } ; document . addEventListener ( "state-changed" , check ) ; check ( ) ; } , } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ls-ui-loader" , controller : function ( element , document ) { document . addEventListener ( 'account.get' , function ( ) { element . classList . add ( 'loaded' ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ui-modal" , controller : function ( document , element , expression ) { let name = expression . parse ( element . dataset [ "name" ] || '' ) ; let buttonText = expression . parse ( element . dataset [ "buttonText" ] || "" ) ; let buttonElement = expression . parse ( element . dataset [ "buttonElement" ] || "button" ) ; let buttonClass = expression . parse ( element . dataset [ "buttonClass" ] || "button-class" ) ; let buttonIcon = expression . parse ( element . dataset [ "buttonIcon" ] || '' ) ; let buttonEvent = expression . parse ( element . dataset [ "buttonEvent" ] || "" ) ; let buttonHide = expression . parse ( element . dataset [ "buttonHide" ] || "" ) ; let buttonAlias = expression . parse ( element . dataset [ "buttonAlias" ] || "" ) ; let buttonElements = ! buttonAlias ? [ document . createElement ( buttonElement ) ] : document . querySelectorAll ( buttonAlias ) ; let openEvent = expression . parse ( element . dataset [ "openEvent" ] || '' ) ; let closeEvent = expression . parse ( element . dataset [ "closeEvent" ] || 'submit' ) ; let background = document . getElementById ( "modal-bg" ) ; if ( ! background ) { background = document . createElement ( "div" ) ; background . id = "modal-bg" ; background . className = "modal-bg" ; document . body . appendChild ( background ) ; background . addEventListener ( "click" , function ( ) { document . dispatchEvent ( new CustomEvent ( "modal-close" , { bubbles : false , cancelable : true } ) ) ; } ) ; }
2020-02-28 20:37:09 +13:00
if ( ! buttonAlias ) { buttonElements . forEach ( button => { button . innerText = buttonText ; button . className = buttonClass ; button . type = buttonElement ; if ( buttonIcon ) { let iconElement = document . createElement ( "i" ) ; iconElement . className = buttonIcon ; button . insertBefore ( iconElement , button . firstChild ) ; } } ) ; }
2019-09-13 22:47:48 +12:00
if ( buttonEvent ) { buttonElements . forEach ( button => { button . addEventListener ( "click" , function ( ) { document . dispatchEvent ( new CustomEvent ( buttonEvent , { bubbles : false , cancelable : true } ) ) ; } ) ; } ) ; }
2020-04-21 06:47:26 +12:00
element . classList . add ( "modal" ) ; if ( ! buttonAlias && ! buttonHide ) { buttonElements . forEach ( button => { element . parentNode . insertBefore ( button , element ) ; } ) ; }
2020-04-21 20:13:45 +12:00
let open = function ( ) { document . documentElement . classList . add ( "modal-open" ) ; document . dispatchEvent ( new CustomEvent ( "modal-open" , { bubbles : false , cancelable : true } ) ) ; element . classList . add ( "open" ) ; element . classList . remove ( "close" ) ; let form = element . querySelector ( 'form' ) ; let elements = ( form && form . elements ) ? [ ... form . elements ] : [ ] ; for ( let index = 0 ; index < elements . length ; index ++ ) { let element = elements [ index ] ; if ( element . type !== 'hidden' && element . type !== 'button' && element . type !== 'submit' ) { element . focus ( ) ; break ; } } } ; let close = function ( event ) { document . documentElement . classList . remove ( "modal-open" ) ; element . classList . add ( "close" ) ; element . classList . remove ( "open" ) ; } ; if ( name ) { document . querySelectorAll ( "[data-ui-modal-ref='" + name + "']" ) . forEach ( function ( elem ) { elem . addEventListener ( "click" , open ) ; } ) ; }
2019-05-09 18:54:39 +12:00
if ( openEvent ) { document . addEventListener ( openEvent , open ) ; }
2019-09-13 22:47:48 +12:00
buttonElements . forEach ( button => { button . addEventListener ( "click" , open ) ; } ) ; document . addEventListener ( "keydown" , function ( event ) { if ( event . which === 27 ) { close ( ) ; } } ) ; element . addEventListener ( "blur" , close ) ; let closeButtons = element . querySelectorAll ( "[data-ui-modal-close]" ) ; for ( let i = 0 ; i < closeButtons . length ; i ++ ) { closeButtons [ i ] . addEventListener ( "click" , close ) ; }
2020-06-13 23:13:53 +12:00
document . addEventListener ( "modal-close" , close ) ; element . addEventListener ( closeEvent , close ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ls-ui-open" , controller : function ( element , window ) { let def = element . classList . contains ( "open" ) ? "open" : "close" ; let buttonClass = element . dataset [ "buttonClass" ] || "ls-ui-open" ; let buttonText = element . dataset [ "buttonText" ] || "" ; let buttonIcon = element . dataset [ "buttonIcon" ] || "" ; let buttonAria = element . dataset [ "buttonAria" ] || "Open" ; let buttonSelector = element . dataset [ "buttonSelector" ] || "" ; let hover = element . hasAttribute ( "data-hover" ) ; let blur = element . hasAttribute ( "data-blur" ) ; let button = window . document . createElement ( "button" ) ; let isTouch = function ( ) { return ( "ontouchstart" in window || navigator . maxTouchPoints ) ; } ; button . innerText = buttonText ; button . className = buttonClass ; button . type = "button" ; if ( buttonIcon ) { let icon = window . document . createElement ( "i" ) ; icon . className = buttonIcon ; button . insertBefore ( icon , button . firstChild ) ; }
if ( buttonAria ) { button . setAttribute ( 'aria-label' , buttonAria ) ; }
2019-09-13 22:47:48 +12:00
if ( def === "close" ) { element . classList . add ( "close" ) ; element . classList . remove ( "open" ) ; } else { element . classList . add ( "open" ) ; element . classList . remove ( "close" ) ; }
button . addEventListener ( "click" , function ( ) { element . classList . toggle ( "open" ) ; element . classList . toggle ( "close" ) ; } ) ; if ( hover && ! isTouch ( ) ) { element . addEventListener ( "mouseover" , function ( ) { element . classList . add ( "open" ) ; element . classList . remove ( "close" ) ; } ) ; element . addEventListener ( "mouseout" , function ( ) { element . classList . add ( "close" ) ; element . classList . remove ( "open" ) ; } ) ; }
2020-05-01 18:49:23 +12:00
let close = function ( ) { element . classList . add ( "close" ) ; element . classList . remove ( "open" ) ; } ; let closeDelay = function ( ) { window . setTimeout ( function ( ) { close ( ) ; } , 400 ) ; } ; let findParent = function ( tagName , el ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; }
2019-09-13 22:47:48 +12:00
while ( ( el = el . parentNode ) ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; } }
return null ; } ; if ( blur ) { button . addEventListener ( "blur" , closeDelay ) ; }
if ( buttonSelector ) { let buttonElements = element . querySelectorAll ( buttonSelector ) ; buttonElements . forEach ( node => { node . addEventListener ( "click" , function ( ) { element . classList . toggle ( "open" ) ; element . classList . toggle ( "close" ) ; } ) ; if ( blur ) { node . addEventListener ( "blur" , closeDelay ) ; } } ) ; }
2020-04-04 08:26:52 +13:00
element . addEventListener ( 'click' , function ( event ) { let targetA = findParent ( 'a' , event . target ) ; let targetB = findParent ( 'button' , event . target ) ; if ( ! targetA && ! targetB ) { return false ; }
if ( targetA && ! targetA . href ) { return false ; }
if ( targetB && ! targetB . classList . contains ( 'link' ) ) { return false ; }
2020-07-16 08:32:02 +12:00
closeDelay ( ) ; } ) ; element . insertBefore ( button , element . firstChild ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ui-phases" , controller : function ( element , window , document , expression , router ) { var tabs = document . createElement ( "ul" ) ; var container = document . createElement ( "div" ) ; var titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h1" ) ) ; var next = Array . prototype . slice . call ( element . querySelectorAll ( "[data-next]" ) ) ; var previous = Array . prototype . slice . call ( element . querySelectorAll ( "[data-previous]" ) ) ; var position = 0 ; var init = false ; if ( titles . length === 0 ) { titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h2" ) ) ; }
if ( titles . length === 0 ) { titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h3" ) ) ; }
if ( titles . length === 0 ) { titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h4" ) ) ; }
if ( titles . length === 0 ) { titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h5" ) ) ; }
if ( titles . length === 0 ) { titles = Array . prototype . slice . call ( element . querySelectorAll ( "li > h6" ) ) ; }
2020-07-15 18:13:18 +12:00
for ( var i = 0 ; i < element . children . length ; i ++ ) { var tabState = expression . parse ( element . children [ i ] . dataset [ "state" ] || "" ) ; if ( tabState && tabState === ( window . location . pathname + window . location . search ) . substring ( 0 , tabState . length ) ) { position = i ; } }
2019-09-13 22:47:48 +12:00
var setTab = function ( index ) { var tabState = expression . parse ( element . children [ index ] . dataset [ "state" ] || "" ) ; var url = "" ; if ( tabState !== "" && tabState !== window . location . pathname + window . location . search ) { var parser = document . createElement ( "a" ) ; parser . href = tabState ; url = ! init ? parser . pathname + window . location . search : tabState ; if ( position != index ) { window . history . pushState ( { } , "" , url ) ; router . reset ( ) ; } }
2020-04-28 06:38:06 +12:00
element . children [ position ] . classList . remove ( "selected" ) ; element . children [ index ] . classList . add ( "selected" ) ; tabs . children [ position ] . classList . remove ( "selected" ) ; tabs . children [ index ] . classList . add ( "selected" ) ; position = index ; document . dispatchEvent ( new CustomEvent ( "tab-changed" ) ) ; init = true ; } ; tabs . classList . add ( "tabs" ) ; container . classList . add ( "container" ) ; container . classList . add ( "close" ) ; container . dataset [ "lsUiOpen" ] = "" ; container . dataset [ "buttonClass" ] = "icon icon-down-dir" ; titles . map ( function ( obj , i ) { var title = document . createElement ( "li" ) ; title . innerHTML = obj . innerHTML ; title . className = obj . className ; title . tabIndex = 0 ; tabs . appendChild ( title ) ; title . addEventListener ( "click" , function ( ) { setTab ( i ) ; } ) ; title . addEventListener ( "keyup" , function ( ) { if ( event . which === 13 ) { setTab ( i ) ; } } ) ; } ) ; next . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { setTab ( position + 1 ) ; } ) ; } ) ; previous . map ( function ( obj ) { obj . addEventListener ( "click" , function ( ) { setTab ( position - 1 ) ; } ) ; } ) ; setTab ( position ) ; container . appendChild ( tabs ) ; element . parentNode . insertBefore ( container , element ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ls-ui-trigger" , controller : function ( element , document , expression ) { let trigger = expression . parse ( element . dataset [ "lsUiTrigger" ] || '' ) . trim ( ) . split ( ',' ) ; let event = expression . parse ( element . dataset [ "event" ] || 'click' ) ; let debug = element . getAttribute ( 'data-debug' ) || false ; for ( let index = 0 ; index < trigger . length ; index ++ ) { let name = trigger [ index ] ; element . addEventListener ( event , function ( ) { if ( debug ) { console . log ( 'Debug: event triggered: ' + name ) ; }
document . dispatchEvent ( new CustomEvent ( name ) ) ; } ) ; } } } ) ; } ) ( window ) ;