aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisko Hevery2010-04-15 14:17:33 -0700
committerMisko Hevery2010-04-15 14:17:33 -0700
commit70e401ef100614295fc808e32f0142f07c315461 (patch)
tree7d31580fb512dd535465e4d42afb0252b0cf0071
parentcd03fe92a5dbd2aba516b64fc8067c5fba1e4a81 (diff)
downloadangular.js-70e401ef100614295fc808e32f0142f07c315461.tar.bz2
added $route service
-rw-r--r--angular-debug.js4
-rw-r--r--src/AngularPublic.js1
-rw-r--r--src/Scope.js2
-rw-r--r--src/services.js40
-rw-r--r--src/widgets.js2
-rw-r--r--test/ScopeSpec.js10
-rw-r--r--test/angular-mocks.js23
-rw-r--r--test/servicesSpec.js38
-rw-r--r--test/testabilityPatch.js27
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('<div></div>');
+ 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 = '<init>';
+ }
+ BookChapter.prototype.init = function(){
+ log += 'init();';
+ };
+ var scope = compile('<div></div>').$init();
+ scope.$route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'});
+ scope.$route.when('/Blank');
+ scope.$route.onChange(function(){
+ log += 'onChange();';
+ });
+ scope.$location.parse('http://server#/Book/Moby/Chapter/Intro?p=123');
+ scope.$eval();
+ expect(log).toEqual('onChange();init();');
+ expect(scope.$route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'});
+ expect(scope.$route.current.scope.log).toEqual('<init>');
+ var lastId = scope.$route.current.scope.$id;
+
+ log = '';
+ scope.$location.parse('http://server#/Blank?ignore');
+ scope.$eval();
+ expect(log).toEqual('onChange();');
+ expect(scope.$route.current.params).toEqual({ignore:true});
+ expect(scope.$route.current.scope.$id).not.toEqual(lastId);
+
+ log = '';
+ scope.$location.parse('http://server#/NONE');
+ scope.$eval();
+ expect(log).toEqual('onChange();');
+ expect(scope.$route.current).toEqual(null);
+
+ });
+});
diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js
index 0c08e39e..89e7d9ea 100644
--- a/test/testabilityPatch.js
+++ b/test/testabilityPatch.js
@@ -64,12 +64,29 @@ function sortedHtml(element) {
}
attrs.sort();
html += attrs.join('');
- if (node.style && node.style.cssText) {
- var style = node.style.cssText.split('; ');
+ if (node.style) {
+ var style = [];
+ if (node.style.cssText) {
+ foreach(node.style.cssText.split(';'), function(value){
+ value = trim(value);
+ if (value) {
+ style.push(value);
+ }
+ });
+ }
+ for(var css in node.style){
+ var value = node.style[css];
+ if (isString(value) && isString(css) && css != 'cssText' && value && (1*css != css)) {
+ var text = css + ': ' + node.style[css];
+ if (indexOf(style, text) == -1) {
+ style.push(text);
+ }
+ }
+ };
style.sort();
- if (style[0] == '')
- style.shift();
- html += ' style="' + style.join('; ') + ';"';
+ if (style.length) {
+ html += ' style="' + style.join('; ') + ';"';
+ }
}
html += '>';
var children = node.childNodes;