1
1
/**
2
2
* State-based routing for AngularJS
3
- * @version v0.3.1
3
+ * @version v0.3.2
4
4
* @link http://angular-ui.github.com/
5
5
* @license MIT License, http://www.opensource.org/licenses/MIT
6
6
*/
@@ -222,6 +222,11 @@ function map(collection, callback) {
222
222
return result ;
223
223
}
224
224
225
+ // issue #2676 #2889
226
+ function silenceUncaughtInPromise ( promise ) {
227
+ return promise . then ( undefined , function ( ) { } ) && promise ;
228
+ }
229
+
225
230
/**
226
231
* @ngdoc overview
227
232
* @name ui.router.util
@@ -1266,8 +1271,8 @@ function $UrlMatcherFactory() {
1266
1271
// If the slashes are simply URLEncoded, the browser can choose to pre-decode them,
1267
1272
// and bidirectional encoding/decoding fails.
1268
1273
// Tilde was chosen because it's not a RFC 3986 section 2.2 Reserved Character
1269
- function valToString ( val ) { return val != null ? val . toString ( ) . replace ( / ~ / g, "~~" ) . replace ( / \/ / g , " ~2F" ) : val ; }
1270
- function valFromString ( val ) { return val != null ? val . toString ( ) . replace ( / ~ 2 F / g, "/" ) . replace ( / ~ ~ / g , "~" ) : val ; }
1274
+ function valToString ( val ) { return val != null ? val . toString ( ) . replace ( / ( ~ | \/ ) / g, function ( m ) { return { '~' : '~~' , '/' : ' ~2F' } [ m ] ; } ) : val ; }
1275
+ function valFromString ( val ) { return val != null ? val . toString ( ) . replace ( / ( ~ ~ | ~ 2 F ) / g, function ( m ) { return { '~~' : '~' , '~2F' : '/' } [ m ] ; } ) : val ; }
1271
1276
1272
1277
var $types = { } , enqueue = true , typeQueue = [ ] , injector , defaultTypes = {
1273
1278
"string" : {
@@ -2901,10 +2906,12 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
2901
2906
$get . $inject = [ '$rootScope' , '$q' , '$view' , '$injector' , '$resolve' , '$stateParams' , '$urlRouter' , '$location' , '$urlMatcherFactory' ] ;
2902
2907
function $get ( $rootScope , $q , $view , $injector , $resolve , $stateParams , $urlRouter , $location , $urlMatcherFactory ) {
2903
2908
2904
- var TransitionSuperseded = $q . reject ( new Error ( 'transition superseded' ) ) ;
2905
- var TransitionPrevented = $q . reject ( new Error ( 'transition prevented' ) ) ;
2906
- var TransitionAborted = $q . reject ( new Error ( 'transition aborted' ) ) ;
2907
- var TransitionFailed = $q . reject ( new Error ( 'transition failed' ) ) ;
2909
+ var TransitionSupersededError = new Error ( 'transition superseded' ) ;
2910
+
2911
+ var TransitionSuperseded = silenceUncaughtInPromise ( $q . reject ( TransitionSupersededError ) ) ;
2912
+ var TransitionPrevented = silenceUncaughtInPromise ( $q . reject ( new Error ( 'transition prevented' ) ) ) ;
2913
+ var TransitionAborted = silenceUncaughtInPromise ( $q . reject ( new Error ( 'transition aborted' ) ) ) ;
2914
+ var TransitionFailed = silenceUncaughtInPromise ( $q . reject ( new Error ( 'transition failed' ) ) ) ;
2908
2915
2909
2916
// Handles the case where a state which is the target of a transition is not found, and the user
2910
2917
// can optionally retry or defer the transition
@@ -2960,7 +2967,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
2960
2967
var retryTransition = $state . transition = $q . when ( evt . retry ) ;
2961
2968
2962
2969
retryTransition . then ( function ( ) {
2963
- if ( retryTransition !== $state . transition ) return TransitionSuperseded ;
2970
+ if ( retryTransition !== $state . transition ) {
2971
+ $rootScope . $broadcast ( '$stateChangeCancel' , redirect . to , redirect . toParams , state , params ) ;
2972
+ return TransitionSuperseded ;
2973
+ }
2964
2974
redirect . options . $retry = true ;
2965
2975
return $state . transitionTo ( redirect . to , redirect . toParams , redirect . options ) ;
2966
2976
} , function ( ) {
@@ -3299,7 +3309,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3299
3309
var transition = $state . transition = resolved . then ( function ( ) {
3300
3310
var l , entering , exiting ;
3301
3311
3302
- if ( $state . transition !== transition ) return TransitionSuperseded ;
3312
+ if ( $state . transition !== transition ) {
3313
+ $rootScope . $broadcast ( '$stateChangeCancel' , to . self , toParams , from . self , fromParams ) ;
3314
+ return TransitionSuperseded ;
3315
+ }
3303
3316
3304
3317
// Exit 'from' states not kept
3305
3318
for ( l = fromPath . length - 1 ; l >= keep ; l -- ) {
@@ -3320,7 +3333,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3320
3333
}
3321
3334
3322
3335
// Run it again, to catch any transitions in callbacks
3323
- if ( $state . transition !== transition ) return TransitionSuperseded ;
3336
+ if ( $state . transition !== transition ) {
3337
+ $rootScope . $broadcast ( '$stateChangeCancel' , to . self , toParams , from . self , fromParams ) ;
3338
+ return TransitionSuperseded ;
3339
+ }
3324
3340
3325
3341
// Update globals in $state
3326
3342
$state . $current = to ;
@@ -3356,7 +3372,14 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3356
3372
3357
3373
return $state . current ;
3358
3374
} ) . then ( null , function ( error ) {
3359
- if ( $state . transition !== transition ) return TransitionSuperseded ;
3375
+ // propagate TransitionSuperseded error without emitting $stateChangeCancel
3376
+ // as it was already emitted in the success handler above
3377
+ if ( error === TransitionSupersededError ) return TransitionSuperseded ;
3378
+
3379
+ if ( $state . transition !== transition ) {
3380
+ $rootScope . $broadcast ( '$stateChangeCancel' , to . self , toParams , from . self , fromParams ) ;
3381
+ return TransitionSuperseded ;
3382
+ }
3360
3383
3361
3384
$state . transition = null ;
3362
3385
/**
@@ -3380,7 +3403,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3380
3403
evt = $rootScope . $broadcast ( '$stateChangeError' , to . self , toParams , from . self , fromParams , error ) ;
3381
3404
3382
3405
if ( ! evt . defaultPrevented ) {
3383
- $urlRouter . update ( ) ;
3406
+ $urlRouter . update ( ) ;
3384
3407
}
3385
3408
3386
3409
return $q . reject ( error ) ;
@@ -3495,7 +3518,17 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3495
3518
var state = findState ( stateOrName , options . relative ) ;
3496
3519
if ( ! isDefined ( state ) ) { return undefined ; }
3497
3520
if ( ! isDefined ( $state . $current . includes [ state . name ] ) ) { return false ; }
3498
- return params ? equalForKeys ( state . params . $$values ( params ) , $stateParams , objectKeys ( params ) ) : true ;
3521
+ if ( ! params ) { return true ; }
3522
+
3523
+ var keys = objectKeys ( params ) ;
3524
+ for ( var i = 0 ; i < keys . length ; i ++ ) {
3525
+ var key = keys [ i ] , paramDef = state . params [ key ] ;
3526
+ if ( paramDef && ! paramDef . type . equals ( $stateParams [ key ] , params [ key ] ) ) {
3527
+ return false ;
3528
+ }
3529
+ }
3530
+
3531
+ return true ;
3499
3532
} ;
3500
3533
3501
3534
@@ -4268,9 +4301,9 @@ function $StateRefDirective($state, $timeout) {
4268
4301
4269
4302
if ( ! type . clickable ) return ;
4270
4303
hookFn = clickHook ( element , $state , $timeout , type , function ( ) { return def ; } ) ;
4271
- element . bind ( "click" , hookFn ) ;
4304
+ element [ element . on ? 'on' : ' bind' ] ( "click" , hookFn ) ;
4272
4305
scope . $on ( '$destroy' , function ( ) {
4273
- element . unbind ( "click" , hookFn ) ;
4306
+ element [ element . off ? 'off' : ' unbind' ] ( "click" , hookFn ) ;
4274
4307
} ) ;
4275
4308
}
4276
4309
} ;
@@ -4320,9 +4353,9 @@ function $StateRefDynamicDirective($state, $timeout) {
4320
4353
4321
4354
if ( ! type . clickable ) return ;
4322
4355
hookFn = clickHook ( element , $state , $timeout , type , function ( ) { return def ; } ) ;
4323
- element . bind ( "click" , hookFn ) ;
4356
+ element [ element . on ? 'on' : ' bind' ] ( "click" , hookFn ) ;
4324
4357
scope . $on ( '$destroy' , function ( ) {
4325
- element . unbind ( "click" , hookFn ) ;
4358
+ element [ element . off ? 'off' : ' unbind' ] ( "click" , hookFn ) ;
4326
4359
} ) ;
4327
4360
}
4328
4361
} ;
0 commit comments