2019-05-09 18:54:39 +12:00
2019-05-12 23:20:51 +12:00
window . ls = window . ls || { } ; window . ls . container = function ( ) { let stock = { } ; let listeners = { } ; 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 ; }
2019-06-08 09:39:40 +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 ; }
2019-08-06 16:19:16 +12:00
let args = getParams ( target ) ; return target . apply ( target , args . map ( function ( value ) { return self . get ( value . trim ( ) ) ; } ) ) ; } ; let path = function ( path , value , as , prefix ) { as = ( as ) ? as : container . get ( '$as' ) ; prefix = ( prefix ) ? prefix : container . get ( '$prefix' ) ; path = ( ( path . indexOf ( '.' ) > - 1 ) ? path . replace ( as + '.' , prefix + '.' ) : path . replace ( as , prefix ) ) . split ( '.' ) ; let name = path . shift ( ) ; let object = this . 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 ( ) ] ; }
2019-08-21 18:55:51 +12:00
let shift = path . shift ( ) ; if ( value !== null && value !== undefined && object && shift && object [ shift ] ) { object [ shift ] = value ; return true ; }
2019-05-12 23:20:51 +12:00
if ( ! object ) { return null ; }
2019-08-21 18:55:51 +12:00
if ( ! shift ) { result = object ; }
2019-06-08 09:39:40 +12:00
else { return object [ shift ] ; }
2019-08-06 16:19:16 +12:00
return result ; } ; let bind = function ( element , path , callback , as , prefix ) { as = ( as ) ? as : container . get ( '$as' ) ; prefix = ( prefix ) ? prefix : container . get ( '$prefix' ) ; let event = ( ( path . indexOf ( '.' ) > - 1 ) ? path . replace ( as + '.' , prefix + '.' ) : path . replace ( as , prefix ) ) + '.changed' ; let service = event . split ( '.' ) . slice ( 0 , 1 ) . pop ( ) ; listeners [ service ] = listeners [ service ] || { } ; listeners [ service ] [ event ] = true ; let printer = ( ) => { if ( ! document . body . contains ( element ) ) { element = null ; document . removeEventListener ( event , printer , false ) ; return false ; }
callback ( ) ; } ; document . addEventListener ( event , printer ) ; } ; let container = { set : set , get : get , resolve : resolve , path : path , bind : bind , stock : stock , listeners : listeners , } ; 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 ) ; }
return new Promise ( function ( resolve , reject ) { let xmlhttp = new XMLHttpRequest ( ) ; xmlhttp . open ( method , url , true ) ; xmlhttp . setRequestHeader ( 'Ajax' , '1' ) ; for ( i = 0 ; i < globalHeaders . length ; i ++ ) { xmlhttp . setRequestHeader ( globalHeaders [ i ] . key , globalHeaders [ i ] . value ) ; }
for ( let key in headers ) { if ( headers . hasOwnProperty ( key ) ) { xmlhttp . setRequestHeader ( key , headers [ key ] ) ; } }
2019-06-08 09:39:40 +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 ; }
2019-08-14 09:07:41 +12: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 ) { 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 -- ; }
continue ; }
node . classList . remove ( 'load-end' ) ; node . classList . add ( 'load-start' ) ; node . $lsSkip = true ; http . get ( comp . template ) . then ( function ( node , comp ) { return function ( data ) { node . $lsSkip = false ; node . innerHTML = data ; node . classList . remove ( 'load-start' ) ; node . classList . add ( 'load-end' ) ; ( function ( comp , node , container ) { execute ( comp , node , container ) ; } ) ( comp , node , container ) ; parse ( node , true ) ; } } ( node , comp ) , function ( error ) { throw new Error ( 'Failed to load comp template: ' + error . message ) ; } ) ; } } }
if ( true === node . $lsSkip ) { return ; }
let list = ( node ) ? node . childNodes : [ ] ; if ( node . $lsSkip === true ) { list = [ ] ; }
for ( let i = 0 ; i < list . length ; i ++ ) { let child = list [ i ] ; parse ( child ) ; } } ; return { stock : stock , add : function ( object ) { if ( typeof object !== 'object' ) { throw new Error ( 'object must be of type object' ) ; }
let defaults = { 'selector' : '' , 'controller' : function ( ) { } , 'template' : '' , 'repeat' : false , 'protected' : false } ; for ( let prop in defaults ) { if ( ! defaults . hasOwnProperty ( prop ) ) { continue ; }
if ( prop in object ) { continue ; }
object [ prop ] = defaults [ prop ] ; }
if ( ! object . selector ) { throw new Error ( 'View component is missing a selector attribute' ) ; }
2019-08-13 02:19:54 +12:00
stock [ object . selector ] = object ; return this ; } , render : function ( element ) { parse ( element ) ; 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 . href . indexOf ( '?' ) ; if ( pos === - 1 ) return [ ] ; query = location . href . substr ( pos + 1 ) ; } else { query = location . search . substr ( 1 ) ; }
let result = { } ; query . split ( '&' ) . forEach ( function ( part ) { if ( ! part ) { return ; }
part = part . split ( '+' ) . join ( ' ' ) ; let eq = part . indexOf ( '=' ) ; let key = eq > - 1 ? part . substr ( 0 , eq ) : part ; let val = eq > - 1 ? decodeURIComponent ( part . substr ( eq + 1 ) ) : '' ; let from = key . indexOf ( '[' ) ; if ( from === - 1 ) { result [ decodeURIComponent ( key ) ] = val ; }
else { let to = key . indexOf ( ']' ) ; let index = decodeURIComponent ( key . substring ( from + 1 , to ) ) ; key = decodeURIComponent ( key . substring ( 0 , from ) ) ; if ( ! result [ key ] ) { result [ key ] = [ ] ; }
if ( ! index ) { result [ key ] . push ( val ) ; }
else { result [ key ] [ index ] = val ; } } } ) ; return result ; } ; let states = [ ] ; let params = getJsonFromUrl ( window . location . search ) ; let hash = window . location . hash ; let current = null ; let previous = null ; let getPrevious = ( ) => previous ; let getCurrent = ( ) => current ; let setPrevious = ( value ) => { previous = value ; return this ; } ; let setCurrent = ( value ) => { current = value ; return this ; } ; let setParam = function ( key , value ) { params [ key ] = value ; return this ; } ; let getParam = function ( key , def ) { if ( key in params ) { return params [ key ] ; }
return def ; } ; let getParams = function ( ) { return params ; } ; let getURL = function ( ) { return window . location . href ; } ; let add = function ( path , view ) { if ( typeof path !== 'string' ) { throw new Error ( 'path must be of type string' ) ; }
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 ; } }
2019-06-08 09:39:40 +12:00
return null } ; let change = function ( URL , replace ) { if ( ! replace ) { window . history . pushState ( { } , '' , URL ) ; }
else { window . history . replaceState ( { } , '' , URL ) ; }
2019-08-13 02:19:54 +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 , as , prefix , 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 = ( reference [ 0 ] || '' ) ; let result = container . path ( path , undefined , as , prefix ) ; path = ( path . indexOf ( '.' ) > - 1 ) ? path . replace ( as + '.' , prefix + '.' ) : path . replace ( as , prefix ) ; 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 ) ; } }
2019-06-08 09:39:40 +12:00
if ( null === result || undefined === result ) { result = def ; }
2019-08-06 16:19:16 +12:00
else if ( typeof result === 'object' ) { result = JSON . stringify ( result , null , 4 ) ; }
2019-06-08 09:39:40 +12:00
else if ( ( ( typeof result === 'object' ) || ( typeof result === 'string' ) ) && cast ) { result = '\'' + result + '\'' ; }
2019-08-20 22:10:32 +12:00
return result ; } ) ; } , getPaths : ( ) => paths , } } , true , false ) ; window . ls . container . set ( 'filter' , function ( container ) { let filters = { } ; let add = function ( name , callback ) { filters [ name ] = callback ; return this ; } ; let apply = function ( name , value ) { container . set ( '$value' , value , true , false ) ; return container . resolve ( filters [ name ] ) ; } ; add ( 'uppercase' , ( $value ) => { if ( typeof $value !== 'string' ) { return $value ; }
return $value . toUpperCase ( ) ; } ) ; add ( 'lowercase' , ( $value ) => { if ( typeof $value !== 'string' ) { return $value ; }
return $value . toLowerCase ( ) ; } ) ; return { add : add , apply : apply } } , true , false ) ; window . ls . container . get ( 'filter' ) . add ( 'escape' , value => { if ( typeof value !== 'string' ) { return value ; }
2019-06-08 09:39:40 +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 ) ; }
2019-08-25 19:42:10 +12:00
catch ( error ) { let handler = window . ls . container . resolve ( this . error ) ; handler ( error ) ; } } ; window . ls . error = ( ) => { return error => { console . error ( 'ls-error' , error . message , error . stack , error . toString ( ) ) ; } } ; window . ls . router = window . ls . container . get ( 'router' ) ; window . ls . view = window . ls . container . get ( 'view' ) ; window . ls . filter = window . ls . container . get ( 'filter' ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-router' , repeat : false , controller : function ( element , window , document , view , router ) { let firstFromServer = ( element . getAttribute ( 'data-first-from-server' ) === 'true' ) ; let scope = { selector : 'data-ls-scope' , template : false , repeat : true , controller : function ( ) { } , } ; let init = function ( route ) { let count = parseInt ( element . getAttribute ( 'data-ls-scope-count' ) || 0 ) ; element . setAttribute ( 'data-ls-scope-count' , count + 1 ) ; window . scrollTo ( 0 , 0 ) ; if ( window . document . body . scrollTo ) { window . document . body . scrollTo ( 0 , 0 ) ; }
2019-05-10 04:15:51 +12:00
router . reset ( ) ; if ( null === route ) { return ; }
2019-06-08 09:39:40 +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 = '' ; }
2019-08-06 16:19:16 +12:00
else if ( count === 1 ) { view . render ( element ) ; }
2019-06-08 09:39:40 +12:00
else if ( null !== router . getPrevious ( ) ) { view . render ( element ) ; }
2019-05-10 04:15:51 +12:00
document . dispatchEvent ( new CustomEvent ( 'state-changed' ) ) ; } ; let findParent = function ( tagName , el ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; }
while ( el = el . parentNode ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; } }
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 ) ; }
2019-08-14 09:07:41 +12: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 , $as , $prefix ) { 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 ) , null , $as , $prefix ) ; paths = paths . concat ( expression . getPaths ( ) ) ; let value = '' ; if ( attr . indexOf ( '=' ) > - 1 ) { value = expression . parse ( attr . substring ( attr . indexOf ( '=' ) + 1 ) , null , $as , $prefix ) || '' ; paths = paths . concat ( expression . getPaths ( ) ) ; }
if ( ! key ) { return null ; }
element . setAttribute ( key , value ) ; } } ; check ( ) ; for ( let i = 0 ; i < paths . length ; i ++ ) { let path = paths [ i ] . split ( '.' ) ; if ( debug ) { console . info ( 'debug-ls-attrs listen to:' , path . join ( '.' ) ) ; }
2019-08-20 22:10:32 +12:00
while ( path . length ) { container . bind ( element , path . join ( '.' ) , check , $as , $prefix ) ; path . pop ( ) ; } } } } ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-bind' , controller : function ( element , expression , container , $prefix , $as ) { 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' ) ; }
2019-08-06 16:19:16 +12:00
else { element . removeAttribute ( 'checked' ) ; }
if ( bind ) { element . addEventListener ( 'change' , ( ) => { for ( let i = 0 ; i < paths . length ; i ++ ) { if ( element . checked ) { value = element . value ; }
container . path ( paths [ i ] , value , $as , $prefix ) ; } } ) ; }
return ; }
2019-06-08 09:39:40 +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 ; }
2019-08-06 16:19:16 +12:00
else { element . removeAttribute ( 'checked' ) ; element . checked = false ; } }
else { try { value = JSON . parse ( value ) ; element . checked = ( Array . isArray ( value ) && ( value . indexOf ( element . value ) > - 1 ) ) ; value = element . value ; }
catch { return null ; } }
if ( bind ) { element . addEventListener ( 'change' , ( ) => { for ( let i = 0 ; i < paths . length ; i ++ ) { let value = container . path ( paths [ i ] , undefined , $as , $prefix ) ; let index = value . indexOf ( element . value ) ; if ( element . checked && index < 0 ) { value . push ( element . value ) ; }
if ( ! element . checked && index > - 1 ) { value . splice ( index , 1 ) ; }
container . path ( paths [ i ] , value , $as , $prefix ) ; } } ) ; }
return ; }
2019-08-21 23:00:32 +12:00
if ( element . value !== value ) { element . value = value ; element . dispatchEvent ( new Event ( 'change' ) ) ; }
2019-06-08 09:39:40 +12:00
if ( bind ) { element . addEventListener ( 'input' , sync ) ; element . addEventListener ( 'change' , sync ) ; } }
2019-08-28 12:13:26 +12:00
else { if ( element . textContent != value ) { element . innerHTML = value ; } } } ; let sync = ( ( as , prefix ) => { return ( ) => { for ( let i = 0 ; i < paths . length ; i ++ ) { if ( '{{' + paths [ i ] + '}}' !== syntax ) { continue ; }
container . path ( paths [ i ] , element . value , as , prefix ) ; } } } ) ( $as , $prefix ) ; let syntax = element . getAttribute ( 'data-ls-bind' ) ; let unsync = ( ! ! element . getAttribute ( 'data-unsync' ) ) || false ; let result = expression . parse ( syntax , null , $as , $prefix ) ; let paths = expression . getPaths ( ) ; echo ( result , ! unsync ) ; element . addEventListener ( 'looped' , function ( ) { echo ( expression . parse ( syntax , null , $as , $prefix ) , false ) ; } ) ; for ( let i = 0 ; i < paths . length ; i ++ ) { let path = paths [ i ] . split ( '.' ) ; while ( path . length ) { container . bind ( element , path . join ( '.' ) , ( ) => { echo ( expression . parse ( syntax , null , $as , $prefix ) , false ) ; } ) ; path . pop ( ) ; } } } } ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-if' , controller : function ( element , expression , container , view , $as , $prefix ) { 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' , $as , $prefix , true ) ) ; }
2019-06-08 09:39:40 +12:00
try { result = ( eval ( expression . parse ( syntax . replace ( /(\r\n|\n|\r)/gm , ' ' ) , 'undefined' , $as , $prefix , 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 ) ; }
2019-06-08 09:39:40 +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' ) ; }
2019-08-20 22:10:32 +12:00
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 , $as , $prefix ) ; path . pop ( ) ; } } } } ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-loop' , template : false , repeat : false , nested : false , controller : function ( element , view , container , window ) { let expr = element . getAttribute ( 'data-ls-loop' ) ; let as = element . getAttribute ( 'data-ls-as' ) ; let echo = function ( ) { let array = container . path ( expr ) ; 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' ) ; }
2019-08-24 17:25:11 +12:00
let children = [ ] ; let originalIndex = container . get ( '$index' ) || null ; let originalPrefix = container . get ( '$prefix' ) || null ; let originalAs = container . get ( '$as' ) || null ; element . $lsSkip = true ; element . style . visibility = ( 0 === array . length ) ? 'hidden' : 'visible' ; for ( let prop in array ) { if ( ! array . hasOwnProperty ( prop ) ) { continue ; }
2019-08-06 16:19:16 +12:00
children [ prop ] = template . cloneNode ( true ) ; element . appendChild ( children [ prop ] ) ; ( index => { let context = expr + '.' + index ; container . set ( as , container . path ( context ) , true , watch ) ; container . set ( '$index' , index , true , false ) ; container . set ( '$prefix' , context , true , false ) ; container . set ( '$as' , as , true , false ) ; view . render ( children [ prop ] ) ; } ) ( prop ) ; }
2019-08-24 17:25:11 +12:00
container . set ( '$index' , originalIndex , true , false ) ; container . set ( '$prefix' , originalPrefix , true , false ) ; container . set ( '$as' , originalAs , true , false ) ; element . dispatchEvent ( new Event ( 'looped' ) ) ; } ; let template = ( element . children . length === 1 ) ? element . children [ 0 ] : window . document . createElement ( 'li' ) ; echo ( ) ; container . bind ( element , expr + '.length' , echo ) ; let path = ( expr + '.length' ) . split ( '.' ) ; while ( path . length ) { container . bind ( element , path . join ( '.' ) , echo ) ; path . pop ( ) ; } } } ) ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-ls-template' , template : false , repeat : true , controller : function ( element , view , http , expression , document ) { let template = expression . parse ( element . getAttribute ( 'data-ls-template' ) ) ; let type = element . getAttribute ( 'data-type' ) || 'url' ; element . innerHTML = '' ; if ( 'script' === type ) { let inlineTemplate = document . getElementById ( template ) ; if ( inlineTemplate && inlineTemplate . innerHTML ) { element . innerHTML = inlineTemplate . innerHTML ; element . dispatchEvent ( new CustomEvent ( 'template-loaded' , { bubbles : true , cancelable : false } ) ) ; }
2019-06-08 09:39:40 +12:00
else { element . innerHTML = '<span style="color: red">Missing template "' + template + '"</span>' ; }
2019-05-10 04:15:51 +12:00
return ; }
2019-09-13 22:47:48 +12:00
http . get ( template ) . 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' ) ; } ) ; } } ) ; window . ls . error = function ( ) { return function ( error ) { console . error ( "ERROR-APP" , error ) ; } ; } ; window . addEventListener ( "error" , function ( event ) { console . error ( "ERROR-EVENT:" , event . error . message , event . error . stack ) ; } ) ; document . addEventListener ( "logout" , function ( ) { window . location = "/auth/signin" ; } ) ; document . addEventListener ( "http-get-401" , function ( ) { document . dispatchEvent ( new CustomEvent ( "logout" ) ) ; } , true ) ; ( function ( window ) { "use strict" ; window . ls . container . set ( 'alerts' , function ( window ) { return { list : [ ] , counter : 0 , add : function ( message , time ) { var scope = this ; message . id = this . counter ++ ; scope . list . unshift ( message ) ; if ( time > 0 ) { window . setTimeout ( function ( message ) { return function ( ) { scope . remove ( message . id ) } } ( message ) , time ) ; }
2019-08-08 08:35:20 +12:00
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 ) ) { if ( typeof obj . callback === "function" ) { obj . callback ( ) ; }
scope . list . splice ( index , 1 ) ; } ; } } } ; } , true , 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 ) }
2019-05-13 06:15:19 +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 'string' : value = value . toString ( ) ; break ; case 'json' : value = ( value ) ? JSON . parse ( value ) : [ ] ; break ; case 'array' : value = ( value . constructor === Array ) ? value : [ value ] ; break ; case 'array-empty' : value = [ ] ; break ; case 'bool' : case 'boolean' : value = ( value === 'false' ) ? false : value ; value = ! ! value ; break ; }
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 ) ; }
2019-09-13 22:47:48 +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 ( '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 ( '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 . VERSION , scope : "home" } ) . add ( "/auth/signup" , { template : "/auth/signup?version=" + APP _ENV . VERSION , scope : "home" } ) . add ( "/auth/recovery" , { template : "/auth/recovery?version=" + APP _ENV . VERSION , scope : "home" } ) . add ( "/auth/recovery/reset" , { template : "/auth/recovery/reset?version=" + APP _ENV . VERSION , scope : "home" } ) . add ( "/auth/confirm" , { template : "/auth/confirm?version=" + APP _ENV . VERSION , scope : "home" } ) . add ( "/auth/join" , { template : "/auth/join?version=" + APP _ENV . VERSION , scope : "home" } ) . add ( "/console" , { template : "/console?version=" + APP _ENV . VERSION , scope : "console" } ) . add ( "/console/account" , { template : "/console/account?version=" + APP _ENV . VERSION , scope : "console" } ) . add ( "/console/account/:tab" , { template : "/console/account?version=" + APP _ENV . VERSION , scope : "console" } ) . add ( "/console/home" , { template : "/console/home?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/home/:tab" , { template : "/console/home?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/platforms/:platform" , { template : function ( window ) { return window . location . pathname + "?version=" + APP _ENV . VERSION ; } , scope : "console" , project : true } ) . add ( "/console/notifications" , { template : "/console/notifications?version=" + APP _ENV . VERSION , scope : "console" } ) . add ( "/console/settings" , { template : "/console/settings?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/settings/:tab" , { template : "/console/settings?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/webhooks" , { template : "/console/webhooks?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/webhooks/:tab" , { template : "/console/webhooks?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/keys" , { template : "/console/keys?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/keys/:tab" , { template : "/console/keys?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/tasks" , { template : "/console/tasks?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/tasks/:tab" , { template : "/console/tasks?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/database" , { template : "/console/database?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/database/collection" , { template : "/console/database/collection?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/storage" , { template : "/console/storage?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/storage/:tab" , { template : "/console/storage?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/users" , { template : "/console/users?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/users/view" , { template : "/console/users/view?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/users/view/:tab" , { template : "/console/users/view?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) . add ( "/console/users/:tab" , { template : "/console/users?version=" + APP _ENV . VERSION , scope : "console" , project : true } ) ; window . ls . filter . add ( "gravatar" , function ( $value , element ) { if ( ! $value ) { return "" ; }
let MD5 = function ( s ) { function L ( k , d ) { return ( k << d ) | ( k >>> ( 32 - d ) ) ; }
function K ( G , k ) { let I , d , F , H , x ; F = G & 2147483648 ; H = k & 2147483648 ; I = G & 1073741824 ; d = k & 1073741824 ; x = ( G & 1073741823 ) + ( k & 1073741823 ) ; if ( I & d ) { return x ^ 2147483648 ^ F ^ H ; }
if ( I | d ) { if ( x & 1073741824 ) { return x ^ 3221225472 ^ F ^ H ; } else { return x ^ 1073741824 ^ F ^ H ; } } else { return x ^ F ^ H ; } }
function r ( d , F , k ) { return ( d & F ) | ( ~ d & k ) ; }
function q ( d , F , k ) { return ( d & k ) | ( F & ~ k ) ; }
function p ( d , F , k ) { return d ^ F ^ k ; }
function n ( d , F , k ) { return F ^ ( d | ~ k ) ; }
function u ( G , F , aa , Z , k , H , I ) { G = K ( G , K ( K ( r ( F , aa , Z ) , k ) , I ) ) ; return K ( L ( G , H ) , F ) ; }
function f ( G , F , aa , Z , k , H , I ) { G = K ( G , K ( K ( q ( F , aa , Z ) , k ) , I ) ) ; return K ( L ( G , H ) , F ) ; }
function D ( G , F , aa , Z , k , H , I ) { G = K ( G , K ( K ( p ( F , aa , Z ) , k ) , I ) ) ; return K ( L ( G , H ) , F ) ; }
function t ( G , F , aa , Z , k , H , I ) { G = K ( G , K ( K ( n ( F , aa , Z ) , k ) , I ) ) ; return K ( L ( G , H ) , F ) ; }
function e ( G ) { let Z ; let F = G . length ; let x = F + 8 ; let k = ( x - ( x % 64 ) ) / 64 ; let I = ( k + 1 ) * 16 ; let aa = Array ( I - 1 ) ; let d = 0 ; let H = 0 ; while ( H < F ) { Z = ( H - ( H % 4 ) ) / 4 ; d = ( H % 4 ) * 8 ; aa [ Z ] = aa [ Z ] | ( G . charCodeAt ( H ) << d ) ; H ++ ; }
Z = ( H - ( H % 4 ) ) / 4 ; d = ( H % 4 ) * 8 ; aa [ Z ] = aa [ Z ] | ( 128 << d ) ; aa [ I - 2 ] = F << 3 ; aa [ I - 1 ] = F >>> 29 ; return aa ; }
function B ( x ) { let k = "" , F = "" , G , d ; for ( d = 0 ; d <= 3 ; d ++ ) { G = ( x >>> ( d * 8 ) ) & 255 ; F = "0" + G . toString ( 16 ) ; k = k + F . substr ( F . length - 2 , 2 ) ; }
return k ; }
function J ( k ) { k = k . replace ( /rn/g , "n" ) ; let d = "" ; for ( let F = 0 ; F < k . length ; F ++ ) { let x = k . charCodeAt ( F ) ; if ( x < 128 ) { d += String . fromCharCode ( x ) ; } else { if ( x > 127 && x < 2048 ) { d += String . fromCharCode ( ( x >> 6 ) | 192 ) ; d += String . fromCharCode ( ( x & 63 ) | 128 ) ; } else { d += String . fromCharCode ( ( x >> 12 ) | 224 ) ; d += String . fromCharCode ( ( ( x >> 6 ) & 63 ) | 128 ) ; d += String . fromCharCode ( ( x & 63 ) | 128 ) ; } } }
return d ; }
let C = Array ( ) ; let P , h , E , v , g , Y , X , W , V ; let S = 7 , Q = 12 , N = 17 , M = 22 ; let A = 5 , z = 9 , y = 14 , w = 20 ; let o = 4 , m = 11 , l = 16 , j = 23 ; let U = 6 , T = 10 , R = 15 , O = 21 ; s = J ( s ) ; C = e ( s ) ; Y = 1732584193 ; X = 4023233417 ; W = 2562383102 ; V = 271733878 ; for ( P = 0 ; P < C . length ; P += 16 ) { h = Y ; E = X ; v = W ; g = V ; Y = u ( Y , X , W , V , C [ P + 0 ] , S , 3614090360 ) ; V = u ( V , Y , X , W , C [ P + 1 ] , Q , 3905402710 ) ; W = u ( W , V , Y , X , C [ P + 2 ] , N , 606105819 ) ; X = u ( X , W , V , Y , C [ P + 3 ] , M , 3250441966 ) ; Y = u ( Y , X , W , V , C [ P + 4 ] , S , 4118548399 ) ; V = u ( V , Y , X , W , C [ P + 5 ] , Q , 1200080426 ) ; W = u ( W , V , Y , X , C [ P + 6 ] , N , 2821735955 ) ; X = u ( X , W , V , Y , C [ P + 7 ] , M , 4249261313 ) ; Y = u ( Y , X , W , V , C [ P + 8 ] , S , 1770035416 ) ; V = u ( V , Y , X , W , C [ P + 9 ] , Q , 2336552879 ) ; W = u ( W , V , Y , X , C [ P + 10 ] , N , 4294925233 ) ; X = u ( X , W , V , Y , C [ P + 11 ] , M , 2304563134 ) ; Y = u ( Y , X , W , V , C [ P + 12 ] , S , 1804603682 ) ; V = u ( V , Y , X , W , C [ P + 13 ] , Q , 4254626195 ) ; W = u ( W , V , Y , X , C [ P + 14 ] , N , 2792965006 ) ; X = u ( X , W , V , Y , C [ P + 15 ] , M , 1236535329 ) ; Y = f ( Y , X , W , V , C [ P + 1 ] , A , 4129170786 ) ; V = f ( V , Y , X , W , C [ P + 6 ] , z , 3225465664 ) ; W = f ( W , V , Y , X , C [ P + 11 ] , y , 643717713 ) ; X = f ( X , W , V , Y , C [ P + 0 ] , w , 3921069994 ) ; Y = f ( Y , X , W , V , C [ P + 5 ] , A , 3593408605 ) ; V = f ( V , Y , X , W , C [ P + 10 ] , z , 38016083 ) ; W = f ( W , V , Y , X , C [ P + 15 ] , y , 3634488961 ) ; X = f ( X , W , V , Y , C [ P + 4 ] , w , 3889429448 ) ; Y = f ( Y , X , W , V , C [ P + 9 ] , A , 568446438 ) ; V = f ( V , Y , X , W , C [ P + 14 ] , z , 3275163606 ) ; W = f ( W , V , Y , X , C [ P + 3 ] , y , 4107603335 ) ; X = f ( X , W , V , Y , C [ P + 8 ] , w , 1163531501 ) ; Y = f ( Y , X , W , V , C [ P + 13 ] , A , 2850285829 ) ; V = f ( V , Y , X , W , C [ P + 2 ] , z , 4243563512 ) ; W = f ( W , V , Y , X , C [ P + 7 ] , y , 1735328473 ) ; X = f ( X , W , V , Y , C [ P + 12 ] , w , 2368359562 ) ; Y = D ( Y , X , W , V , C [ P + 5 ] , o , 4294588738 ) ; V = D ( V , Y , X , W , C [ P + 8 ] , m , 2272392833 ) ; W = D ( W , V , Y , X , C [ P + 11 ] , l , 1839030562 ) ; X = D ( X , W , V , Y , C [ P + 14 ] , j , 4259657740 ) ; Y = D ( Y , X , W , V , C [ P + 1 ] , o , 2763975236 ) ; V = D ( V , Y , X , W , C [ P + 4 ] , m , 1272893353 ) ; W = D ( W , V , Y , X , C [ P + 7 ] , l , 4139469664 ) ; X = D ( X , W , V , Y , C [ P + 10 ] , j , 3200236656 ) ; Y = D ( Y , X , W , V , C [ P + 13 ] , o , 681279174 ) ; V = D ( V , Y , X , W , C [ P + 0 ] , m , 3936430074 ) ; W = D ( W , V , Y , X , C [ P + 3 ] , l , 3572445317 ) ; X = D ( X , W , V , Y , C [ P + 6 ] , j , 76029189 ) ; Y = D ( Y , X , W , V , C [ P + 9 ] , o , 3654602809 ) ; V = D ( V , Y , X , W , C [ P + 12 ] , m , 3873151461 ) ; W = D ( W , V , Y , X , C [ P + 15 ] , l , 530742520 ) ; X = D ( X , W , V , Y , C [ P + 2 ] , j , 3299628645 ) ; Y = t ( Y , X , W , V , C [ P + 0 ] , U , 4096336452 ) ; V = t ( V , Y , X , W , C [ P + 7 ] , T , 1126891415 ) ; W = t ( W , V , Y , X , C [ P + 14 ] , R , 2878612391 ) ; X = t ( X , W , V , Y , C [ P + 5 ] , O , 4237533241 ) ; Y = t ( Y , X , W , V , C [ P + 12 ] , U , 1700485571 ) ; V = t ( V , Y , X , W , C [ P + 3 ] , T , 2399980690 ) ; W = t ( W , V , Y , X , C [ P + 10 ] , R , 4293915773 ) ; X = t ( X , W , V , Y , C [ P + 1 ] , O , 2240044497 ) ; Y = t ( Y , X , W , V , C [ P + 8 ] , U , 1873313359 ) ; V = t ( V , Y , X , W , C [ P + 15 ] , T , 4264355552 ) ; W = t ( W , V , Y , X , C [ P + 6 ] , R , 2734768916 ) ; X = t ( X , W , V , Y , C [ P + 13 ] , O , 1309151649 ) ; Y = t ( Y , X , W , V , C [ P + 4 ] , U , 4149444226 ) ; V = t ( V , Y , X , W , C [ P + 11 ] , T , 3174756917 ) ; W = t ( W , V , Y , X , C [ P + 2 ] , R , 718787259 ) ; X = t ( X , W , V , Y , C [ P + 9 ] , O , 3951481745 ) ; Y = K ( Y , h ) ; X = K ( X , E ) ; W = K ( W , v ) ; V = K ( V , g ) ; }
2019-10-13 10:53:03 +13:00
let i = B ( Y ) + B ( X ) + B ( W ) + B ( V ) ; return i . toLowerCase ( ) ; } ; let size = element . dataset [ "size" ] || 80 ; let email = $value . email || $value || "" ; let name = $value . name || $value || "" ; name = ( typeof stringValue !== 'string' ) ? '' : name ; let theme = name . split ( "" ) . map ( char => char . charCodeAt ( 0 ) ) . reduce ( ( a , b ) => a + b , 0 ) . toString ( ) ; let themes = [ { color : "27005e" , background : "e1d2f6" } , { color : "5e2700" , background : "f3d9c6" } , { color : "006128" , background : "c9f3c6" } , { color : "580061" , background : "f2d1f5" } , { color : "00365d" , background : "c6e1f3" } , { color : "00075c" , background : "d2d5f6" } , { color : "610038" , background : "f5d1e6" } , { color : "386100" , background : "dcf1bd" } , { color : "615800" , background : "f1ecba" } , { color : "610008" , background : "f6d2d5" } ] ; name = name . split ( " " ) . map ( function ( n ) { if ( ! isNaN ( parseFloat ( n ) ) && isFinite ( n ) ) { return "" ; }
2019-09-13 22:47:48 +12:00
return n [ 0 ] ; } ) . join ( "" ) || "--" ; let background = themes [ theme [ theme . length - 1 ] ] [ "background" ] ; let color = themes [ theme [ theme . length - 1 ] ] [ "color" ] ; let def = "https://ui-avatars.com/api/" +
encodeURIComponent ( name ) + "/" +
size + "/" +
encodeURIComponent ( background ) + "/" +
encodeURIComponent ( color ) ; return ( "//www.gravatar.com/avatar/" +
MD5 ( email ) + ".jpg?s=" +
size + "&d=" +
encodeURIComponent ( def ) ) ; } ) . 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 ( "date-time" , function ( $value , date ) { return date . format ( "Y-m-d H:i" , $value ) ; } ) . add ( "date-text" , function ( $value , date ) { return date . format ( "d M Y" , $value ) ; } ) . 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" ) ; }
return "< 1s" ; } ) . 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 ; }
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 ; }
2019-10-19 12:59:33 +13:00
$value = abbreviate ( $value , 1 , false , false ) ; return $value === "0" ? "N/A" : $value ; } ) . add ( "isEmptyObject" , function ( $value ) { return ( ( Object . keys ( $value ) . length === 0 && $value . constructor === Object ) || $value . length === 0 ) } ) ; 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" ) ; }
2019-11-04 07:33:36 +13:00
if ( "/console" === router . getCurrent ( ) . path ) { document . body . classList . add ( "index" ) ; } else { document . body . classList . remove ( "index" ) ; } } } ) . add ( { selector : "data-cookie-policy" , controller : function ( element , alerts , cookie , env ) { if ( ! cookie . get ( "cookie-alert" ) ) { let text = element . dataset [ "cookiePolicy" ] || "" ; alerts . add ( { text : text , class : "cookie-alert" , link : env . HOME + "/policy/cookies" , callback : function ( ) { cookie . set ( "cookie-alert" , "true" , 365 * 10 ) ; } } , 0 ) ; } } } ) . add ( { selector : "data-ls-ui-alerts" , controller : function ( element , window , view ) { window . document . addEventListener ( "alerted" , function ( ) { view . render ( element ) ; } , true ) ; } } ) . add ( { selector : "data-ls-ui-alerts-delete" , controller : function ( document , element , alerts , expression ) { let message = expression . parse ( element . dataset [ "message" ] ) ; let remove = function ( ) { alerts . remove ( message ) ; } ; element . addEventListener ( "click" , remove ) ; } } ) . 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 ( ) ; } } ) . 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 ) ; }
2019-09-13 22:47:48 +12:00
window . getSelection ( ) . removeAllRanges ( ) ; } ) ; element . parentNode . parentNode . appendChild ( copy ) ; } } ) . add ( { selector : "data-code-example" , controller : function ( window , document , element , cookie ) { let prefix = element . dataset [ "codeExample" ] || "unknown" ; element . addEventListener ( "change" , function ( ) { select ( element . value ) ; } ) ; let select = function ( value ) { for ( let i = 0 ; i < element . length ; i ++ ) { document . body . classList . remove ( prefix + "-" + element . options [ i ] . value ) ; }
document . body . classList . add ( prefix + "-" + value ) ; cookie . set ( "language-" + prefix , value , 365 ) ; document . dispatchEvent ( new CustomEvent ( "updated-language-" + prefix ) ) ; } ; document . addEventListener ( "updated-language-" + prefix , function ( ) { element . value = cookie . get ( "language-" + prefix ) ; } ) ; let def = cookie . get ( "language-" + prefix ) || element . options [ 0 ] . value ; select ( def ) ; element . value = def ; } } ) . add ( { selector : "data-ls-ui-chart" , controller : function ( element , container , date , document ) { let child = document . createElement ( "canvas" ) ; child . width = 500 ; child . height = 175 ; let stats = container . get ( "usage" ) ; if ( ! stats || ! stats [ "requests" ] || ! stats [ "requests" ] [ "data" ] ) { return ; }
let config = { type : "line" , data : { labels : [ ] , datasets : [ { label : "Requests" , backgroundColor : "rgba(230, 248, 253, 0.3)" , borderColor : "#29b5d9" , borderWidth : 2 , data : [ 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , fill : true } ] } , 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 < stats [ "requests" ] [ "data" ] . length ; i ++ ) { config . data . datasets [ 0 ] . data [ i ] = stats [ "requests" ] [ "data" ] [ i ] . value ; config . data . labels [ i ] = date . format ( "d F Y" , stats [ "requests" ] [ "data" ] [ i ] . date ) ; }
let chart = container . get ( "chart" ) ; if ( chart ) { }
element . innerHTML = "" ; element . appendChild ( child ) ; container . set ( "chart" , new Chart ( child . getContext ( "2d" ) , config ) , true ) ; element . dataset [ "canvas" ] = true ; } } ) ; ( 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" ] || action ; let event = element . dataset [ "event" ] ; let confirm = element . dataset [ "confirm" ] || "" ; let loading = element . dataset [ "loading" ] || "" ; let loaderId = null ; let scope = element . dataset [ "scope" ] || "sdk" ; let debug = ! ! element . dataset [ "debug" ] ; let success = element . dataset [ "success" ] || "" ; let failure = element . dataset [ "failure" ] || "" ; success = success && success != "" ? success . split ( "," ) . map ( element => element . trim ( ) ) : [ ] ; failure = failure && failure != "" ? failure . split ( "," ) . map ( element => element . trim ( ) ) : [ ] ; if ( debug )
console . log ( "%c[service init]: " + action + " (" + service + ")" , "color:red" ) ; let callbacks = { 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 ; }
if ( debug )
console . log ( "%c[event triggered]: " + events [ i ] , "color:green" ) ; document . dispatchEvent ( new CustomEvent ( events [ i ] ) ) ; } } ; } } ; 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 ) ; }
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 ( ) { } ; }
let args = getParams ( target ) ; if ( debug ) console . log ( "%c[form data]: " , "color:green" , data ) ; return target . apply ( target , args . map ( function ( value ) { let result = getValue ( value , prefix , data ) ; if ( debug )
console . log ( "[param resolved]: (" + service + ") " + value + "=" , result ) ; return result ; } ) ) ; } ; let exec = function ( event ) { element . $lsSkip = true ; element . classList . add ( "load-service-start" ) ; if ( debug )
console . log ( "%c[executed]: " + scope + "." + action , "color:yellow" , event , element , document . body . contains ( element ) ) ; if ( ! document . body . contains ( element ) ) { element = undefined ; return false ; }
2019-05-09 18:54:39 +12:00
if ( event ) { event . preventDefault ( ) ; }
if ( confirm ) { if ( window . confirm ( confirm ) !== true ) { return false ; } }
2019-09-13 22:47:48 +12:00
if ( loading ) { loaderId = alerts . add ( { text : loading , class : "" } , 0 ) ; }
let method = container . path ( scope + "." + action ) ; if ( ! method ) { throw new Error ( 'Method "' + scope + "." + action + '" not found' ) ; }
let formData = "FORM" === element . tagName ? form . toJson ( element ) : { } ; let result = resolve ( method , "param" , formData ) ; if ( ! result ) { return ; }
2019-05-09 18:54:39 +12:00
result . then ( function ( data ) { if ( loaderId !== null ) { alerts . remove ( loaderId ) ; }
if ( ! element ) { return ; }
2019-09-13 22:47:48 +12:00
element . classList . add ( "load-service-end" ) ; container . set ( service . replace ( "." , "-" ) , data , true , true ) ; container . set ( "serviceData" , data , true , true ) ; container . set ( "serviceForm" , formData , true , true ) ; if ( debug )
console . log ( '%cservice ready: "' + service . replace ( "." , "-" ) + '"' , "color:green" ) ; if ( debug )
console . log ( "%cservice:" , "color:blue" , container . get ( service . replace ( "." , "-" ) ) ) ; for ( let i = 0 ; i < success . length ; i ++ ) { container . resolve ( resolve ( callbacks [ success [ i ] ] , "successParam" +
success [ i ] . charAt ( 0 ) . toUpperCase ( ) +
success [ i ] . slice ( 1 ) , { } ) ) ; }
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 ; }
2019-09-13 22:47:48 +12:00
for ( let i = 0 ; i < failure . length ; i ++ ) { container . resolve ( resolve ( callbacks [ failure [ i ] ] , "failureParam" +
failure [ i ] . charAt ( 0 ) . toUpperCase ( ) +
failure [ i ] . slice ( 1 ) , { } ) ) ; }
element . $lsSkip = false ; view . render ( element ) ; } ) ; } ; let events = event . trim ( ) . split ( "," ) ; for ( let y = 0 ; y < events . length ; y ++ ) { if ( "" === events [ y ] ) { continue ; }
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 ) ; }
if ( debug )
console . log ( '%cregistered: "' + events [ y ] . trim ( ) + '" (' + service + ")" , "color:blue" ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-analytics-event" , controller : function ( element ) { var action = element . getAttribute ( "data-event-action" ) || "click" ; element . addEventListener ( action , function ( ) { var category = element . getAttribute ( "data-event-category" ) || "undefined" ; var label = element . getAttribute ( "data-event-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-pageview" , controller : function ( window , router ) { if ( ! ga ) { console . error ( "Google Analytics ga object is not available" ) ; }
var company = router . params [ "company" ] || null ; if ( ! company ) { }
ga ( "set" , "page" , window . location . pathname ) ; ga ( "set" , "dimension1" , company ) ; 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 ) ; }
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-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 . title = "Copy to Clipboard" ; copy . addEventListener ( "click" , function ( ) { element . disabled = false ; element . focus ( ) ; element . select ( ) ; document . execCommand ( "Copy" ) ; if ( document . selection ) { document . selection . empty ( ) ; } else if ( window . getSelection ) { window . getSelection ( ) . removeAllRanges ( ) ; }
element . disabled = true ; alerts . add ( { text : "Copied to clipboard" , class : "" } , 3000 ) ; } ) ; let check = function ( ) { if ( ! element . value ) { return ; }
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 ; }
2019-09-13 22:47:48 +12: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 ) { element . disabled = false ; element . focus ( ) ; element . select ( ) ; document . execCommand ( "Copy" ) ; if ( document . selection ) { document . selection . empty ( ) ; } else if ( window . getSelection ) { window . getSelection ( ) . removeAllRanges ( ) ; }
element . disabled = true ; alerts . add ( { text : "Copied to clipboard" , class : "" } , 3000 ) ; } ; button . addEventListener ( "click" , copy ) ; } } ) ; } ) ( 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 ; }
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" ) ; }
break ; default : break ; } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-parent-down" , controller : function ( element ) { var target = element . dataset [ "target" ] || null ; target = target ? element . closest ( target ) : element . parentNode ; element . addEventListener ( "click" , function ( ) { if ( target . nextElementSibling ) { target . parentNode . insertBefore ( target . nextElementSibling , target ) ; element . scrollIntoView ( { behavior : "smooth" } ) ; } } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-parent-remove" , controller : function ( element ) { var target = element . dataset [ "target" ] || null ; target = target ? element . closest ( target ) : element . parentNode ; element . addEventListener ( "click" , function ( ) { target . parentNode . removeChild ( target ) ; element . scrollIntoView ( { behavior : "smooth" } ) ; } ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( "view" ) . add ( { selector : "data-forms-parent-up" , controller : function ( element ) { var target = element . dataset [ "target" ] || null ; target = target ? element . closest ( target ) : element . parentNode ; element . addEventListener ( "click" , function ( ) { if ( target . previousElementSibling ) { target . parentNode . insertBefore ( target , target . previousElementSibling ) ; element . scrollIntoView ( { behavior : "smooth" } ) ; } } ) ; } } ) ; } ) ( 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 ] ] ; }
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 ; } }
2019-12-24 18:43:15 +13: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 ) { 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 ) { 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>' } ] } ) ; element . addEventListener ( "change" , function ( ) { editor . content . innerHTML = markdown . render ( element . value ) ; } ) ; editor . content . setAttribute ( "placeholder" , element . placeholder ) ; editor . content . innerHTML = markdown . render ( element . value ) ; editor . content . tabIndex = 0 ; 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 ( ) ; } } } } } ; var clean = function ( e ) { e . stopPropagation ( ) ; e . preventDefault ( ) ; var clipboardData = e . clipboardData || window . clipboardData ; window . pell . exec ( "insertText" , clipboardData . getData ( "Text" ) ) ; return true ; } ; div . addEventListener ( "paste" , clean ) ; div . addEventListener ( "drop" , clean ) ; } } ) ; } ) ( 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-switch" , controller : function ( element ) { let input = window . document . createElement ( "input" ) ; input . type = "checkbox" ; input . className = "switch" ; let syncA = function ( ) { element . value = input . checked ? "on" : "off" ; } ; let syncB = function ( ) { input . checked = element . value === "on" ; } ; 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" ) ; tags . className = "tags" ; preview . className = " tags
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 ( ) ; }
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 = [ ] ; }
2019-09-13 22:47:48 +12:00
preview . innerHTML = "" ; for ( let index = 0 ; index < array . length ; index ++ ) { let value = array [ index ] ; let tag = window . document . createElement ( "li" ) ; tag . className = "tag" ; tag . textContent = value ; tag . addEventListener ( "click" , function ( ) { array . splice ( index , 1 ) ; element . value = JSON . stringify ( array ) ; check ( ) ; } ) ; preview . appendChild ( tag ) ; }
if ( element . required && array . length === 0 ) { add . setCustomValidity ( "Please add permissions" ) ; } else { add . setCustomValidity ( "" ) ; } } ; 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 ( "span" ) ; counter . className = "counter" ; element . parentNode . insertBefore ( counter , element . nextSibling ) ; var count = function ( ) { if ( 0 <= element . maxLength ) { counter . innerText = ( element . maxLength - element . value . length ) . toString ( ) + " / " +
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 ) { var rtlStock = "^ا ^ب^ت^ث^ج^ح^خ^د^ذ^ر^ز^س^ش^ص^ض^ط^ظ^ع^غ^ف^ق^ك^ل^م^ن^ه ^و^ي^א^ב^ג^ד^ה^ו ^ז^ח^ט ^י ^כ^ך^ל^מ^ם^נ^ן ^ס ^ע^פ^ף^צ^ץ^ק^ר^ש^ת^" ; var special = [ "\n" , " " , "״" , '"' , "_" , "'" , "!" , "@" , "#" , "$" , "^" , "&" , "%" , "*" , "(" , ")" , "+" , "=" , "-" , "[" , "]" , "\\" , "/" , "{" , "}" , "|" , ":" , "<" , ">" , "?" , "," , "." , "0" , "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" , "9" ] ; var setDirection = function ( ) { var value = element . value [ 0 ] ? element . value : "" ; var direction = "ltr" ; var align = "left" ; for ( var i = 0 ; i < value . length ; i ++ ) { if ( - 1 === special . indexOf ( value [ i ] ) ) { var firstChar = value [ i ] ; break ; } }
if ( - 1 < rtlStock . indexOf ( "^" + firstChar + "^" ) ) { direction = "rtl" ; align = "right" ; }
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 ) ; }
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 ) { var scope = element . dataset [ "scope" ] ; 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 accept = element . dataset [ "accept" ] || "" ; var required = element . dataset [ "required" ] || false ; var multiple = element . dataset [ "multiple" ] || 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 ? multiple ? JSON . parse ( element . value ) : [ element . value ] : [ ] ; var total = 0 ; 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 . multiple = multiple ; input . tabIndex = - 1 ; count . className = "count" ; upload . className = "button reverse margin-bottom" ; 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 humanFileSize = function ( bytes , si ) { var thresh = si ? 1000 : 1024 ; if ( Math . abs ( bytes ) < thresh ) { return bytes + " B" ; }
var units = si ? [ "KB" , "MB" , "GB" , "TB" , "PB" , "EB" , "ZB" , "YB" ] : [ "KiB" , "MiB" , "GiB" , "TiB" , "PiB" , "EiB" , "ZiB" , "YiB" ] ; var u = - 1 ; do { bytes /= thresh ; ++ u ; } while ( Math . abs ( bytes ) >= thresh && u < units . length - 1 ) ; return bytes . toFixed ( 1 ) + " " + units [ u ] ; } ; 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 ( files ) { if ( ! Array . isArray ( files ) ) { files = [ files ] ; }
preview . innerHTML = "" ; count . innerHTML = "0 / " + max ; files . map ( function ( obj ) { var file = document . createElement ( "li" ) ; var image = document . createElement ( "img" ) ; image . src = image . src = env . API + "/storage/files/" +
obj + "/preview?width=" +
previewWidth + "&height=" +
previewHeight ; file . className = "file avatar" ; file . tabIndex = 0 ; file . appendChild ( image ) ; count . innerHTML = files . length + " / " + max ; preview . appendChild ( file ) ; if ( files . length >= max ) { input . disabled = true ; upload . classList . add ( "disabled" ) ; } else { input . disabled = false ; upload . classList . remove ( "disabled" ) ; }
var remove = ( function ( obj ) { return function ( event ) { output = Array . isArray ( output ) ? output . filter ( function ( e ) { return e !== obj ; } ) : [ ] ; render ( output ) ; } ; } ) ( obj ) ; file . addEventListener ( "click" , remove ) ; file . addEventListener ( "keypress" , remove ) ; element . value = multiple ? JSON . stringify ( output ) : output [ 0 ] ; } ) ; } ; 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" ] || "[]" ) ) ; if ( ! multiple ) { output = [ ] ; }
sdk . storage . createFile ( files [ 0 ] , read , write , 1 ) . then ( function ( response ) { response . map ( function ( obj ) { if ( ! Array . isArray ( output ) ) { throw new Error ( "Can't append new file to non array value" ) ; }
output [ output . length ] = obj [ "$uid" ] ; } ) ; onComplete ( message ) ; render ( output ) ; } , function ( error ) { alerts . add ( { text : "An error occurred!" , class : "" } , 3000 ) ; onComplete ( message ) ; } ) ; input . disabled = true ; } ) ; element . addEventListener ( "change" , function ( ) { if ( ! element . value ) { return ; }
output = multiple ? JSON . parse ( element . value ) : [ element . value ] ; render ( output ) ; } ) ; upload . addEventListener ( "keypress" , function ( ) { input . click ( ) ; } ) ; element . parentNode . insertBefore ( wrapper , element ) ; wrapper . appendChild ( preview ) ; wrapper . appendChild ( progress ) ; wrapper . appendChild ( upload ) ; if ( multiple ) { wrapper . appendChild ( count ) ; }
2019-10-24 08:04:47 +13:00
upload . appendChild ( input ) ; render ( output ) ; } } ) ; } ) ( 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 ) { window . ls . container . get ( "view" ) . add ( { selector : "data-setup" , controller : function ( element , console , form , alerts ) { 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 . createTeam ( formData [ "name" ] || "" ) . then ( function ( data ) { let team = data [ "$uid" ] ; formData = JSON . parse ( JSON . stringify ( formData ) . replace ( new RegExp ( "{{teamId}}" , "g" ) , team ) ) ; console . projects . createProject ( formData [ "name" ] , team ) . then ( function ( project ) { alerts . remove ( loaderId ) ; window . location . href = "/console/home?project=" + project [ "$uid" ] ; } , 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 ; }
2019-09-13 22:47:48 +12: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-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 ++ ) { links [ i ] . href = links [ i ] . href || expression . parse ( links [ i ] . dataset [ "lsHref" ] || "" ) ; list . push ( links [ i ] ) ; }
list . sort ( function ( a , b ) { return a . pathname . length - b . pathname . length ; } ) ; for ( let i = 0 ; i < list . length ; i ++ ) { if ( list [ i ] . pathname === window . location . pathname . substring ( 0 , list [ i ] . pathname . length ) ) { list [ i ] . classList . add ( "selected" ) ; if ( selected !== null ) { list [ selected ] . classList . remove ( "selected" ) ; }
selected = i ; } else { list [ i ] . classList . remove ( "selected" ) ; } } } ; document . addEventListener ( "state-changed" , check ) ; check ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { window . ls . container . get ( "view" ) . add ( { selector : "data-ui-modal" , controller : function ( document , element , expression ) { let name = element . dataset [ "name" ] || null ; let buttonText = expression . parse ( element . dataset [ "buttonText" ] || "" ) ; let buttonClass = element . dataset [ "buttonClass" ] || "button-class" ; let buttonIcon = element . dataset [ "buttonIcon" ] || null ; let buttonEvent = element . dataset [ "buttonEvent" ] || "" ; let buttonAlias = element . dataset [ "buttonAlias" ] || "" ; let buttonElements = ! buttonAlias ? [ document . createElement ( "button" ) ] : document . querySelectorAll ( buttonAlias ) ; let openEvent = element . dataset [ "openEvent" ] || null ; 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 } ) ) ; } ) ; }
if ( ! buttonAlias ) { buttonElements . forEach ( button => { button . innerText = buttonText ; button . className = buttonClass ; button . type = "button" ; if ( buttonIcon ) { let iconElement = document . createElement ( "i" ) ; iconElement . className = buttonIcon ; button . insertBefore ( iconElement , button . firstChild ) ; } } ) ; }
if ( buttonEvent ) { buttonElements . forEach ( button => { button . addEventListener ( "click" , function ( ) { document . dispatchEvent ( new CustomEvent ( buttonEvent , { bubbles : false , cancelable : true } ) ) ; } ) ; } ) ; }
element . classList . add ( "modal" ) ; if ( ! buttonAlias ) { buttonElements . forEach ( button => { element . parentNode . insertBefore ( button , element ) ; } ) ; }
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 close = function ( ) { 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 ) ; }
document . addEventListener ( "modal-close" , close ) ; element . addEventListener ( "submit" , 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 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 . tabIndex = 1 ; button . type = "button" ; if ( buttonIcon ) { let icon = window . document . createElement ( "i" ) ; icon . className = buttonIcon ; button . insertBefore ( icon , button . firstChild ) ; }
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" ) ; } ) ; }
let close = function ( ) { element . classList . add ( "close" ) ; element . classList . remove ( "open" ) ; } ; let closeDelay = function ( ) { window . setTimeout ( function ( ) { close ( ) ; } , 150 ) ; } ; let findParent = function ( tagName , el ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; }
while ( ( el = el . parentNode ) ) { if ( ( el . nodeName || el . tagName ) . toLowerCase ( ) === tagName . toLowerCase ( ) ) { return el ; } }
return null ; } ; 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 ) ; } } ) ; }
element . addEventListener ( "click" , function ( event ) { let target = findParent ( "a" , event . target ) ; if ( ! target ) { return false ; }
2019-05-09 18:54:39 +12:00
if ( ! target . href ) { return false ; }
2019-09-13 22:47:48 +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 . getElementsByTagName ( "h2" ) ) ; 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 ; for ( var i = 0 ; i < element . children . length ; i ++ ) { var tabState = expression . parse ( element . children [ i ] . dataset [ "state" ] || "" ) ; if ( tabState === ( window . location . pathname + window . location . search ) . substring ( 0 , tabState . length ) ) { position = i ; } }
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 ( ) ; } }
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 ) { let trigger = element . dataset [ "lsUiTrigger" ] ; let event = element . dataset [ "event" ] || "click" ; element . addEventListener ( event , function ( ) { document . dispatchEvent ( new CustomEvent ( trigger ) ) ; } ) ; } } ) ; } ) ( window ) ;