Skip to content

Commit ea03a14

Browse files
committed
release 0.2.6
1 parent 4602609 commit ea03a14

18 files changed

+1915
-156
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#### The de-facto solution to flexible routing with nested views
44
---
5-
**[Download 0.2.5](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|**
5+
**[Download 0.2.6](http://angular-ui.github.io/ui-router/release/angular-ui-router.js)** (or **[Minified](http://angular-ui.github.io/ui-router/release/angular-ui-router.min.js)**) **|**
66
**[Learn](#resources) |**
77
**[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router) |**
88
**[Get Help](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |**

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-ui-router",
3-
"version": "0.2.5",
3+
"version": "0.2.6",
44
"main": "./release/angular-ui-router.js",
55
"dependencies": {
66
"angular": ">= 1.1.5"

component.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-ui-router",
3-
"version": "0.2.5",
3+
"version": "0.2.6",
44
"description": "State-based routing for AngularJS",
55
"keywords": [
66
"angular",

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "angular-ui-router",
33
"description": "State-based routing for AngularJS",
4-
"version": "0.2.5",
4+
"version": "0.2.6",
55
"homepage": "http://angular-ui.github.com/",
66
"contributors": [
77
{
@@ -52,7 +52,7 @@
5252
"karma-chrome-launcher": "~0.1.0",
5353
"karma-html2js-preprocessor": "~0.1.0",
5454
"karma-jasmine": "~0.1.3",
55-
"karma-requirejs": "~0.1.0",
55+
"karma-requirejs": "~0.2.0",
5656
"karma-script-launcher": "~0.1.0",
5757
"karma-coffee-preprocessor": "~0.1.0",
5858
"karma": "~0.10.4",

release/angular-ui-router.js

+141-57
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* State-based routing for AngularJS
3-
* @version v0.2.5
3+
* @version v0.2.6
44
* @link http://angular-ui.github.com/
55
* @license MIT License, http://www.opensource.org/licenses/MIT
66
*/
@@ -57,6 +57,24 @@ function ancestors(first, second) {
5757
return path;
5858
}
5959

60+
/**
61+
* IE8-safe wrapper for `Object.keys()`.
62+
*
63+
* @param {Object} object A JavaScript object.
64+
* @return {Array} Returns the keys of the object as an array.
65+
*/
66+
function keys(object) {
67+
if (Object.keys) {
68+
return Object.keys(object);
69+
}
70+
var result = [];
71+
72+
angular.forEach(object, function(val, key) {
73+
result.push(key);
74+
});
75+
return result;
76+
}
77+
6078
/**
6179
* IE8-safe wrapper for `Array.prototype.indexOf()`.
6280
*
@@ -104,6 +122,61 @@ function inheritParams(currentParams, newParams, $current, $to) {
104122
return extend({}, inherited, newParams);
105123
}
106124

125+
/**
126+
* Normalizes a set of values to string or `null`, filtering them by a list of keys.
127+
*
128+
* @param {Array} keys The list of keys to normalize/return.
129+
* @param {Object} values An object hash of values to normalize.
130+
* @return {Object} Returns an object hash of normalized string values.
131+
*/
132+
function normalize(keys, values) {
133+
var normalized = {};
134+
135+
forEach(keys, function (name) {
136+
var value = values[name];
137+
normalized[name] = (value != null) ? String(value) : null;
138+
});
139+
return normalized;
140+
}
141+
142+
/**
143+
* Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
144+
*
145+
* @param {Object} a The first object.
146+
* @param {Object} b The second object.
147+
* @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
148+
* it defaults to the list of keys in `a`.
149+
* @return {Boolean} Returns `true` if the keys match, otherwise `false`.
150+
*/
151+
function equalForKeys(a, b, keys) {
152+
if (!keys) {
153+
keys = [];
154+
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
155+
}
156+
157+
for (var i=0; i<keys.length; i++) {
158+
var k = keys[i];
159+
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
160+
}
161+
return true;
162+
}
163+
164+
/**
165+
* Returns the subset of an object, based on a list of keys.
166+
*
167+
* @param {Array} keys
168+
* @param {Object} values
169+
* @return {Boolean} Returns a subset of `values`.
170+
*/
171+
function filterByKeys(keys, values) {
172+
var filtered = {};
173+
174+
forEach(keys, function (name) {
175+
filtered[name] = values[name];
176+
});
177+
return filtered;
178+
}
179+
107180
angular.module('ui.router.util', ['ng']);
108181
angular.module('ui.router.router', ['ui.router.util']);
109182
angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
@@ -799,7 +872,7 @@ angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
799872
$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider'];
800873
function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) {
801874

802-
var root, states = {}, $state, queue = {};
875+
var root, states = {}, $state, queue = {}, abstractKey = 'abstract';
803876

804877
// Builds state properties from definition passed to registerState()
805878
var stateBuilder = {
@@ -976,10 +1049,10 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
9761049
states[name] = state;
9771050

9781051
// Register the state in the global state list and with $urlRouter if necessary.
979-
if (!state['abstract'] && state.url) {
1052+
if (!state[abstractKey] && state.url) {
9801053
$urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
9811054
if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
982-
$state.transitionTo(state, $match, false);
1055+
$state.transitionTo(state, $match, { location: false });
9831056
}
9841057
}]);
9851058
}
@@ -1116,7 +1189,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
11161189
throw new Error("No such state '" + to + "'");
11171190
}
11181191
}
1119-
if (toState['abstract']) throw new Error("Cannot transition to abstract state '" + to + "'");
1192+
if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
11201193
if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
11211194
to = toState;
11221195

@@ -1286,13 +1359,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
12861359
return url;
12871360
};
12881361

1289-
$state.get = function (stateOrName) {
1362+
$state.get = function (stateOrName, context) {
12901363
if (!isDefined(stateOrName)) {
12911364
var list = [];
12921365
forEach(states, function(state) { list.push(state.self); });
12931366
return list;
12941367
}
1295-
var state = findState(stateOrName);
1368+
var state = findState(stateOrName, context);
12961369
return (state && state.self) ? state.self : null;
12971370
};
12981371

@@ -1344,39 +1417,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
13441417
return $state;
13451418
}
13461419

1347-
function normalize(keys, values) {
1348-
var normalized = {};
1349-
1350-
forEach(keys, function (name) {
1351-
var value = values[name];
1352-
normalized[name] = (value != null) ? String(value) : null;
1353-
});
1354-
return normalized;
1355-
}
1356-
1357-
function equalForKeys(a, b, keys) {
1358-
// If keys not provided, assume keys from object 'a'
1359-
if (!keys) {
1360-
keys = [];
1361-
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
1362-
}
1363-
1364-
for (var i=0; i<keys.length; i++) {
1365-
var k = keys[i];
1366-
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
1367-
}
1368-
return true;
1369-
}
1370-
1371-
function filterByKeys(keys, values) {
1372-
var filtered = {};
1373-
1374-
forEach(keys, function (name) {
1375-
filtered[name] = values[name];
1376-
});
1377-
return filtered;
1378-
}
1379-
13801420
function shouldTriggerReload(to, from, locals, options) {
13811421
if ( to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false)) ) {
13821422
return true;
@@ -1420,9 +1460,7 @@ angular.module('ui.router.state').provider('$view', $ViewProvider);
14201460

14211461
$ViewDirective.$inject = ['$state', '$compile', '$controller', '$injector', '$anchorScroll'];
14221462
function $ViewDirective( $state, $compile, $controller, $injector, $anchorScroll) {
1423-
// TODO: Change to $injector.has() when we version bump to Angular 1.1.5.
1424-
// See: https://github.com/angular/angular.js/blob/master/CHANGELOG.md#115-triangle-squarification-2013-05-22
1425-
var $animator; try { $animator = $injector.get('$animator'); } catch (e) { /* do nothing */ }
1463+
var $animator = $injector.has('$animator') ? $injector.get('$animator') : null;
14261464
var viewIsUpdating = false;
14271465

14281466
var directive = {
@@ -1435,7 +1473,7 @@ function $ViewDirective( $state, $compile, $controller, $injector, $an
14351473
var viewScope, viewLocals,
14361474
name = attr[directive.name] || attr.name || '',
14371475
onloadExp = attr.onload || '',
1438-
animate = isDefined($animator) && $animator(scope, attr),
1476+
animate = $animator && $animator(scope, attr),
14391477
initialView = transclude(scope);
14401478

14411479
// Returns a set of DOM manipulation functions based on whether animation
@@ -1543,22 +1581,25 @@ function parseStateRef(ref) {
15431581
return { state: parsed[1], paramExpr: parsed[3] || null };
15441582
}
15451583

1546-
$StateRefDirective.$inject = ['$state'];
1547-
function $StateRefDirective($state) {
1584+
function stateContext(el) {
1585+
var stateData = el.parent().inheritedData('$uiView');
1586+
1587+
if (stateData && stateData.state && stateData.state.name) {
1588+
return stateData.state;
1589+
}
1590+
}
1591+
1592+
$StateRefDirective.$inject = ['$state', '$timeout'];
1593+
function $StateRefDirective($state, $timeout) {
15481594
return {
15491595
restrict: 'A',
1550-
link: function(scope, element, attrs) {
1596+
require: '?^uiSrefActive',
1597+
link: function(scope, element, attrs, uiSrefActive) {
15511598
var ref = parseStateRef(attrs.uiSref);
1552-
var params = null, url = null, base = $state.$current;
1599+
var params = null, url = null, base = stateContext(element) || $state.$current;
15531600
var isForm = element[0].nodeName === "FORM";
15541601
var attr = isForm ? "action" : "href", nav = true;
15551602

1556-
var stateData = element.parent().inheritedData('$uiView');
1557-
1558-
if (stateData && stateData.state && stateData.state.name) {
1559-
base = stateData.state;
1560-
}
1561-
15621603
var update = function(newVal) {
15631604
if (newVal) params = newVal;
15641605
if (!nav) return;
@@ -1570,6 +1611,9 @@ function $StateRefDirective($state) {
15701611
return false;
15711612
}
15721613
element[0][attr] = newHref;
1614+
if (uiSrefActive) {
1615+
uiSrefActive.$$setStateInfo(ref.state, params);
1616+
}
15731617
};
15741618

15751619
if (ref.paramExpr) {
@@ -1586,8 +1630,11 @@ function $StateRefDirective($state) {
15861630
var button = e.which || e.button;
15871631

15881632
if ((button === 0 || button == 1) && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
1589-
scope.$evalAsync(function() {
1590-
$state.go(ref.state, params, { relative: base });
1633+
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
1634+
$timeout(function() {
1635+
scope.$apply(function() {
1636+
$state.go(ref.state, params, { relative: base });
1637+
});
15911638
});
15921639
e.preventDefault();
15931640
}
@@ -1596,7 +1643,44 @@ function $StateRefDirective($state) {
15961643
};
15971644
}
15981645

1599-
angular.module('ui.router.state').directive('uiSref', $StateRefDirective);
1646+
$StateActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
1647+
function $StateActiveDirective($state, $stateParams, $interpolate) {
1648+
return {
1649+
restrict: "A",
1650+
controller: function($scope, $element, $attrs) {
1651+
var state, params, activeClass;
1652+
1653+
// There probably isn't much point in $observing this
1654+
activeClass = $interpolate($attrs.uiSrefActive || '', false)($scope);
1655+
1656+
// Allow uiSref to communicate with uiSrefActive
1657+
this.$$setStateInfo = function(newState, newParams) {
1658+
state = $state.get(newState, stateContext($element));
1659+
params = newParams;
1660+
update();
1661+
};
1662+
1663+
$scope.$on('$stateChangeSuccess', update);
1664+
1665+
// Update route state
1666+
function update() {
1667+
if ($state.$current.self === state && matchesParams()) {
1668+
$element.addClass(activeClass);
1669+
} else {
1670+
$element.removeClass(activeClass);
1671+
}
1672+
}
1673+
1674+
function matchesParams() {
1675+
return !params || equalForKeys(params, $stateParams);
1676+
}
1677+
}
1678+
};
1679+
}
1680+
1681+
angular.module('ui.router.state')
1682+
.directive('uiSref', $StateRefDirective)
1683+
.directive('uiSrefActive', $StateActiveDirective);
16001684

16011685
$RouteProvider.$inject = ['$stateProvider', '$urlRouterProvider'];
16021686
function $RouteProvider( $stateProvider, $urlRouterProvider) {

release/angular-ui-router.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)