From 70e401ef100614295fc808e32f0142f07c315461 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Thu, 15 Apr 2010 14:17:33 -0700 Subject: added $route service --- angular-debug.js | 4 +++- src/AngularPublic.js | 1 + src/Scope.js | 2 ++ src/services.js | 40 ++++++++++++++++++++++++++++++++++++++++ src/widgets.js | 2 +- test/ScopeSpec.js | 10 ++++++++++ test/angular-mocks.js | 23 +++++++++++++++++++++++ test/servicesSpec.js | 38 ++++++++++++++++++++++++++++++++++++++ test/testabilityPatch.js | 27 ++++++++++++++++++++++----- 9 files changed, 140 insertions(+), 7 deletions(-) diff --git a/angular-debug.js b/angular-debug.js index 897db442..fd9b9902 100644 --- a/angular-debug.js +++ b/angular-debug.js @@ -807,6 +807,8 @@ function createScope(parent, services, existing) { exceptionHandler(e); } else if (exceptionHandler) { errorHandlerFor(exceptionHandler, e); + } else if (isFunction(instance.$exceptionHandler)) { + instance.$exceptionHandler(e); } } }, @@ -3395,7 +3397,7 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ }); if (dstName) this.$set(dstName, dst); } - return match; + return match ? dst : null; } }); angularService("$window", bind(window, identity, window)); diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 176d6a91..1739ac4b 100644 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -16,6 +16,7 @@ extend(angular, { 'extend': extend, 'foreach': foreach, 'noop':noop, + 'bind':bind, 'identity':identity, 'isUndefined': isUndefined, 'isDefined': isDefined, diff --git a/src/Scope.js b/src/Scope.js index 7529d726..8d44f4ef 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -117,6 +117,8 @@ function createScope(parent, services, existing) { exceptionHandler(e); } else if (exceptionHandler) { errorHandlerFor(exceptionHandler, e); + } else if (isFunction(instance.$exceptionHandler)) { + instance.$exceptionHandler(e); } } }, diff --git a/src/services.js b/src/services.js index 11453338..90a5bb85 100644 --- a/src/services.js +++ b/src/services.js @@ -137,3 +137,43 @@ angularService("$invalidWidgets", function(){ } return invalidWidgets; }); + +angularService('$route', function(location, params){ + var routes = {}, + onChange = [], + matcher = angularWidget('NG:SWITCH').route, + $route = { + routes: routes, + onChange: bind(onChange, onChange.push), + when:function (path, params){ + if (angular.isUndefined(path)) return routes; + var route = routes[path]; + if (!route) route = routes[path] = {}; + if (params) angular.extend(route, params); + return route; + } + }; + this.$watch(function(){return location.hash;}, function(hash){ + var parentScope = this, childScope; + $route.current = null; + angular.foreach(routes, function(routeParams, route) { + if (!childScope) { + var pathParams = matcher(location.hashPath, route); + if (pathParams) { + childScope = angular.scope(parentScope); + $route.current = angular.extend({}, routeParams, { + scope: childScope, + params: angular.extend({}, location.hashSearch, pathParams) + }); + } + } + }); + angular.foreach(onChange, parentScope.$tryEval); + if (childScope) { + childScope.$become($route.current.controller); + parentScope.$tryEval(childScope.init); + } + }); + return $route; +}, {inject: ['$location']}); + diff --git a/src/widgets.js b/src/widgets.js index 28798c1b..09b602af 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -259,6 +259,6 @@ angularWidget('NG:SWITCH', function ngSwitch(element){ }); if (dstName) this.$set(dstName, dst); } - return match; + return match ? dst : null; } }); diff --git a/test/ScopeSpec.js b/test/ScopeSpec.js index 0665968b..23638b27 100644 --- a/test/ScopeSpec.js +++ b/test/ScopeSpec.js @@ -82,6 +82,16 @@ describe('scope/model', function(){ expect(element.hasClass('ng-exception')).toBeTruthy(); }); + it('should report error on $excetionHandler', function(){ + var element = jqLite('
'); + var scope = createScope(); + scope.$exceptionHandler = function(e){ + this.error = e; + }; + scope.$tryEval('throw "myError"'); + expect(scope.error).toEqual("myError"); + }); + // $onEval it("should eval using priority", function(){ diff --git a/test/angular-mocks.js b/test/angular-mocks.js index 88552aad..3e272313 100644 --- a/test/angular-mocks.js +++ b/test/angular-mocks.js @@ -1,3 +1,26 @@ +/** + * The MIT License + * + * Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ function MockBrowser() { var self = this, expectations = {}, requests = []; diff --git a/test/servicesSpec.js b/test/servicesSpec.js index 618d9a15..715a232e 100644 --- a/test/servicesSpec.js +++ b/test/servicesSpec.js @@ -99,3 +99,41 @@ describe("service $invalidWidgets", function(){ expect(scope.$invalidWidgets.length).toEqual(0); }); }); + +describe("service $route", function(){ + it('should route and fire change event', function(){ + var log = ''; + function BookChapter() { + this.log = '