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-08-20 22:10:32 +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-08-11 17:18:10 +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 ) } 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 || '' ; let theme = name . split ( '' ) . ma
2019-08-22 17:42:16 +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 " : "" ) +
Number . parseFloat ( seconds ) . toFixed ( 0 ) + "s" ; }
2019-08-17 18:09:54 +12:00
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 ; }
2019-08-07 20:53:47 +12:00
let thresh = 1000 ; if ( Math . abs ( $value ) < thresh ) { return $value + ' B' ; }
let units = [ 'kB' , 'MB' , 'GB' , 'TB' , 'PB' , 'EB' , 'ZB' , 'YB' ] ; let u = - 1 ; do { $value /= thresh ; ++ u ; } while ( Math . abs ( $value ) >= thresh && u < units . length - 1 ) ; return $value . toFixed ( 1 ) + '<span class="text-size-small unit">' + units [ u ] + '</span>' ; } ) . add ( 'statsTotal' , function ( $value ) { if ( ! $value ) { return 0 ; }
2019-05-10 07:30:30 +12:00
$value = abbreviate ( $value , 1 , false , false ) ; return ( $value === '0' ) ? 'N/A' : $value ; } ) ; function abbreviate ( number , maxPlaces , forcePlaces , forceLetter ) { number = Number ( number ) ; forceLetter = forceLetter || false ; if ( forceLetter !== false ) { return annotate ( number , maxPlaces , forcePlaces , forceLetter ) ; }
2019-05-09 18:54:39 +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 = '' ; }
return annotate ( number , maxPlaces , forcePlaces , abbr ) ; }
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 }
2019-05-09 20:23:22 +12:00
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' ) ; }
2019-05-09 18:54:39 +12:00
else { document . body . classList . add ( 'show-nav' ) ; document . body . classList . remove ( 'hide-nav' ) ; }
2019-05-09 20:23:22 +12:00
if ( '/console' === router . getCurrent ( ) . path ) { document . body . classList . add ( 'index' ) ; }
2019-08-22 17:56:25 +12:00
else { document . body . classList . remove ( 'index' ) ; } } } ) . add ( { selector : 'data-cookie-policy' , controller : function ( element , alerts , cookie ) { if ( ! cookie . get ( 'cookie-alert' ) ) { let text = element . dataset [ 'cookiePolicy' ] || '' ; alerts . add ( { text : text , class : 'cookie-alert' , link : '/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 . 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 ) ; }
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 ; }
2019-05-09 18:54:39 +12:00
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 ) { }
2019-08-21 16:37:08 +12:00
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-08-12 09:18:05 +12: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 ) { router . change ( 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 ] ; }
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 ; } } }
2019-08-24 17:00:40 +12:00
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 ; }
2019-08-08 06:10:53 +12:00
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]*?\*\/))/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 ; let functionAsString = func . toString ( ) ; let params = [ ] ; let match ; functionAsString = functionAsString . replace ( REGEX _COMMENTS , '' ) ; functionAsString = functionAsString . match ( REGEX _FUNCTION _PARAMS ) [ 1 ] ; if ( functionAsString . charAt ( 0 ) === '(' ) { functionAsString = functionAsString . slice ( 1 , - 1 ) ; }
2019-08-07 19:02:12 +12:00
while ( match = REGEX _PARAMETERS _VALUES . exec ( functionAsString ) ) { params . push ( match [ 1 ] ) ; }
return params ; }
2019-08-12 09:18:05 +12:00
let getValue = function ( key , prefix , data ) { let result = null ; if ( ! key ) { return null ; }
2019-08-21 05:35:30 +12:00
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-05-09 18:54:39 +12:00
if ( ! result ) { result = '' ; }
2019-08-21 05:35:30 +12:00
return result ; }
2019-08-12 09:18:05 +12:00
let resolve = function ( target , prefix = 'param' , data = { } ) { if ( ! target ) { return function ( ) { } ; }
2019-08-21 05:35:30 +12:00
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-08-08 08:35:20 +12:00
if ( loading ) { loaderId = alerts . add ( { text : loading , class : '' } , 0 ) ; }
2019-05-12 23:20:51 +12:00
let method = container . path ( scope + '.' + action ) ; if ( ! method ) { throw new Error ( 'Method "' + scope + '.' + action + '" not found' ) ; }
2019-08-21 16:37:08 +12:00
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-08-14 09:07:41 +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 ) , { } ) ) ; }
2019-08-13 02:19:54 +12:00
container . set ( 'serviceData' , null , true , true ) ; container . set ( 'serviceForm' , null , true , true ) ; element . $lsSkip = false ; view . render ( element ) ; } , function ( exception ) { if ( loaderId !== null ) { alerts . remove ( loaderId ) ; }
2019-08-07 22:46:51 +12:00
if ( ! element ) { return ; }
2019-08-08 01:02:14 +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 ) , { } ) ) ; }
2019-08-07 22:46:51 +12:00
element . $lsSkip = false ; view . render ( element ) ; } ) ; } ; let events = event . trim ( ) . split ( ',' ) ; for ( let y = 0 ; y < events . length ; y ++ ) { if ( '' === events [ y ] ) { continue ; }
2019-05-23 09:03:37 +12:00
switch ( events [ y ] . trim ( ) ) { case 'load' : exec ( ) ; break ; case 'none' : break ; case 'click' : case 'change' : case 'keypress' : case 'keydown' : case 'keyup' : case 'input' : case 'submit' : element . addEventListener ( events [ y ] , exec ) ; break ; default : document . addEventListener ( events [ y ] , exec ) ; }
2019-05-12 23:20:51 +12:00
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' ) ; }
2019-05-09 20:01:51 +12:00
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 ) { }
2019-08-22 17:56:25 +12:00
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 ) ; }
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 ) ; }
2019-08-22 07:22:48 +12:00
clone . querySelector ( 'input' ) . focus ( ) ; Array . prototype . slice . call ( clone . querySelectorAll ( '[data-remove]' ) ) . map ( function ( obj ) { obj . addEventListener ( 'click' , function ( ) { clone . parentNode . removeChild ( clone ) ; obj . scrollIntoView ( { behavior : 'smooth' } ) ; } ) ; } ) ; Array . prototype . slice . call ( clone . querySelectorAll ( '[data-up]' ) ) . map ( function ( obj ) { obj . addEventListener ( 'click' , function ( ) { if ( clone . previousElementSibling ) { clone . parentNode . insertBefore ( clone , clone . previousElementSibling ) ; obj . scrollIntoView ( { behavior : 'smooth' } ) ; } } ) ; } ) ; Array . prototype . slice . call ( clone . querySelectorAll ( '[data-down]' ) ) . map ( function ( obj ) { obj . addEventListener ( 'click' , function ( ) { if ( clone . nextElementSibling ) { clone . parentNode . insertBefore ( clone . nextElementSibling , clone ) ; obj . scrollIntoView ( { behavior : 'smooth' } ) ; } } ) ; } ) ; } ) ; element . parentNode . insertBefore ( button , element . nextSibling ) ; element . parentNode . removeChild ( element ) ; if ( first ) { button . click ( ) ; } } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-forms-code' , controller : function ( element ) { let div = document . createElement ( 'div' ) ; let pre = document . createElement ( 'pre' ) ; let code = document . createElement ( 'code' ) ; let copy = document . createElement ( 'i' ) ; div . appendChild ( pre ) ; pre . appendChild ( code ) ; element . parentNode . appendChild ( div ) ; element . parentNode . appendChild ( copy ) ; div . className = 'ide' ; pre . className = 'line-numbers' ; code . className = 'prism language-json' ; copy . className = 'icon-docs copy' ; copy . title = 'Copy to Clipboard' ; 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-08-21 23:00:32 +12:00
window . getSelection ( ) . removeAllRanges ( ) ; } ) ; let check = function ( ) { if ( ! element . value ) { return ; }
let value = JSON . stringify ( JSON . parse ( element . value ) , null , 4 ) ; code . innerHTML = value ; Prism . highlightElement ( code ) ; div . scrollTop = 0 ; }
2019-08-22 17:56:25 +12:00
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-08-08 08:35:20 +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 ) { window . getSelection ( ) . removeAllRanges ( ) ; var 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-05-12 23:20:51 +12:00
window . getSelection ( ) . removeAllRanges ( ) ; } ; 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 ; }
2019-05-09 18:54:39 +12:00
str . push ( ( v !== null && typeof v === "object" ) ? serialize ( v , k ) : encodeURIComponent ( k ) + "=" + encodeURIComponent ( v ) ) ; } }
return str . join ( "&" ) ; } ; let parse = function ( filter ) { if ( filter === '' ) { return null ; }
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" ) ; }
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 ] ; } } } }
2019-05-12 18:59:49 +12:00
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 { }
2019-05-09 18:54:39 +12:00
element . setAttribute ( 'data-event' , 'none' ) ; }
2019-08-22 17:56:25 +12:00
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 )
2019-05-09 18:54:39 +12:00
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 ; } }
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 )
2019-08-22 17:56:25 +12:00
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>' } ] } ) ; 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 ( ) ; }
2019-08-22 22:44:55 +12:00
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-list' ; add . type = 'text' ; add . className = 'add' ; tags . addEventListener ( 'click' , function ( ) { add . focus ( ) ; } ) ; add . addEventListener ( 'keydown' , function ( event ) { if ( ( ( event . key === "Enter" || event . key === " " ) ) && ( add . value . length > 0 ) ) { array . push ( add . value ) ; add . value = '' ; element . value = JSON . stringify ( array ) ; check ( ) ; event . preventDefault ( ) ; }
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 ) || [ ] ; }
2019-08-24 17:00:40 +12:00
catch ( error ) { array = [ ] ; }
2019-08-22 22:44:55 +12:00
if ( ! Array . isArray ( array ) ) { array = [ ] ; }
2019-08-24 17:00:40 +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 ) ; }
2019-08-22 22:44:55 +12:00
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 ; }
2019-08-22 17:56:25 +12:00
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 ; } }
2019-05-09 18:54:39 +12:00
if ( - 1 < rtlStock . indexOf ( '^' + firstChar + '^' ) ) { direction = 'rtl' ; align = 'right' ; }
2019-08-22 17:56:25 +12:00
element . style . direction = direction ; element . style . textAlign = align ; } ; element . addEventListener ( 'keyup' , setDirection ) ; element . addEventListener ( 'change' , setDirection ) ; element . addEventListener ( 'cut' , setDirection ) ; element . addEventListener ( 'paste' , setDirection ) ; element . addEventListener ( 'drop' , setDirection ) ; setDirection ( ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . container . get ( 'view' ) . add ( { selector : 'data-forms-text-resize' , controller : function ( element , window ) { function resize ( ) { var scrollLeft = window . pageXOffset || ( window . document . documentElement || window . document . body . parentNode || window . document . body ) . scrollLeft ; var scrollTop = window . pageYOffset || ( window . document . documentElement || window . document . body . parentNode || window . document . body ) . scrollTop ; var offset = element . offsetHeight - element . clientHeight ; element . style . height = 'auto' ; element . style . height = element . scrollHeight + offset + 'px' ; window . scrollTo ( scrollLeft , scrollTop ) ; }
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' ; }
2019-08-19 16:37:58 +12:00
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 ] ; }
2019-08-24 17:00:40 +12:00
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' ) ; }
2019-05-09 18:54:39 +12:00
else { input . disabled = false ; upload . classList . remove ( 'disabled' ) ; }
2019-08-19 16:37:58 +12:00
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 ; }
2019-05-09 18:54:39 +12:00
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-08-22 17:56:25 +12:00
upload . appendChild ( input ) ; render ( output ) ; } } ) ; } ) ( window ) ; ( function ( window ) { "use strict" ; window . ls . view . add ( { selector : 'data-general-oauth' , controller : function ( element , env , expression ) { let provider = expression . parse ( element . dataset [ 'authOauth' ] || '' ) ; let success = expression . parse ( element . dataset [ 'success' ] || '' ) ; let failure = expression . parse ( element . dataset [ 'failure' ] || '' ) ; element . href = env . API + '/oauth/' + provider + '?project=' + env . PROJECT
2019-08-06 19:11:53 +12:00
+ '&success=' + encodeURIComponent ( success )
2019-08-22 07:22:48 +12:00
+ '&failure=' + encodeURIComponent ( failure ) ; } } ) ; } ) ( 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 ) { element . addEventListener ( 'submit' , function ( event ) { event . preventDefault ( ) ; 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 ) { window . location . href = '/console?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 ; }
if ( element . value === router . params . project ) { return ; }
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 ; }
2019-08-15 01:50:40 +12:00
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 ; }
2019-08-14 09:07:41 +12:00
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 ] ) ; }
2019-08-21 07:21:24 +12:00
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' ) ; }
2019-05-09 18:54:39 +12:00
selected = i ; }
2019-06-09 15:44:20 +12:00
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 } ) ) ; } ) ; }
2019-08-25 18:07:04 +12:00
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 ) ; } } ) ; }
2019-06-09 15:44:20 +12:00
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 ) ; } ) ; }
2019-05-13 08:27:33 +12:00
let open = function ( ) { document . documentElement . classList . add ( 'modal-open' ) ; document . dispatchEvent ( new CustomEvent ( 'modal-open' , { bubbles : false , cancelable : true } ) ) ; element . classList . add ( 'open' ) ; element . classList . remove ( 'close' ) ; } ; let 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-06-09 15:44:20 +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 ) ; }
2019-08-31 11:41:33 +12:00
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 ) ; }
2019-05-09 18:54:39 +12:00
if ( def === 'close' ) { element . classList . add ( 'close' ) ; element . classList . remove ( 'open' ) ; }
else { element . classList . add ( 'open' ) ; element . classList . remove ( 'close' ) ; }
button . addEventListener ( 'click' , function ( ) { element . classList . toggle ( 'open' ) ; element . classList . toggle ( 'close' ) ; } ) ; if ( hover && ! isTouch ( ) ) { element . addEventListener ( 'mouseover' , function ( ) { element . classList . add ( 'open' ) ; element . classList . remove ( 'close' ) ; } ) ; element . addEventListener ( 'mouseout' , function ( ) { element . classList . add ( 'close' ) ; element . classList . remove ( 'open' ) ; } ) ; }
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 ; } }
2019-08-09 18:28:16 +12:00
return null ; } ; if ( blur ) { button . addEventListener ( 'blur' , closeDelay ) ; }
2019-08-31 11:47:33 +12:00
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 ) ; } } ) ; }
2019-08-09 18:28:16 +12:00
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-08-22 17:56:25 +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 ; } }
2019-08-24 17:00:40 +12:00
var setTab = function ( index ) { var tabState = expression . parse ( element . children [ index ] . dataset [ 'state' ] || '' ) ; var url = '' ; if ( ( tabState !== '' ) && ( tabState !== window . location . pathname + window . location . search ) ) { var parser = document . createElement ( 'a' ) ; parser . href = tabState ; url = ( ! init ) ? parser . pathname + window . location . search : tabState ; if ( position != index ) { window . history . pushState ( { } , '' , url ) ; router . reset ( ) ; } }
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 ) ;