Skip to content

Commit 805e69b

Browse files
release 0.2.15
1 parent b4a2d27 commit 805e69b

File tree

2 files changed

+70
-39
lines changed

2 files changed

+70
-39
lines changed

release/angular-ui-router.js

+68-37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* State-based routing for AngularJS
3-
* @version v0.2.14
3+
* @version v0.2.15
44
* @link http://angular-ui.github.com/
55
* @license MIT License, http://www.opensource.org/licenses/MIT
66
*/
@@ -1241,15 +1241,14 @@ function $UrlMatcherFactory() {
12411241

12421242
function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; }
12431243
function valFromString(val) { return val != null ? val.toString().replace(/%2F/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); }
12471244

12481245
var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
12491246
string: {
12501247
encode: valToString,
12511248
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"; },
12531252
pattern: /[^/]*/
12541253
},
12551254
int: {
@@ -1293,7 +1292,6 @@ function $UrlMatcherFactory() {
12931292
any: { // does not encode/decode
12941293
encode: angular.identity,
12951294
decode: angular.identity,
1296-
is: angular.identity,
12971295
equals: angular.equals,
12981296
pattern: /.*/
12991297
}
@@ -2002,7 +2000,8 @@ function $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {
20022000
if (evt && evt.defaultPrevented) return;
20032001
var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;
20042002
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;
20062005

20072006
function check(rule) {
20082007
var handled = rule($injector, $location);
@@ -3104,7 +3103,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
31043103
* have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd
31053104
* use this when you want to force a reload when *everything* is the same, including search params.
31063105
* 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.
31083107
*
31093108
* @returns {promise} A promise representing the state of the new transition. See
31103109
* {@link ui.router.state.$state#methods_go $state.go}.
@@ -3152,7 +3151,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
31523151

31533152
// Starting from the root of the path, keep all levels that haven't changed
31543153
var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];
3155-
var skipTriggerReloadCheck = false;
31563154

31573155
if (!options.reload) {
31583156
while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {
@@ -3170,8 +3168,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
31703168
throw new Error("No such reload state '" + (isString(options.reload) ? options.reload : options.reload.name) + "'");
31713169
}
31723170

3173-
skipTriggerReloadCheck = true;
3174-
31753171
while (state && state === fromPath[keep] && state !== reloadState) {
31763172
locals = toLocals[keep] = state.locals;
31773173
keep++;
@@ -3184,8 +3180,16 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
31843180
// TODO: We may not want to bump 'transition' if we're called from a location change
31853181
// that we've initiated ourselves, because we might accidentally abort a legitimate
31863182
// 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+
}
31893193
$state.transition = null;
31903194
return $q.when($state.current);
31913195
}
@@ -3540,39 +3544,66 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
35403544
})];
35413545
if (inherited) promises.push(inherited);
35423546

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+
}
35643576

35653577
// 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) {
35673579
return dst;
35683580
});
35693581
}
35703582

35713583
return $state;
35723584
}
35733585

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)))) {
35763607
return true;
35773608
}
35783609
}

0 commit comments

Comments
 (0)