@@ -9,8 +9,8 @@ import { ng as angular } from "../../angular";
9
9
import { IAugmentedJQuery , ITimeoutService , IScope , IInterpolateService } from "angular" ;
10
10
11
11
import {
12
- Obj , extend , forEach , toJson , tail , isString , isObject , parse , noop ,
13
- PathNode , StateOrName , StateService , TransitionService , State , UIRouter
12
+ Obj , extend , forEach , tail , isString , isObject , parse , noop , unnestR , identity , uniqR , inArray , removeFrom ,
13
+ RawParams , PathNode , StateOrName , StateService , TransitionService , StateDeclaration , UIRouter
14
14
} from "ui-router-core" ;
15
15
import { UIViewData } from "./viewDirective" ;
16
16
@@ -354,13 +354,15 @@ let uiState = ['$uiRouter', '$timeout',
354
354
* to both the <div> and <a> elements. It is important to note that the state
355
355
* names/globs passed to ui-sref-active shadow the state provided by ui-sref.
356
356
*/
357
- let uiSrefActive = [ '$state' , '$stateParams' , '$interpolate' , '$transitions' , '$ uiRouter',
358
- function $StateRefActiveDirective ( $state : StateService , $stateParams : Obj , $interpolate : IInterpolateService , $transitions : TransitionService , $ uiRouter : UIRouter ) {
357
+ let uiSrefActive = [ '$state' , '$stateParams' , '$interpolate' , '$uiRouter' ,
358
+ function $StateRefActiveDirective ( $state : StateService , $stateParams : Obj , $interpolate : IInterpolateService , $uiRouter : UIRouter ) {
359
359
return {
360
360
restrict : "A" ,
361
- controller : [ '$scope' , '$element' , '$attrs' , '$timeout' ,
362
- function ( $scope : IScope , $element : IAugmentedJQuery , $attrs : any , $timeout : ITimeoutService ) {
363
- var states : any [ ] = [ ] , activeClasses : Obj = { } , activeEqClass : string , uiSrefActive : any ;
361
+ controller : [ '$scope' , '$element' , '$attrs' ,
362
+ function ( $scope : IScope , $element : IAugmentedJQuery , $attrs : any ) {
363
+ var states : StateData [ ] = [ ] ,
364
+ activeEqClass : string ,
365
+ uiSrefActive : any ;
364
366
365
367
// There probably isn't much point in $observing this
366
368
// uiSrefActive and uiSrefActiveEq share the same directive object with some
@@ -400,89 +402,56 @@ let uiSrefActive = ['$state', '$stateParams', '$interpolate', '$transitions', '$
400
402
}
401
403
402
404
$scope . $on ( '$stateChangeSuccess' , update ) ;
403
- $scope . $on ( '$destroy' , < any > $transitions . onStart ( { } , updateAfterTransition ) ) ;
405
+ $scope . $on ( '$destroy' , < any > $uiRouter . transitionService . onStart ( { } , updateAfterTransition ) ) ;
404
406
if ( $uiRouter . globals . transition ) {
405
407
updateAfterTransition ( $uiRouter . globals . transition ) ;
406
408
}
407
409
408
410
function addState ( stateName : string , stateParams : Obj , activeClass : string ) {
409
411
var state = $state . get ( stateName , stateContext ( $element ) ) ;
410
- var stateHash = createStateHash ( stateName , stateParams ) ;
411
412
412
413
var stateInfo = {
413
414
state : state || { name : stateName } ,
414
415
params : stateParams ,
415
- hash : stateHash
416
+ activeClass : activeClass
416
417
} ;
417
418
418
419
states . push ( stateInfo ) ;
419
- activeClasses [ stateHash ] = activeClass ;
420
420
421
421
return function removeState ( ) {
422
- var idx = states . indexOf ( stateInfo ) ;
423
- if ( idx !== - 1 ) states . splice ( idx , 1 ) ;
422
+ removeFrom ( states ) ( stateInfo ) ;
424
423
}
425
424
}
426
425
427
- /**
428
- * @param {string } state
429
- * @param {Object|string } [params]
430
- * @return {string }
431
- */
432
- function createStateHash ( state : string , params : ( Obj | string ) ) {
433
- if ( ! isString ( state ) ) {
434
- throw new Error ( 'state should be a string' ) ;
435
- }
436
- if ( isObject ( params ) ) {
437
- return state + toJson ( params ) ;
438
- }
439
- params = $scope . $eval ( params as string ) ;
440
- if ( isObject ( params ) ) {
441
- return state + toJson ( params ) ;
442
- }
443
- return state ;
444
- }
445
-
446
426
// Update route state
447
427
function update ( ) {
448
- for ( var i = 0 ; i < states . length ; i ++ ) {
449
- if ( anyMatch ( states [ i ] . state , states [ i ] . params ) ) {
450
- addClass ( $element , activeClasses [ states [ i ] . hash ] ) ;
451
- } else {
452
- removeClass ( $element , activeClasses [ states [ i ] . hash ] ) ;
453
- }
454
-
455
- if ( exactMatch ( states [ i ] . state , states [ i ] . params ) ) {
456
- addClass ( $element , activeEqClass ) ;
457
- } else {
458
- removeClass ( $element , activeEqClass ) ;
459
- }
460
- }
461
- }
462
-
463
- function addClass ( el : IAugmentedJQuery , className : string ) {
464
- $scope . $evalAsync ( ( ) => el . addClass ( className ) ) ;
465
- }
466
-
467
- function removeClass ( el : IAugmentedJQuery , className : string ) {
468
- $scope . $evalAsync ( ( ) => el . removeClass ( className ) ) ;
469
- }
470
-
471
- function anyMatch ( state : State , params : Obj ) {
472
- return $state . includes ( state . name , params ) ;
473
- }
474
-
475
- function exactMatch ( state : State , params : Obj ) {
476
- return $state . is ( state . name , params ) ;
428
+ const splitClasses = str =>
429
+ str . split ( / \s / ) . filter ( identity ) ;
430
+ const getClasses = ( stateList : StateData [ ] ) =>
431
+ stateList . map ( x => x . activeClass ) . map ( splitClasses ) . reduce ( unnestR , [ ] ) ;
432
+
433
+ let allClasses = getClasses ( states ) . concat ( splitClasses ( activeEqClass ) ) . reduce ( uniqR , [ ] ) ;
434
+ let fuzzyClasses = getClasses ( states . filter ( x => $state . includes ( x . state . name , x . params ) ) ) ;
435
+ let exactlyMatchesAny = ! ! states . filter ( x => $state . is ( x . state . name , x . params ) ) . length ;
436
+ let exactClasses = exactlyMatchesAny ? splitClasses ( activeEqClass ) : [ ] ;
437
+
438
+ let addClasses = fuzzyClasses . concat ( exactClasses ) . reduce ( uniqR , [ ] ) ;
439
+ let removeClasses = allClasses . filter ( cls => ! inArray ( addClasses , cls ) ) ;
440
+
441
+ $scope . $evalAsync ( ( ) => {
442
+ addClasses . forEach ( className => $element . addClass ( className ) ) ;
443
+ removeClasses . forEach ( className => $element . removeClass ( className ) ) ;
444
+ } ) ;
477
445
}
478
446
479
447
update ( ) ;
480
448
} ]
481
449
} ;
482
450
} ] ;
483
451
484
- interface Def { uiState : string ; href : string ; uiStateParams : Obj ; uiStateOpts : any ;
485
- }
452
+ interface Def { uiState : string ; href : string ; uiStateParams : Obj ; uiStateOpts : any ; }
453
+ interface StateData { state : StateDeclaration ; params : RawParams ; activeClass : string ; }
454
+
486
455
angular . module ( 'ui.router.state' )
487
456
. directive ( 'uiSref' , uiSref )
488
457
. directive ( 'uiSrefActive' , uiSrefActive )
0 commit comments