import RouteRecognizer from '../ivy-route-recognizer/route-recognizer' ; import { Route } from '../ivy-route-recognizer/route-recognizer/dsl' ; import { isNode } from '../utils/utils' ; import { EventContract } from '../tsaction/event_contract' ; const ROUTER_LOCAL_NAME = 'pages-router' ; function getCurrentLocation ( ) { return window . location . pathname + window . location . search ; } /**
 * A lightweight custom element based router for loading 'pages'.
 */ export function registerRouterElement ( doc , ceRegistry , initialPath , routes , eventContract ? , onLoad ? ) { class RouterElement extends HTMLElement { private recognizer : RouteRecognizer ; private currentPageComponent = '' ; private childElement : Element ; private parentRouter : Element | null = null ; private depth = 0 ; private getMatchedRoute ( path ) { const match = this . recognizer . recognize ( path ) ; if ( match == null || match . length < this . depth ) { return { queryParams : { } , match : { handler : 'code-404' , params : { } , isDynamic : false , } } ; } return { queryParams : match . queryParams , match : match [ this . depth - 1 ] , } ; } private initRouteRecognizer ( ) { if ( this . recognizer == null ) { this . recognizer = new RouteRecognizer ( ) ; for ( const route of routes ) { if ( route instanceof Array ) { this . recognizer . add ( route ) ; } else { this . recognizer . add ( [ route ] ) ; } } } } private initRouter ( ) { this . childElement = this . firstElementChild ; for ( let el = this as HTMLElement ; el != null ; el = el . parentElement ) { if ( el . localName === ROUTER_LOCAL_NAME ) { if ( this . depth == 1 ) { this . parentRouter = el ; el [ 'childRouter' ] = this ; } this . depth ++ ; } } this . initRouteRecognizer ( ) ; } public navigate ( newPath ? ) { const path = newPath || getCurrentLocation ( ) ; const matchedRoute = this . getMatchedRoute ( path ) ; this . currentPageComponent = matchedRoute . match . handler as string ; while ( this . firstChild ) { this . removeChild ( this . firstChild ) ; } this . childElement = doc . createElement ( this . currentPageComponent ) ; this . insertAdjacentElement ( 'afterbegin' , this . childElement ) ; for ( const param of Object . keys ( matchedRoute . match . params ) ) { this . childElement [ param ] = matchedRoute . match . params [ param ] ; } this . childElement [ 'queryParams' ] = matchedRoute . queryParams ; if ( this [ 'childRouter' ] != null ) { this [ 'childRouter' ] . navigate ( newPath ) ; } } private routerCallback ( url ) { if ( url !== getCurrentLocation ( ) ) { window . history . pushState ( { } , '' , url ) ; this . navigate ( ) ; } } connectedCallback ( ) { this . initRouter ( ) ; if ( isNode ( ) ) { this . navigate ( initialPath ) ; } else { window . addEventListener ( 'popstate' , _evt => { this . navigate ( ) ; } ) ; if ( this . depth == 1 ) { eventContract ! . setRouterCallback ( this . routerCallback . bind ( this ) ) ; } } if ( onLoad ) { onLoad ( this ) ; } } disconnectedCallback ( ) { if ( this . parentRouter != null ) { this . parentRouter [ 'childRouter' ] = null ; } } } ceRegistry . define ( ROUTER_LOCAL_NAME , RouterElement ) ; }