import { Location } from "./location" ; import { defer } from "./util" ; export interface HistoryDelegate { historyPoppedToLocationWithRestorationIdentifier ( location , restorationIdentifier ) : void ; } type HistoryMethod = ( state : any , title : string , url ? : string | null | undefined ) => void ; export class History { readonly delegate : HistoryDelegate ; started = false ; pageLoaded = false ; constructor ( delegate ) { this . delegate = delegate ; } start ( ) { if ( ! this . started ) { addEventListener ( "popstate" , this . onPopState , false ) ; addEventListener ( "load" , this . onPageLoad , false ) ; this . started = true ; } } stop ( ) { if ( this . started ) { removeEventListener ( "popstate" , this . onPopState , false ) ; removeEventListener ( "load" , this . onPageLoad , false ) ; this . started = false ; } } push ( location , restorationIdentifier ) { this . update ( history . pushState , location , restorationIdentifier ) ; } replace ( location , restorationIdentifier ) { this . update ( history . replaceState , location , restorationIdentifier ) ; } onPopState = ( event ) => { if ( ! this . shouldHandlePopState ( ) ) return ; if ( ! event . state ) return ; const { turbolinks } = event . state ; if ( ! turbolinks ) return ; const location = Location . currentLocation ; const { restorationIdentifier } = turbolinks ; this . delegate . historyPoppedToLocationWithRestorationIdentifier ( location , restorationIdentifier ) ; } ; onPageLoad = ( event ) => { defer ( ( ) => { this . pageLoaded = true ; } ) ; } ; shouldHandlePopState ( ) { return this . pageIsLoaded ( ) ; } pageIsLoaded ( ) { return this . pageLoaded || document . readyState == "complete" ; } update ( method , location , restorationIdentifier ) { const state = { turbolinks : { restorationIdentifier } } ; method . call ( history , state , "" , location . absoluteURL ) ; } }