Skip to content

Commit

Permalink
release 0.2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
nateabele committed Dec 6, 2013
1 parent 4602609 commit ea03a14
Show file tree
Hide file tree
Showing 18 changed files with 1,915 additions and 156 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#### The de-facto solution to flexible routing with nested views
---
**[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)**) **|**
**[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)**) **|**
**[Learn](#resources) |**
**[Discuss](https://groups.google.com/forum/#!categories/angular-ui/router) |**
**[Get Help](http://stackoverflow.com/questions/ask?tags=angularjs,angular-ui-router) |**
Expand Down
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-router",
"version": "0.2.5",
"version": "0.2.6",
"main": "./release/angular-ui-router.js",
"dependencies": {
"angular": ">= 1.1.5"
Expand Down
2 changes: 1 addition & 1 deletion component.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-router",
"version": "0.2.5",
"version": "0.2.6",
"description": "State-based routing for AngularJS",
"keywords": [
"angular",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "angular-ui-router",
"description": "State-based routing for AngularJS",
"version": "0.2.5",
"version": "0.2.6",
"homepage": "http://angular-ui.github.com/",
"contributors": [
{
Expand Down Expand Up @@ -52,7 +52,7 @@
"karma-chrome-launcher": "~0.1.0",
"karma-html2js-preprocessor": "~0.1.0",
"karma-jasmine": "~0.1.3",
"karma-requirejs": "~0.1.0",
"karma-requirejs": "~0.2.0",
"karma-script-launcher": "~0.1.0",
"karma-coffee-preprocessor": "~0.1.0",
"karma": "~0.10.4",
Expand Down
198 changes: 141 additions & 57 deletions release/angular-ui-router.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* State-based routing for AngularJS
* @version v0.2.5
* @version v0.2.6
* @link http://angular-ui.github.com/
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
Expand Down Expand Up @@ -57,6 +57,24 @@ function ancestors(first, second) {
return path;
}

/**
* IE8-safe wrapper for `Object.keys()`.
*
* @param {Object} object A JavaScript object.
* @return {Array} Returns the keys of the object as an array.
*/
function keys(object) {
if (Object.keys) {
return Object.keys(object);
}
var result = [];

angular.forEach(object, function(val, key) {
result.push(key);
});
return result;
}

/**
* IE8-safe wrapper for `Array.prototype.indexOf()`.
*
Expand Down Expand Up @@ -104,6 +122,61 @@ function inheritParams(currentParams, newParams, $current, $to) {
return extend({}, inherited, newParams);
}

/**
* Normalizes a set of values to string or `null`, filtering them by a list of keys.
*
* @param {Array} keys The list of keys to normalize/return.
* @param {Object} values An object hash of values to normalize.
* @return {Object} Returns an object hash of normalized string values.
*/
function normalize(keys, values) {
var normalized = {};

forEach(keys, function (name) {
var value = values[name];
normalized[name] = (value != null) ? String(value) : null;
});
return normalized;
}

/**
* Performs a non-strict comparison of the subset of two objects, defined by a list of keys.
*
* @param {Object} a The first object.
* @param {Object} b The second object.
* @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,
* it defaults to the list of keys in `a`.
* @return {Boolean} Returns `true` if the keys match, otherwise `false`.
*/
function equalForKeys(a, b, keys) {
if (!keys) {
keys = [];
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
}

for (var i=0; i<keys.length; i++) {
var k = keys[i];
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
}
return true;
}

/**
* Returns the subset of an object, based on a list of keys.
*
* @param {Array} keys
* @param {Object} values
* @return {Boolean} Returns a subset of `values`.
*/
function filterByKeys(keys, values) {
var filtered = {};

forEach(keys, function (name) {
filtered[name] = values[name];
});
return filtered;
}

angular.module('ui.router.util', ['ng']);
angular.module('ui.router.router', ['ui.router.util']);
angular.module('ui.router.state', ['ui.router.router', 'ui.router.util']);
Expand Down Expand Up @@ -799,7 +872,7 @@ angular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);
$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider', '$locationProvider'];
function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $locationProvider) {

var root, states = {}, $state, queue = {};
var root, states = {}, $state, queue = {}, abstractKey = 'abstract';

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

// Register the state in the global state list and with $urlRouter if necessary.
if (!state['abstract'] && state.url) {
if (!state[abstractKey] && state.url) {
$urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {
if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {
$state.transitionTo(state, $match, false);
$state.transitionTo(state, $match, { location: false });
}
}]);
}
Expand Down Expand Up @@ -1116,7 +1189,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
throw new Error("No such state '" + to + "'");
}
}
if (toState['abstract']) throw new Error("Cannot transition to abstract state '" + to + "'");
if (toState[abstractKey]) throw new Error("Cannot transition to abstract state '" + to + "'");
if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);
to = toState;

Expand Down Expand Up @@ -1286,13 +1359,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
return url;
};

$state.get = function (stateOrName) {
$state.get = function (stateOrName, context) {
if (!isDefined(stateOrName)) {
var list = [];
forEach(states, function(state) { list.push(state.self); });
return list;
}
var state = findState(stateOrName);
var state = findState(stateOrName, context);
return (state && state.self) ? state.self : null;
};

Expand Down Expand Up @@ -1344,39 +1417,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
return $state;
}

function normalize(keys, values) {
var normalized = {};

forEach(keys, function (name) {
var value = values[name];
normalized[name] = (value != null) ? String(value) : null;
});
return normalized;
}

function equalForKeys(a, b, keys) {
// If keys not provided, assume keys from object 'a'
if (!keys) {
keys = [];
for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility
}

for (var i=0; i<keys.length; i++) {
var k = keys[i];
if (a[k] != b[k]) return false; // Not '===', values aren't necessarily normalized
}
return true;
}

function filterByKeys(keys, values) {
var filtered = {};

forEach(keys, function (name) {
filtered[name] = values[name];
});
return filtered;
}

function shouldTriggerReload(to, from, locals, options) {
if ( to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false)) ) {
return true;
Expand Down Expand Up @@ -1420,9 +1460,7 @@ angular.module('ui.router.state').provider('$view', $ViewProvider);

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

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

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

$StateRefDirective.$inject = ['$state'];
function $StateRefDirective($state) {
function stateContext(el) {
var stateData = el.parent().inheritedData('$uiView');

if (stateData && stateData.state && stateData.state.name) {
return stateData.state;
}
}

$StateRefDirective.$inject = ['$state', '$timeout'];
function $StateRefDirective($state, $timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
require: '?^uiSrefActive',
link: function(scope, element, attrs, uiSrefActive) {
var ref = parseStateRef(attrs.uiSref);
var params = null, url = null, base = $state.$current;
var params = null, url = null, base = stateContext(element) || $state.$current;
var isForm = element[0].nodeName === "FORM";
var attr = isForm ? "action" : "href", nav = true;

var stateData = element.parent().inheritedData('$uiView');

if (stateData && stateData.state && stateData.state.name) {
base = stateData.state;
}

var update = function(newVal) {
if (newVal) params = newVal;
if (!nav) return;
Expand All @@ -1570,6 +1611,9 @@ function $StateRefDirective($state) {
return false;
}
element[0][attr] = newHref;
if (uiSrefActive) {
uiSrefActive.$$setStateInfo(ref.state, params);
}
};

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

if ((button === 0 || button == 1) && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
scope.$evalAsync(function() {
$state.go(ref.state, params, { relative: base });
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
$timeout(function() {
scope.$apply(function() {
$state.go(ref.state, params, { relative: base });
});
});
e.preventDefault();
}
Expand All @@ -1596,7 +1643,44 @@ function $StateRefDirective($state) {
};
}

angular.module('ui.router.state').directive('uiSref', $StateRefDirective);
$StateActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];
function $StateActiveDirective($state, $stateParams, $interpolate) {
return {
restrict: "A",
controller: function($scope, $element, $attrs) {
var state, params, activeClass;

// There probably isn't much point in $observing this
activeClass = $interpolate($attrs.uiSrefActive || '', false)($scope);

// Allow uiSref to communicate with uiSrefActive
this.$$setStateInfo = function(newState, newParams) {
state = $state.get(newState, stateContext($element));
params = newParams;
update();
};

$scope.$on('$stateChangeSuccess', update);

// Update route state
function update() {
if ($state.$current.self === state && matchesParams()) {
$element.addClass(activeClass);
} else {
$element.removeClass(activeClass);
}
}

function matchesParams() {
return !params || equalForKeys(params, $stateParams);
}
}
};
}

angular.module('ui.router.state')
.directive('uiSref', $StateRefDirective)
.directive('uiSrefActive', $StateActiveDirective);

$RouteProvider.$inject = ['$stateProvider', '$urlRouterProvider'];
function $RouteProvider( $stateProvider, $urlRouterProvider) {
Expand Down
4 changes: 2 additions & 2 deletions release/angular-ui-router.min.js

Large diffs are not rendered by default.

Loading

5 comments on commit ea03a14

@ghengeveld
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably have been a minor version increase rather than a patch, since the upgrade to Angular 1.1.5 is a breaking change.

@nateabele
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a dependency, it's just for the tests. It's still compatible with 1.0.8 anyway.

@ghengeveld
Copy link

@ghengeveld ghengeveld commented on ea03a14 Dec 17, 2013 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nateabele
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, HEAD includes 1.0.8, which the test suite is run against. If you observe issues with that, you're welcome to file an issue.

@ghengeveld
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the error I'm getting:

TypeError: Object #<Object> has no method 'has' at $ViewDirective (angular-ui-router.js:1463:29)

This is the line in question:

var $animator = $injector.has('$animator') ? $injector.get('$animator') : false;

I checked the Angular docs and found that $injector.has() does not exist in v1.0.8, it was introduced in v1.1.5.

Here's where it went wrong: 516a9a1#diff-5

Please sign in to comment.