'use strict'; /** * @ngdoc object * @name angular.module.ng.$routeProvider * @function * * @description * * Used for configuring routes. See {@link angular.module.ng.$route $route} for an example. */ function $RouteProvider(){ var routes = {}; /** * @ngdoc method * @name angular.module.ng.$routeProvider#when * @methodOf angular.module.ng.$routeProvider * * @param {string} path Route path (matched against `$location.hash`) * @param {Object} route Mapping information to be assigned to `$route.current` on route * match. * * Object properties: * * - `controller` – `{function()=}` – Controller fn that should be associated with newly * created scope. * - `template` – `{string=}` – path to an html template that should be used by * {@link angular.module.ng.$compileProvider.directive.ng-view ng-view} or * {@link angular.module.ng.$compileProvider.directive.ng-include ng-include} directives. * - `redirectTo` – {(string|function())=} – value to update * {@link angular.module.ng.$location $location} path with and trigger route redirection. * * If `redirectTo` is a function, it will be called with the following parameters: * * - `{Object.}` - route parameters extracted from the current * `$location.path()` by applying the current route template. * - `{string}` - current `$location.path()` * - `{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. * * If the option is set to `false` and url in the browser changes, then * `$routeUpdate` event is broadcasted on the root scope. * * @returns {Object} route object * * @description * Adds a new route definition to the `$route` service. */ this.when = function(path, route) { var routeDef = routes[path]; if (!routeDef) routeDef = routes[path] = {reloadOnSearch: true}; if (route) extend(routeDef, route); // TODO(im): what the heck? merge two route definitions? return routeDef; }; /** * @ngdoc method * @name angular.module.ng.$routeProvider#otherwise * @methodOf angular.module.ng.$routeProvider * * @description * Sets route definition that will be used on route change when no other route definition * is matched. * * @param {Object} params Mapping information to be assigned to `$route.current`. */ this.otherwise = function(params) { this.when(null, params); }; this.$get = ['$rootScope', '$location', '$routeParams', function( $rootScope, $location, $routeParams) { /** * @ngdoc object * @name angular.module.ng.$route * @requires $location * @requires $routeParams * * @property {Object} current Reference to the current route definition. * @property {Array.} routes Array of all configured routes. * * @description * 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. * * You can define routes through {@link angular.module.ng.$routeProvider $routeProvider}'s API. * * The `$route` service is typically used in conjunction with {@link angular.module.ng.$compileProvider.directive.ng-view ng-view} * directive and the {@link angular.module.ng.$routeParams $routeParams} service. * * @example This example shows how changing the URL hash causes the `$route` to match a route against the URL, and the `ng-view` pulls in the partial. Note that this example is using {@link angular.module.ng.$compileProvide.directive.script inlined templates} to get it working on jsfiddle as well.
Choose: Moby | Moby: Ch1 | Gatsby | Gatsby: Ch4 | Scarlet Letter

$location.path() = {{$location.path()}}
$route.current.template = {{$route.current.template}}
$route.current.params = {{$route.current.params}}
$route.current.scope.name = {{$route.current.scope.name}}
$routeParams = {{$routeParams}}
it('should load and compile correct template', function() { element('a:contains("Moby: Ch1")').click(); var content = element('.doc-example-live [ng-view]').text(); expect(content).toMatch(/controller\: ChapterCntl/); expect(content).toMatch(/Book Id\: Moby/); expect(content).toMatch(/Chapter Id\: 1/); element('a:contains("Scarlet")').click(); content = element('.doc-example-live [ng-view]').text(); expect(content).toMatch(/controller\: BookCntl/); expect(content).toMatch(/Book Id\: Scarlet/); });
*/ /** * @ngdoc event * @name angular.module.ng.$route#$beforeRouteChange * @eventOf angular.module.ng.$route * @eventType broadcast on root scope * @description * Broadcasted before a route change. * * @param {Route} next Future route information. * @param {Route} current Current route information. */ /** * @ngdoc event * @name angular.module.ng.$route#$afterRouteChange * @eventOf angular.module.ng.$route * @eventType broadcast on root scope * @description * Broadcasted after a route change. * * @param {Route} current Current route information. * @param {Route} previous Previous route information. */ /** * @ngdoc event * @name angular.module.ng.$route#$routeUpdate * @eventOf angular.module.ng.$route * @eventType broadcast on root scope * @description * * The `reloadOnSearch` property has been set to false, and we are reusing the same * instance of the Controller. */ var matcher = switchRouteMatcher, dirty = 0, forceReload = false, $route = { routes: routes, /** * @ngdoc method * @name angular.module.ng.$route#reload * @methodOf angular.module.ng.$route * * @description * Causes `$route` service to reload the current route even if * {@link angular.module.ng.$location $location} hasn't changed. * * As a result of that, {@link angular.module.ng.$compileProvider.directive.ng-view ng-view} * creates new scope, reinstantiates the controller. */ reload: function() { dirty++; forceReload = true; } }; $rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute); return $route; ///////////////////////////////////////////////////// function switchRouteMatcher(on, when) { // TODO(i): this code is convoluted and inefficient, we should construct the route matching // regex only once and then reuse it var regex = '^' + when.replace(/([\.\\\(\)\^\$])/g, "\\$1") + '$', params = [], dst = {}; forEach(when.split(/\W/), function(param) { if (param) { var paramRegExp = new RegExp(":" + param + "([\\W])"); if (regex.match(paramRegExp)) { regex = regex.replace(paramRegExp, "([^\\/]*)$1"); params.push(param); } } }); var match = on.match(new RegExp(regex)); if (match) { forEach(params, function(name, index) { dst[name] = match[index + 1]; }); } return match ? dst : null; } function updateRoute() { var next = parseRoute(), last = $route.current; if (next && last && next.$route === last.$route && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { last.params = next.params; copy(last.params, $routeParams); $rootScope.$broadcast('$routeUpdate', last); } else if (next || last) { forceReload = false; $rootScope.$broadcast('$beforeRouteChange', next, last); $route.current = next; if (next) { if (next.redirectTo) { if (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(); } } else { copy(next.params, $routeParams); } } $rootScope.$broadcast('$afterRouteChange', next, last); } } /** * @returns the current active route, by matching it against the URL */ function parseRoute() { // Match a route var params, match; forEach(routes, function(route, path) { if (!match && (params = matcher($location.path(), path))) { match = inherit(route, { params: extend({}, $location.search(), params), pathParams: params}); match.$route = route; } }); // No route matched; fallback to "otherwise" route return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); } /** * @returns interpolation of the redirect path with the parametrs */ function interpolate(string, params) { var result = []; 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]); result.push(segmentMatch[2] || ''); delete params[key]; } }); return result.join(''); } }]; }