1
1
/**
2
2
* State-based routing for AngularJS
3
- * @version v0.2.14
3
+ * @version v0.2.15
4
4
* @link http://angular-ui.github.com/
5
5
* @license MIT License, http://www.opensource.org/licenses/MIT
6
6
*/
@@ -1241,15 +1241,14 @@ function $UrlMatcherFactory() {
1241
1241
1242
1242
function valToString ( val ) { return val != null ? val . toString ( ) . replace ( / \/ / g, "%2F" ) : val ; }
1243
1243
function valFromString ( val ) { return val != null ? val . toString ( ) . replace ( / % 2 F / g, "/" ) : val ; }
1244
- // TODO: in 1.0, make string .is() return false if value is undefined by default.
1245
- // function regexpMatches(val) { /*jshint validthis:true */ return isDefined(val) && this.pattern.test(val); }
1246
- function regexpMatches ( val ) { /*jshint validthis:true */ return this . pattern . test ( val ) ; }
1247
1244
1248
1245
var $types = { } , enqueue = true , typeQueue = [ ] , injector , defaultTypes = {
1249
1246
string : {
1250
1247
encode : valToString ,
1251
1248
decode : valFromString ,
1252
- is : function ( val ) { return typeof val === "string" ; } ,
1249
+ // TODO: in 1.0, make string .is() return false if value is undefined/null by default.
1250
+ // In 0.2.x, string params are optional by default for backwards compat
1251
+ is : function ( val ) { return val == null || ! isDefined ( val ) || typeof val === "string" ; } ,
1253
1252
pattern : / [ ^ / ] * /
1254
1253
} ,
1255
1254
int : {
@@ -1293,7 +1292,6 @@ function $UrlMatcherFactory() {
1293
1292
any : { // does not encode/decode
1294
1293
encode : angular . identity ,
1295
1294
decode : angular . identity ,
1296
- is : angular . identity ,
1297
1295
equals : angular . equals ,
1298
1296
pattern : / .* /
1299
1297
}
@@ -2002,7 +2000,8 @@ function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
2002
2000
if ( evt && evt . defaultPrevented ) return ;
2003
2001
var ignoreUpdate = lastPushedUrl && $location . url ( ) === lastPushedUrl ;
2004
2002
lastPushedUrl = undefined ;
2005
- if ( ignoreUpdate ) return true ;
2003
+ // TODO: Re-implement this in 1.0 for https://github.com/angular-ui/ui-router/issues/1573
2004
+ //if (ignoreUpdate) return true;
2006
2005
2007
2006
function check ( rule ) {
2008
2007
var handled = rule ( $injector , $location ) ;
@@ -3104,7 +3103,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3104
3103
* have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
3105
3104
* use this when you want to force a reload when *everything* is the same, including search params.
3106
3105
* if String, then will reload the state with the name given in reload, and any children.
3107
- * if Object, then a stateObj is expected, will reload the state found in stateObj, and any chhildren .
3106
+ * if Object, then a stateObj is expected, will reload the state found in stateObj, and any children .
3108
3107
*
3109
3108
* @returns {promise } A promise representing the state of the new transition. See
3110
3109
* {@link ui.router.state.$state#methods_go $state.go}.
@@ -3152,7 +3151,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3152
3151
3153
3152
// Starting from the root of the path, keep all levels that haven't changed
3154
3153
var keep = 0 , state = toPath [ keep ] , locals = root . locals , toLocals = [ ] ;
3155
- var skipTriggerReloadCheck = false ;
3156
3154
3157
3155
if ( ! options . reload ) {
3158
3156
while ( state && state === fromPath [ keep ] && state . ownParams . $$equals ( toParams , fromParams ) ) {
@@ -3170,8 +3168,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3170
3168
throw new Error ( "No such reload state '" + ( isString ( options . reload ) ? options . reload : options . reload . name ) + "'" ) ;
3171
3169
}
3172
3170
3173
- skipTriggerReloadCheck = true ;
3174
-
3175
3171
while ( state && state === fromPath [ keep ] && state !== reloadState ) {
3176
3172
locals = toLocals [ keep ] = state . locals ;
3177
3173
keep ++ ;
@@ -3184,8 +3180,16 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3184
3180
// TODO: We may not want to bump 'transition' if we're called from a location change
3185
3181
// that we've initiated ourselves, because we might accidentally abort a legitimate
3186
3182
// transition initiated from code?
3187
- if ( ! skipTriggerReloadCheck && shouldTriggerReload ( to , from , locals , options ) ) {
3188
- if ( to . self . reloadOnSearch !== false ) $urlRouter . update ( ) ;
3183
+ if ( shouldSkipReload ( to , toParams , from , fromParams , locals , options ) ) {
3184
+ if ( hash ) toParams [ '#' ] = hash ;
3185
+ $state . params = toParams ;
3186
+ copy ( $state . params , $stateParams ) ;
3187
+ if ( options . location && to . navigable && to . navigable . url ) {
3188
+ $urlRouter . push ( to . navigable . url , toParams , {
3189
+ $$avoidResync : true , replace : options . location === 'replace'
3190
+ } ) ;
3191
+ $urlRouter . update ( true ) ;
3192
+ }
3189
3193
$state . transition = null ;
3190
3194
return $q . when ( $state . current ) ;
3191
3195
}
@@ -3540,39 +3544,66 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
3540
3544
} ) ] ;
3541
3545
if ( inherited ) promises . push ( inherited ) ;
3542
3546
3543
- // Resolve template and dependencies for all views.
3544
- forEach ( state . views , function ( view , name ) {
3545
- var injectables = ( view . resolve && view . resolve !== state . resolve ? view . resolve : { } ) ;
3546
- injectables . $template = [ function ( ) {
3547
- return $view . load ( name , { view : view , locals : locals , params : $stateParams , notify : options . notify } ) || '' ;
3548
- } ] ;
3549
-
3550
- promises . push ( $resolve . resolve ( injectables , locals , dst . resolve , state ) . then ( function ( result ) {
3551
- // References to the controller (only instantiated at link time)
3552
- if ( isFunction ( view . controllerProvider ) || isArray ( view . controllerProvider ) ) {
3553
- var injectLocals = angular . extend ( { } , injectables , locals , result ) ;
3554
- result . $$controller = $injector . invoke ( view . controllerProvider , null , injectLocals ) ;
3555
- } else {
3556
- result . $$controller = view . controller ;
3557
- }
3558
- // Provide access to the state itself for internal use
3559
- result . $$state = state ;
3560
- result . $$controllerAs = view . controllerAs ;
3561
- dst [ name ] = result ;
3562
- } ) ) ;
3563
- } ) ;
3547
+ function resolveViews ( ) {
3548
+ var viewsPromises = [ ] ;
3549
+
3550
+ // Resolve template and dependencies for all views.
3551
+ forEach ( state . views , function ( view , name ) {
3552
+ var injectables = ( view . resolve && view . resolve !== state . resolve ? view . resolve : { } ) ;
3553
+ injectables . $template = [ function ( ) {
3554
+ return $view . load ( name , { view : view , locals : dst . globals , params : $stateParams , notify : options . notify } ) || '' ;
3555
+ } ] ;
3556
+
3557
+ viewsPromises . push ( $resolve . resolve ( injectables , dst . globals , dst . resolve , state ) . then ( function ( result ) {
3558
+ // References to the controller (only instantiated at link time)
3559
+ if ( isFunction ( view . controllerProvider ) || isArray ( view . controllerProvider ) ) {
3560
+ var injectLocals = angular . extend ( { } , injectables , dst . globals ) ;
3561
+ result . $$controller = $injector . invoke ( view . controllerProvider , null , injectLocals ) ;
3562
+ } else {
3563
+ result . $$controller = view . controller ;
3564
+ }
3565
+ // Provide access to the state itself for internal use
3566
+ result . $$state = state ;
3567
+ result . $$controllerAs = view . controllerAs ;
3568
+ dst [ name ] = result ;
3569
+ } ) ) ;
3570
+ } ) ;
3571
+
3572
+ return $q . all ( viewsPromises ) . then ( function ( ) {
3573
+ return dst . globals ;
3574
+ } ) ;
3575
+ }
3564
3576
3565
3577
// Wait for all the promises and then return the activation object
3566
- return $q . all ( promises ) . then ( function ( values ) {
3578
+ return $q . all ( promises ) . then ( resolveViews ) . then ( function ( values ) {
3567
3579
return dst ;
3568
3580
} ) ;
3569
3581
}
3570
3582
3571
3583
return $state ;
3572
3584
}
3573
3585
3574
- function shouldTriggerReload ( to , from , locals , options ) {
3575
- if ( to === from && ( ( locals === from . locals && ! options . reload ) || ( to . self . reloadOnSearch === false ) ) ) {
3586
+ function shouldSkipReload ( to , toParams , from , fromParams , locals , options ) {
3587
+ // Return true if there are no differences in non-search (path/object) params, false if there are differences
3588
+ function nonSearchParamsEqual ( fromAndToState , fromParams , toParams ) {
3589
+ // Identify whether all the parameters that differ between `fromParams` and `toParams` were search params.
3590
+ function notSearchParam ( key ) {
3591
+ return fromAndToState . params [ key ] . location != "search" ;
3592
+ }
3593
+ var nonQueryParamKeys = fromAndToState . params . $$keys ( ) . filter ( notSearchParam ) ;
3594
+ var nonQueryParams = pick . apply ( { } , [ fromAndToState . params ] . concat ( nonQueryParamKeys ) ) ;
3595
+ var nonQueryParamSet = new $$UMFP . ParamSet ( nonQueryParams ) ;
3596
+ return nonQueryParamSet . $$equals ( fromParams , toParams ) ;
3597
+ }
3598
+
3599
+ // If reload was not explicitly requested
3600
+ // and we're transitioning to the same state we're already in
3601
+ // and the locals didn't change
3602
+ // or they changed in a way that doesn't merit reloading
3603
+ // (reloadOnParams:false, or reloadOnSearch.false and only search params changed)
3604
+ // Then return true.
3605
+ if ( ! options . reload && to === from &&
3606
+ ( locals === from . locals || ( to . self . reloadOnSearch === false && nonSearchParamsEqual ( from , fromParams , toParams ) ) ) ) {
3576
3607
return true ;
3577
3608
}
3578
3609
}
0 commit comments