@@ -519,24 +519,66 @@ function createElement(object) {
519519 return new Element ( object ) ;
520520}
521521class RouteEvent {
522- constructor ( instance , before_route , current_route , params = { } ) {
522+ constructor ( manager , instance , before_route , current_route , params = { } ) {
523+ this . manager = manager
523524 this . instance = instance ;
524525 this . current_route = current_route
525526 this . before_route = before_route
526527 this . params = params
527528 }
528529}
529530class Router {
530- constructor ( route_prefix = "/" ) {
531+ constructor (
532+ route_prefix = "/" ,
533+ ) {
531534 this . _route_prefix = route_prefix . replace ( / \/ + $ / , "" )
532- this . _before_handlers = [ ]
533- this . _after_handlers = [ ]
534- this . _current_path = null ; //this._get_current_path()
535535 this . _routes = [ ]
536+ this . _beforeHandlers = [ ]
537+ this . _afterHandlers = [ ]
538+ this . _current_path = null
539+ }
540+ get _getCurrentPath ( ) {
541+ return window . location . pathname . replace ( this . _route_prefix , "" ) || "/"
542+ }
543+ on ( path , handler ) {
544+ // path {xxx}
545+ // replace to like python (?P<xxx>*.+)
546+ var params = ( path . match ( / \{ ( ( \w + ) | ( \: ( u r l ) \: ) ) \} / g) || [ ] ) . map ( x => x . replaceAll ( "{" , "" ) . replaceAll ( "}" , "" ) . replaceAll ( ":" , "" ) )
547+ var regexp_path = path . replace ( / \{ \: ( u r l ) \: \} / g, "(.*)" ) . replace ( / \{ ( \w + ) \} / g, "([^/]*)" )
548+ var config = {
549+ raw_path : path ,
550+ path : new RegExp ( `^${ regexp_path } $` ) ,
551+ params : params ,
552+ handler
553+ }
554+ this . _routes . push ( config )
555+ // sort path length
556+ this . _routes . sort ( ( a , b ) => b . path . length - a . path . length )
557+ return this
558+ }
559+ beforeHandler ( handler ) {
560+ if ( handler == null ) this ;
561+ this . _beforeHandlers . push ( handler )
562+ return this
563+ }
564+ afterHandler ( handler ) {
565+ if ( handler == null ) this ;
566+ this . _afterHandlers . push ( handler )
567+ return this
568+ }
569+
570+ }
571+ class RouterManager {
572+ constructor (
573+ route_prefix = "/" ,
574+ ) {
575+ this . _routes = [
576+ new Router ( route_prefix )
577+ ]
536578 }
537579 init ( ) {
538580 window . addEventListener ( "popstate" , ( ) => {
539- this . _popstate_handler ( )
581+ this . _popstateHandler ( )
540582 } )
541583 window . addEventListener ( "click" , ( e ) => {
542584 if ( e . target . tagName == "A" ) {
@@ -545,86 +587,134 @@ class Router {
545587 if ( url . origin != window . location . origin ) return ;
546588 e . preventDefault ( )
547589 if ( url . pathname . startsWith ( this . _route_prefix ) ) {
548- this . _popstate_handler ( url . pathname )
590+ this . _popstateHandler ( url . pathname )
549591 }
550592 }
551593 } )
552- this . _popstate_handler ( )
553- }
554- page ( path ) {
555- this . _popstate_handler ( path )
594+ this . _popstateHandler ( )
556595 }
557- _get_current_path ( ) {
596+ get _getCurrentPath ( ) {
558597 return window . location . pathname
559598 }
560- async _popstate_handler ( path ) {
561- const new_path = ( path ?? this . _get_current_path ( ) ) . replace ( this . _route_prefix , "" ) || "/"
562- const old_path = this . _current_path
563- if ( old_path == new_path ) return ;
564- window . history . pushState ( null , '' , this . _route_prefix + new_path )
565- this . _current_path = new_path
566- this . _before_handlers . forEach ( handler => {
567- try {
568- handler ( new RouteEvent ( this , old_path , new_path ) )
569- } catch ( e ) {
570- console . log ( e )
599+ _popstateHandler ( path ) {
600+ path = path || this . _getCurrentPath
601+ const matchRoutes = [ ]
602+ for ( const router of this . _routes ) {
603+ if ( path . startsWith ( router . _route_prefix ) ) {
604+ matchRoutes . push ( router )
571605 }
606+ }
607+ if ( ! matchRoutes . length ) matchRoutes . push ( this . _routes [ 0 ] )
608+ const handlers = {
609+ before : [ ] ,
610+ route : [ ] ,
611+ after : [ ]
612+ } ;
613+ var router = null ;
614+ for ( const r of matchRoutes ) {
615+ let new_path = path . replace ( r . _route_prefix , "" ) || "/"
616+ var match_routes = r . _routes . filter ( x => x . path . test ( new_path ) )
617+ if ( match_routes . length ) {
618+ router = r
619+ break
620+ }
621+ }
622+ router = router || matchRoutes [ 0 ]
623+ const old_path = router . _current_path
624+ const new_path = path . replace ( router . _route_prefix , "" ) || "/"
625+ if ( new_path == router . _current_path ) return ;
626+ router . _current_path = new_path
627+ window . history . pushState ( null , '' , router . _route_prefix + new_path )
628+ for ( const handler of router . _beforeHandlers ) {
629+ handlers . before . push ( handler )
630+ }
631+
632+ // route
633+ for ( const route of router . _routes . filter ( x => x . path . test ( new_path ) ) ) {
634+ handlers . route . push ( route )
635+ }
636+ // after
637+ for ( const handler of router . _afterHandlers ) {
638+ handlers . after . push ( handler )
639+ }
640+ this . _run ( handlers , {
641+ manager : this ,
642+ router,
643+ old_path : old_path ,
644+ new_path : new_path ,
572645 } )
646+ }
647+ _run ( handlers = {
648+ before : [ ] ,
649+ route : [ ] ,
650+ after : [ ]
651+ } , options = {
652+ manager : this ,
653+ router : null ,
654+ old_path : null ,
655+ new_path : null ,
656+ } ) {
657+ var preHandle = (
658+ preHandlers
659+ ) => {
660+ preHandlers . forEach ( handler => {
661+ try {
662+ handler ( new RouteEvent (
663+ options . manager ,
664+ options . router ,
665+ options . old_path ,
666+ options . new_path ,
667+ ) )
668+ } catch ( e ) {
669+ console . error ( e )
670+ }
671+ } )
672+ }
673+ preHandle ( handlers . before )
573674 try {
574- // get route
575- var routes = this . _routes . filter ( x => x . path . test ( new_path ) )
576- if ( routes ) {
577- routes . forEach ( route => {
578- var params = route . path . exec ( new_path ) . slice ( 1 ) . reduce ( ( acc , cur , i ) => {
579- acc [ route . params [ i ] ] = cur
580- return acc
581- } , { } )
582- var handler = route ? route . handler : null
583- if ( handler ) {
584- try {
585- handler ( new RouteEvent ( this , old_path , new_path , params ) )
586- } catch ( e ) {
587- console . log ( e )
588- }
675+ handlers . route . forEach ( route => {
676+ var params = route . path . exec ( options . new_path ) . slice ( 1 ) . reduce ( ( acc , cur , i ) => {
677+ acc [ route . params [ i ] ] = cur
678+ return acc
679+ } , { } )
680+ var handler = route ? route . handler : null
681+ if ( handler ) {
682+ try {
683+ handler ( new RouteEvent (
684+ options . manager ,
685+ options . router ,
686+ options . old_path ,
687+ options . new_path ,
688+ params
689+ ) )
690+ } catch ( e ) {
691+ console . log ( e )
589692 }
590- } )
591-
592- }
693+ }
694+ } )
593695 } catch ( e ) {
594- console . log ( e )
696+ console . error ( e )
697+
595698 }
596- this . _after_handlers . forEach ( handler => {
597- try {
598- handler ( new RouteEvent ( this , old_path , new_path ) )
599- } catch ( e ) {
600- console . log ( e )
601- }
602- } )
699+ preHandle ( handlers . after )
700+ return true
603701 }
604702 on ( path , handler ) {
605- // path {xxx}
606- // replace to like python (?P<xxx>*.+)
607- var params = ( path . match ( / \{ ( ( \w + ) | ( \: ( u r l ) \: ) ) \} / g) || [ ] ) . map ( x => x . replaceAll ( "{" , "" ) . replaceAll ( "}" , "" ) . replaceAll ( ":" , "" ) )
608- var regexp_path = path . replace ( / \{ \: ( u r l ) \: \} / g, "(.*)" ) . replace ( / \{ ( \w + ) \} / g, "([^/]*)" )
609- var config = {
610- raw_path : path ,
611- path : new RegExp ( `^${ regexp_path } $` ) ,
612- params : params ,
613- handler
614- }
615- this . _routes . push ( config )
616- // sort path length
617- this . _routes . sort ( ( a , b ) => b . path . length - a . path . length )
703+ this . _routes [ 0 ] . on ( path , handler )
618704 return this
619705 }
620- before_handler ( handler ) {
621- if ( handler == null ) this ;
622- this . _before_handlers . push ( handler )
706+ beforeHandler ( handler ) {
707+ this . _routes [ 0 ] . beforeHandler ( handler )
623708 return this
624709 }
625- after_handler ( handler ) {
626- if ( handler == null ) this ;
627- this . _after_handlers . push ( handler )
710+ afterHandler ( handler ) {
711+ this . _routes [ 0 ] . afterHandler ( handler )
712+ return this
713+ }
714+ page ( path ) {
715+ this . _popstateHandler (
716+ this . _routes [ 0 ] . _route_prefix + path
717+ )
628718 return this
629719 }
630720}
@@ -1077,6 +1167,7 @@ export {
10771167 createElement ,
10781168 Configuration ,
10791169 Router ,
1170+ RouterManager ,
10801171 ElementManager ,
10811172 I18NManager ,
10821173 Style ,
0 commit comments