app/assets/javascripts/angular/angular-route.js in angular-rails-engine-1.2.0.0 vs app/assets/javascripts/angular/angular-route.js in angular-rails-engine-1.2.0.1

- old
+ new

@@ -1,36 +1,26 @@ /** - * @license AngularJS v1.2.0rc1 + * @license AngularJS v1.2.0 * (c) 2010-2012 Google, Inc. http://angularjs.org * License: MIT */ (function(window, angular, undefined) {'use strict'; -var copy = angular.copy, - equals = angular.equals, - extend = angular.extend, - forEach = angular.forEach, - isDefined = angular.isDefined, - isFunction = angular.isFunction, - isString = angular.isString, - jqLite = angular.element, - noop = angular.noop, - toJson = angular.toJson; - - -function inherit(parent, extra) { - return extend(new (extend(function() {}, {prototype:parent}))(), extra); -} - /** * @ngdoc overview * @name ngRoute * @description * - * Module that provides routing and deeplinking services and directives for angular apps. + * # ngRoute + * + * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. + * + * {@installModule route} + * + * <div doc-module-components="ngRoute"></div> */ - + /* global -ngRouteModule */ var ngRouteModule = angular.module('ngRoute', ['ng']). provider('$route', $RouteProvider); /** * @ngdoc object @@ -38,12 +28,18 @@ * @function * * @description * * Used for configuring routes. See {@link ngRoute.$route $route} for an example. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. */ function $RouteProvider(){ + function inherit(parent, extra) { + return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra); + } + var routes = {}; /** * @ngdoc method * @name ngRoute.$routeProvider#when @@ -55,12 +51,12 @@ * route definition. * * * `path` can contain named groups starting with a colon (`:name`). All characters up * to the next slash are matched and stored in `$routeParams` under the given `name` * when the route matches. - * * `path` can contain named groups starting with a colon and ending with a star (`:name*`). - * All characters are eagerly stored in `$routeParams` under the given `name` + * * `path` can contain named groups starting with a colon and ending with a star (`:name*`). + * All characters are eagerly stored in `$routeParams` under the given `name` * when the route matches. * * `path` can contain optional named groups with a question mark (`:name?`). * * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match * `/color/brown/largecode/code/with/slashs/edit` and extract: @@ -72,13 +68,13 @@ * @param {Object} route Mapping information to be assigned to `$route.current` on route * match. * * Object properties: * - * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly - * created scope or the name of a {@link angular.Module#controller registered controller} - * if passed as a string. + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be * published to scope under the `controllerAs` name. * - `template` – `{string=|function()=}` – html template as a string or a function that * returns an html template as a string which should be used by {@link * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. @@ -96,21 +92,26 @@ * * - `{Array.<Object>}` - route parameters extracted from the current * `$location.path()` by applying the current route * * - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should - * be injected into the controller. If any of these dependencies are promises, they will be - * resolved and converted to a value before the controller is instantiated and the - * `$routeChangeSuccess` event is fired. The map object is: + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object + * is: * * - `key` – `{string}`: a name of a dependency to be injected into the controller. * - `factory` - `{string|function}`: If `string` then it is an alias for a service. * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} - * and the return value is treated as the dependency. If the result is a promise, it is resolved - * before its value is injected into the controller. Be aware that `ngRoute.$routeParams` will - * still refer to the previous route within these resolve functions. Use `$route.current.params` - * to access the new route parameters, instead. + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. * * - `redirectTo` – {(string|function())=} – value to update * {@link ng.$location $location} path with and trigger route redirection. * * If `redirectTo` is a function, it will be called with the following parameters: @@ -121,12 +122,12 @@ * - `{Object}` - current `$location.search()` * * The custom `redirectTo` function is expected to return a string which will be used * to update `$location.path()` and `$location.search()`. * - * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search() - * changes. + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` + * or `$location.hash()` changes. * * If the option is set to `false` and url in the browser changes, then * `$routeUpdate` event is broadcasted on the root scope. * * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive @@ -138,23 +139,23 @@ * * @description * Adds a new route definition to the `$route` service. */ this.when = function(path, route) { - routes[path] = extend( + routes[path] = angular.extend( {reloadOnSearch: true}, route, path && pathRegExp(path, route) ); // create redirection for trailing slashes if (path) { var redirectPath = (path[path.length-1] == '/') - ? path.substr(0, path.length-1) - : path +'/'; + ? path.substr(0, path.length-1) + : path +'/'; - routes[redirectPath] = extend( + routes[redirectPath] = angular.extend( {redirectTo: path}, pathRegExp(redirectPath, route) ); } @@ -189,11 +190,13 @@ slash = slash || ''; return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') - + (star && '(.+)?' || '([^/]+)?') + ')' + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + (optional || ''); }) .replace(/([\/$\*])/g, '\\$1'); ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); @@ -216,12 +219,19 @@ this.when(null, params); return this; }; - this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache', '$sce', - function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$http', + '$templateCache', + '$sce', + function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { /** * @ngdoc object * @name ngRoute.$route * @requires $location @@ -239,26 +249,29 @@ * - `$template` - The current route template HTML. * * @property {Array.<Object>} routes Array of all configured routes. * * @description - * Is used for deep-linking URLs to controllers and views (HTML partials). + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). * It watches `$location.url()` and tries to map the path to an existing route definition. * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. * - * The `$route` service is typically used in conjunction with {@link ngRoute.directive:ngView ngView} - * directive and the {@link ngRoute.$routeParams $routeParams} service. + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. * * @example This example shows how changing the URL hash causes the `$route` to match a route against the URL, and the `ngView` pulls in the partial. Note that this example is using {@link ng.directive:script inlined templates} to get it working on jsfiddle as well. - <example module="ngView" deps="angular-route.js"> + <example module="ngViewExample" deps="angular-route.js"> <file name="index.html"> <div ng-controller="MainCntl"> Choose: <a href="Book/Moby">Moby</a> | <a href="Book/Moby/ch/1">Moby: Ch1</a> | @@ -287,11 +300,13 @@ Book Id: {{params.bookId}}<br /> Chapter Id: {{params.chapterId}} </file> <file name="script.js"> - angular.module('ngView', ['ngRoute']).config(function($routeProvider, $locationProvider) { + angular.module('ngViewExample', ['ngRoute']) + + .config(function($routeProvider, $locationProvider) { $routeProvider.when('/Book/:bookId', { templateUrl: 'book.html', controller: BookCntl, resolve: { // I will cause a 1 second delay @@ -356,10 +371,11 @@ * resolving all of the dependencies needed for the route change to occurs. * Typically this involves fetching the view template as well as any dependencies * defined in `resolve` route property. Once all of the dependencies are resolved * `$routeChangeSuccess` is fired. * + * @param {Object} angularEvent Synthetic event object. * @param {Route} next Future route information. * @param {Route} current Current route information. */ /** @@ -372,21 +388,23 @@ * {@link ngRoute.directive:ngView ngView} listens for the directive * to instantiate the controller and render the view. * * @param {Object} angularEvent Synthetic event object. * @param {Route} current Current route information. - * @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. */ /** * @ngdoc event * @name ngRoute.$route#$routeChangeError * @eventOf ngRoute.$route * @eventType broadcast on root scope * @description * Broadcasted if any of the resolve promises are rejected. * + * @param {Object} angularEvent Synthetic event object * @param {Route} current Current route information. * @param {Route} previous Previous route information. * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. */ @@ -447,17 +465,16 @@ if (!route.regexp) return null; var m = route.regexp.exec(on); if (!m) return null; - var N = 0; for (var i = 1, len = m.length; i < len; ++i) { var key = keys[i - 1]; var val = 'string' == typeof m[i] - ? decodeURIComponent(m[i]) - : m[i]; + ? decodeURIComponent(m[i]) + : m[i]; if (key && val) { params[key.name] = val; } } @@ -467,21 +484,22 @@ function updateRoute() { var next = parseRoute(), last = $route.current; if (next && last && next.$$route === last.$$route - && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { + && angular.equals(next.pathParams, last.pathParams) + && !next.reloadOnSearch && !forceReload) { last.params = next.params; - copy(last.params, $routeParams); + angular.copy(last.params, $routeParams); $rootScope.$broadcast('$routeUpdate', last); } else if (next || last) { forceReload = false; $rootScope.$broadcast('$routeChangeStart', next, last); $route.current = next; if (next) { if (next.redirectTo) { - if (isString(next.redirectTo)) { + if (angular.isString(next.redirectTo)) { $location.path(interpolate(next.redirectTo, next.params)).search(next.params) .replace(); } else { $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) .replace(); @@ -490,44 +508,45 @@ } $q.when(next). then(function() { if (next) { - var locals = extend({}, next.resolve), + var locals = angular.extend({}, next.resolve), template, templateUrl; - forEach(locals, function(value, key) { - locals[key] = isString(value) ? $injector.get(value) : $injector.invoke(value); + angular.forEach(locals, function(value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : $injector.invoke(value); }); - if (isDefined(template = next.template)) { - if (isFunction(template)) { + if (angular.isDefined(template = next.template)) { + if (angular.isFunction(template)) { template = template(next.params); } - } else if (isDefined(templateUrl = next.templateUrl)) { - if (isFunction(templateUrl)) { + } else if (angular.isDefined(templateUrl = next.templateUrl)) { + if (angular.isFunction(templateUrl)) { templateUrl = templateUrl(next.params); } templateUrl = $sce.getTrustedResourceUrl(templateUrl); - if (isDefined(templateUrl)) { + if (angular.isDefined(templateUrl)) { next.loadedTemplateUrl = templateUrl; template = $http.get(templateUrl, {cache: $templateCache}). then(function(response) { return response.data; }); } } - if (isDefined(template)) { + if (angular.isDefined(template)) { locals['$template'] = template; } return $q.all(locals); } }). // after route change then(function(locals) { if (next == $route.current) { if (next) { next.locals = locals; - copy(next.params, $routeParams); + angular.copy(next.params, $routeParams); } $rootScope.$broadcast('$routeChangeSuccess', next, last); } }, function(error) { if (next == $route.current) { @@ -542,14 +561,14 @@ * @returns the current active route, by matching it against the URL */ function parseRoute() { // Match a route var params, match; - forEach(routes, function(route, path) { + angular.forEach(routes, function(route, path) { if (!match && (params = switchRouteMatcher($location.path(), route))) { match = inherit(route, { - params: extend({}, $location.search(), params), + params: angular.extend({}, $location.search(), params), pathParams: params}); match.$$route = route; } }); // No route matched; fallback to "otherwise" route @@ -559,12 +578,12 @@ /** * @returns interpolation of the redirect path with the parameters */ function interpolate(string, params) { var result = []; - forEach((string||'').split(':'), function(segment, i) { - if (i == 0) { + angular.forEach((string||'').split(':'), function(segment, i) { + if (i === 0) { result.push(segment); } else { var segmentMatch = segment.match(/(\w+)(.*)/); var key = segmentMatch[1]; result.push(params[key]); @@ -584,14 +603,18 @@ * @ngdoc object * @name ngRoute.$routeParams * @requires $route * * @description - * Current set of route parameters. The route parameters are a combination of the - * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters - * are extracted when the {@link ngRoute.$route $route} path is matched. + * The `$routeParams` service allows you to retrieve the current set of route parameters. * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * * In case of parameter name collision, `path` params take precedence over `search` params. * * The service guarantees that the identity of the `$routeParams` object will remain unchanged * (but its properties will likely change) even when a route change occurs. * @@ -611,10 +634,12 @@ */ function $RouteParamsProvider() { this.$get = function() { return {}; }; } +ngRouteModule.directive('ngView', ngViewFactory); + /** * @ngdoc directive * @name ngRoute.directive:ngView * @restrict ECA * @@ -623,17 +648,20 @@ * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by * including the rendered template of the current route into the main layout (`index.html`) file. * Every time the current route changes, the included view changes with it according to the * configuration of the `$route` service. * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * * @animations * enter - animation is used to bring new content into the browser. * leave - animation is used to animate existing content away. * * The enter and leave animation occur concurrently. * * @scope + * @priority 400 * @example <example module="ngViewExample" deps="angular-route.js" animations="true"> <file name="index.html"> <div ng-controller="MainCntl as main"> Choose: @@ -641,12 +669,12 @@ <a href="Book/Moby/ch/1">Moby: Ch1</a> | <a href="Book/Gatsby">Gatsby</a> | <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> | <a href="Book/Scarlet">Scarlet Letter</a><br/> - <div class="example-animate-container"> - <div ng-view class="view-example"></div> + <div class="view-animate-container"> + <div ng-view class="view-animate"></div> </div> <hr /> <pre>$location.path() = {{main.$location.path()}}</pre> <pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre> @@ -670,26 +698,26 @@ Chapter Id: {{chapter.params.chapterId}} </div> </file> <file name="animations.css"> - .example-animate-container { + .view-animate-container { position:relative; + height:100px!important; + position:relative; background:white; border:1px solid black; height:40px; overflow:hidden; } - .example-animate-container > div { + .view-animate { padding:10px; } - .view-example.ng-enter, .view-example.ng-leave { + .view-animate.ng-enter, .view-animate.ng-leave { -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; display:block; width:100%; border-left:1px solid black; @@ -700,43 +728,37 @@ right:0; bottom:0; padding:10px; } - .example-animate-container { - position:relative; - height:100px; - } - - .view-example.ng-enter { + .view-animate.ng-enter { left:100%; } - .view-example.ng-enter.ng-enter-active { + .view-animate.ng-enter.ng-enter-active { left:0; } - - .view-example.ng-leave { } - .view-example.ng-leave.ng-leave-active { + .view-animate.ng-leave.ng-leave-active { left:-100%; } </file> <file name="script.js"> - angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], function($routeProvider, $locationProvider) { - $routeProvider.when('/Book/:bookId', { - templateUrl: 'book.html', - controller: BookCntl, - controllerAs: 'book' - }); - $routeProvider.when('/Book/:bookId/ch/:chapterId', { - templateUrl: 'chapter.html', - controller: ChapterCntl, - controllerAs: 'chapter' - }); + angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], + function($routeProvider, $locationProvider) { + $routeProvider.when('/Book/:bookId', { + templateUrl: 'book.html', + controller: BookCntl, + controllerAs: 'book' + }); + $routeProvider.when('/Book/:bookId/ch/:chapterId', { + templateUrl: 'chapter.html', + controller: ChapterCntl, + controllerAs: 'chapter' + }); - // configure html5 to get links working on jsfiddle - $locationProvider.html5Mode(true); + // configure html5 to get links working on jsfiddle + $locationProvider.html5Mode(true); }); function MainCntl($route, $routeParams, $location) { this.$route = $route; this.$location = $location; @@ -778,27 +800,24 @@ * @eventOf ngRoute.directive:ngView * @eventType emit on the current ngView scope * @description * Emitted every time the ngView content is reloaded. */ -var NG_VIEW_PRIORITY = 500; -var ngViewDirective = ['$route', '$anchorScroll', '$compile', '$controller', '$animate', - function($route, $anchorScroll, $compile, $controller, $animate) { +ngViewFactory.$inject = ['$route', '$anchorScroll', '$compile', '$controller', '$animate']; +function ngViewFactory( $route, $anchorScroll, $compile, $controller, $animate) { return { restrict: 'ECA', terminal: true, - priority: NG_VIEW_PRIORITY, - compile: function(element, attr) { - var onloadExp = attr.onload || ''; + priority: 400, + transclude: 'element', + compile: function(element, attr, linker) { + return function(scope, $element, attr) { + var currentScope, + currentElement, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; - element.html(''); - var anchor = jqLite(document.createComment(' ngView ')); - element.replaceWith(anchor); - - return function(scope) { - var currentScope, currentElement; - scope.$on('$routeChangeSuccess', update); update(); function cleanupLastView() { if (currentScope) { @@ -814,47 +833,48 @@ function update() { var locals = $route.current && $route.current.locals, template = locals && locals.$template; if (template) { - cleanupLastView(); + var newScope = scope.$new(); + linker(newScope, function(clone) { + clone.html(template); + $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); - currentScope = scope.$new(); - currentElement = element.clone(); - currentElement.html(template); - $animate.enter(currentElement, null, anchor); + cleanupLastView(); - var link = $compile(currentElement, false, NG_VIEW_PRIORITY - 1), - current = $route.current; + var link = $compile(clone.contents()), + current = $route.current; - if (current.controller) { - locals.$scope = currentScope; - var controller = $controller(current.controller, locals); - if (current.controllerAs) { - currentScope[current.controllerAs] = controller; + currentScope = current.scope = newScope; + currentElement = clone; + + if (current.controller) { + locals.$scope = currentScope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + currentScope[current.controllerAs] = controller; + } + clone.data('$ngControllerController', controller); + clone.children().data('$ngControllerController', controller); } - currentElement.data('$ngControllerController', controller); - currentElement.children().data('$ngControllerController', controller); - } - current.scope = currentScope; - - link(currentScope); - - currentScope.$emit('$viewContentLoaded'); - currentScope.$eval(onloadExp); - - // $anchorScroll might listen on event... - $anchorScroll(); + link(currentScope); + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + }); } else { cleanupLastView(); } } - } + }; } }; -}]; - -ngRouteModule.directive('ngView', ngViewDirective); +} })(window, window.angular);