aboutsummaryrefslogtreecommitdiffstats
path: root/src/service/route.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/route.js')
-rw-r--r--src/service/route.js473
1 files changed, 238 insertions, 235 deletions
diff --git a/src/service/route.js b/src/service/route.js
index 3918c251..f2ecbd2a 100644
--- a/src/service/route.js
+++ b/src/service/route.js
@@ -62,264 +62,267 @@
</doc:scenario>
</doc:example>
*/
-angularServiceInject('$route', function($rootScope, $location, $routeParams) {
- /**
- * @ngdoc event
- * @name angular.service.$route#$beforeRouteChange
- * @eventOf angular.service.$route
- * @eventType broadcast on root scope
- * @description
- * Broadcasted before a route change.
- *
- * @param {Route} next Future route information.
- * @param {Route} current Current route information.
- *
- * The `Route` object extends the route definition with the following properties.
- *
- * * `scope` - The instance of the route controller.
- * * `params` - The current {@link angular.service.$routeParams params}.
- *
- */
+function $RouteProvider(){
+ this.$get = ['$rootScope', '$location', '$routeParams',
+ function( $rootScope, $location, $routeParams) {
+ /**
+ * @ngdoc event
+ * @name angular.service.$route#$beforeRouteChange
+ * @eventOf angular.service.$route
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted before a route change.
+ *
+ * @param {Route} next Future route information.
+ * @param {Route} current Current route information.
+ *
+ * The `Route` object extends the route definition with the following properties.
+ *
+ * * `scope` - The instance of the route controller.
+ * * `params` - The current {@link angular.service.$routeParams params}.
+ *
+ */
- /**
- * @ngdoc event
- * @name angular.service.$route#$afterRouteChange
- * @eventOf angular.service.$route
- * @eventType broadcast on root scope
- * @description
- * Broadcasted after a route change.
- *
- * @param {Route} current Current route information.
- * @param {Route} previous Previous route information.
- *
- * The `Route` object extends the route definition with the following properties.
- *
- * * `scope` - The instance of the route controller.
- * * `params` - The current {@link angular.service.$routeParams params}.
- *
- */
+ /**
+ * @ngdoc event
+ * @name angular.service.$route#$afterRouteChange
+ * @eventOf angular.service.$route
+ * @eventType broadcast on root scope
+ * @description
+ * Broadcasted after a route change.
+ *
+ * @param {Route} current Current route information.
+ * @param {Route} previous Previous route information.
+ *
+ * The `Route` object extends the route definition with the following properties.
+ *
+ * * `scope` - The instance of the route controller.
+ * * `params` - The current {@link angular.service.$routeParams params}.
+ *
+ */
- /**
- * @ngdoc event
- * @name angular.service.$route#$routeUpdate
- * @eventOf angular.service.$route
- * @eventType emit on the current route scope
- * @description
- *
- * The `reloadOnSearch` property has been set to false, and we are reusing the same
- * instance of the Controller.
- */
+ /**
+ * @ngdoc event
+ * @name angular.service.$route#$routeUpdate
+ * @eventOf angular.service.$route
+ * @eventType emit on the current route scope
+ * @description
+ *
+ * The `reloadOnSearch` property has been set to false, and we are reusing the same
+ * instance of the Controller.
+ */
- var routes = {},
- matcher = switchRouteMatcher,
- parentScope = $rootScope,
- dirty = 0,
- forceReload = false,
- $route = {
- routes: routes,
+ var routes = {},
+ matcher = switchRouteMatcher,
+ parentScope = $rootScope,
+ dirty = 0,
+ forceReload = false,
+ $route = {
+ routes: routes,
- /**
- * @ngdoc method
- * @name angular.service.$route#parent
- * @methodOf angular.service.$route
- *
- * @param {Scope} [scope=rootScope] Scope to be used as parent for newly created
- * `$route.current.scope` scopes.
- *
- * @description
- * Sets a scope to be used as the parent scope for scopes created on route change. If not
- * set, defaults to the root scope.
- */
- parent: function(scope) {
- if (scope) parentScope = scope;
- },
+ /**
+ * @ngdoc method
+ * @name angular.service.$route#parent
+ * @methodOf angular.service.$route
+ *
+ * @param {Scope} [scope=rootScope] Scope to be used as parent for newly created
+ * `$route.current.scope` scopes.
+ *
+ * @description
+ * Sets a scope to be used as the parent scope for scopes created on route change. If not
+ * set, defaults to the root scope.
+ */
+ parent: function(scope) {
+ if (scope) parentScope = scope;
+ },
- /**
- * @ngdoc method
- * @name angular.service.$route#when
- * @methodOf angular.service.$route
- *
- * @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.widget.ng:view ng:view} or
- * {@link angular.widget.ng:include ng:include} widgets.
- * - `redirectTo` – {(string|function())=} – value to update
- * {@link angular.service.$location $location} path with and trigger route redirection.
- *
- * If `redirectTo` is a function, it will be called with the following parameters:
- *
- * - `{Object.<string>}` - 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 emited on the current route scope. You can use this event to
- * react to {@link angular.service.$routeParams} changes:
- *
- * function MyCtrl($route, $routeParams) {
- * this.$on('$routeUpdate', function() {
- * // do stuff with $routeParams
- * });
- * }
- *
- * @returns {Object} route object
- *
- * @description
- * Adds a new route definition to the `$route` service.
- */
- 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?
- dirty++;
- return routeDef;
- },
+ /**
+ * @ngdoc method
+ * @name angular.service.$route#when
+ * @methodOf angular.service.$route
+ *
+ * @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.widget.ng:view ng:view} or
+ * {@link angular.widget.ng:include ng:include} widgets.
+ * - `redirectTo` – {(string|function())=} – value to update
+ * {@link angular.service.$location $location} path with and trigger route redirection.
+ *
+ * If `redirectTo` is a function, it will be called with the following parameters:
+ *
+ * - `{Object.<string>}` - 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 emited on the current route scope. You can use this event to
+ * react to {@link angular.service.$routeParams} changes:
+ *
+ * function MyCtrl($route, $routeParams) {
+ * this.$on('$routeUpdate', function() {
+ * // do stuff with $routeParams
+ * });
+ * }
+ *
+ * @returns {Object} route object
+ *
+ * @description
+ * Adds a new route definition to the `$route` service.
+ */
+ 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?
+ dirty++;
+ return routeDef;
+ },
- /**
- * @ngdoc method
- * @name angular.service.$route#otherwise
- * @methodOf angular.service.$route
- *
- * @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`.
- */
- otherwise: function(params) {
- $route.when(null, params);
- },
+ /**
+ * @ngdoc method
+ * @name angular.service.$route#otherwise
+ * @methodOf angular.service.$route
+ *
+ * @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`.
+ */
+ otherwise: function(params) {
+ $route.when(null, params);
+ },
- /**
- * @ngdoc method
- * @name angular.service.$route#reload
- * @methodOf angular.service.$route
- *
- * @description
- * Causes `$route` service to reload (and recreate the `$route.current` scope) upon the next
- * eval even if {@link angular.service.$location $location} hasn't changed.
- */
- reload: function() {
- dirty++;
- forceReload = true;
- }
- };
+ /**
+ * @ngdoc method
+ * @name angular.service.$route#reload
+ * @methodOf angular.service.$route
+ *
+ * @description
+ * Causes `$route` service to reload (and recreate the `$route.current` scope) upon the next
+ * eval even if {@link angular.service.$location $location} hasn't changed.
+ */
+ reload: function() {
+ dirty++;
+ forceReload = true;
+ }
+ };
- $rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute);
+ $rootScope.$watch(function() { return dirty + $location.url(); }, updateRoute);
- return $route;
+ 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);
+ 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];
});
+ var match = on.match(new RegExp(regex));
+ if (match) {
+ forEach(params, function(name, index) {
+ dst[name] = match[index + 1];
+ });
+ }
+ return match ? dst : null;
}
- return match ? dst : null;
- }
- function updateRoute() {
- var next = parseRoute(),
- last = $route.current,
- Controller;
+ function updateRoute() {
+ var next = parseRoute(),
+ last = $route.current,
+ Controller;
- if (next && last && next.$route === last.$route
- && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {
- $route.current = next;
- copy(next.params, $routeParams);
- last.scope && last.scope.$emit('$routeUpdate');
- } else {
- forceReload = false;
- $rootScope.$broadcast('$beforeRouteChange', next, last);
- last && last.scope && last.scope.$destroy();
- $route.current = next;
- if (next) {
- if (next.redirectTo) {
- if (isString(next.redirectTo)) {
- $location.path(interpolate(next.redirectTo, next.params)).search(next.params)
- .replace();
+ if (next && last && next.$route === last.$route
+ && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) {
+ $route.current = next;
+ copy(next.params, $routeParams);
+ last.scope && last.scope.$emit('$routeUpdate');
+ } else {
+ forceReload = false;
+ $rootScope.$broadcast('$beforeRouteChange', next, last);
+ last && last.scope && last.scope.$destroy();
+ $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 {
- $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search()))
- .replace();
+ copy(next.params, $routeParams);
+ (Controller = next.controller) && inferInjectionArgs(Controller);
+ next.scope = parentScope.$new(Controller);
}
- } else {
- copy(next.params, $routeParams);
- (Controller = next.controller) && inferInjectionArgs(Controller);
- next.scope = parentScope.$new(Controller);
}
+ $rootScope.$broadcast('$afterRouteChange', next, last);
}
- $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 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('');
- }
+ /**
+ * @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('');
+ }
-}, ['$rootScope', '$location', '$routeParams']);
+ }];
+}