Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 7a4b480

Browse files
committed
added ng:switch widget
1 parent 4bfa4e2 commit 7a4b480

22 files changed

+198
-190
lines changed

jsTestDriver.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ load:
1111
- src/scenario/_namespace.js
1212
- src/scenario/*.js
1313
- test/testabilityPatch.js
14+
- test/angular-mocks.js
1415
- test/scenario/*.js
1516
- test/*.js
1617

1718
exclude:
1819
- src/angular.prefix
1920
- src/angular.suffix
2021
- src/angular-bootstrap.js
22+
- src/AngularPublic.js

scenario/application-account.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<div>
2+
account page goes here!
3+
</div>
4+

scenario/application.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3+
<head>
4+
<link rel="stylesheet" type="text/css" href="style.css"></link>
5+
<script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
6+
</head>
7+
<body ng-init="$window.$scope = this">
8+
[ <a href="#login">login</a>
9+
| <a href="#account">account</a>
10+
]
11+
12+
<ng:switch on="$location.hashPath">
13+
<div ng-switch-when="login">login screen</div>
14+
<ng:include ng-switch-when="account" src="application-account.html"></ng:include>
15+
</ng:switch>
16+
17+
<pre>$location={{$location}}</pre>
18+
</body>
19+
</html>

src/Angular.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,16 @@ function escapeHtml(html) {
247247
replace(/>/g, '&gt;');
248248
}
249249

250+
251+
function isRenderableElement(element) {
252+
var name = element && element[0] && element[0].nodeName;
253+
return name && name.charAt(0) != '#' &&
254+
!includes(['TR', 'COL', 'COLGROUP', 'TBODY', 'THEAD', 'TFOOT'], name);
255+
}
250256
function elementError(element, type, error) {
257+
while (!isRenderableElement(element)) {
258+
element = element.parent() || jqLite(document.body);
259+
}
251260
if (error) {
252261
element.addClass(type);
253262
element.attr(NG_ERROR, error);

src/AngularPublic.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
var browserSingleton;
2+
angularService('$browser', function browserFactory(){
3+
if (!browserSingleton) {
4+
var XHR = XMLHttpRequest;
5+
if (isUndefined(XHR)) {
6+
XHR = function () {
7+
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
8+
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
9+
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
10+
throw new Error("This browser does not support XMLHttpRequest.");
11+
};
12+
}
13+
browserSingleton = new Browser(window.location, XHR);
14+
browserSingleton.startUrlWatcher();
15+
}
16+
return browserSingleton;
17+
});
18+
19+
extend(angular, {
20+
'element': jqLite,
21+
'compile': compile,
22+
'scope': createScope,
23+
'copy': copy,
24+
'extend': extend,
25+
'foreach': foreach,
26+
'noop':noop,
27+
'identity':identity,
28+
'isUndefined': isUndefined,
29+
'isDefined': isDefined,
30+
'isString': isString,
31+
'isFunction': isFunction,
32+
'isNumber': isNumber,
33+
'isArray': isArray
34+
});
35+

src/Browser.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
// Browser
44
//////////////////////////////
55

6-
function Browser(location) {
6+
function Browser(location, XHR) {
77
this.location = location;
88
this.delay = 25;
9+
this.XHR = XHR;
910
this.setTimeout = function(fn, delay) {
1011
window.setTimeout(fn, delay);
1112
};
@@ -14,6 +15,17 @@ function Browser(location) {
1415
}
1516

1617
Browser.prototype = {
18+
xhr: function(method, url, callback){
19+
var xhr = new this.XHR();
20+
xhr.open(method, url, true);
21+
xhr.onreadystatechange = function() {
22+
if (xhr.readyState == 4) {
23+
callback(xhr.status, xhr.responseText);
24+
}
25+
};
26+
xhr.send('');
27+
},
28+
1729
watchUrl: function(fn){
1830
this.listeners.push(fn);
1931
},
@@ -23,7 +35,11 @@ Browser.prototype = {
2335
(function pull () {
2436
if (self.expectedUrl !== self.location.href) {
2537
foreach(self.listeners, function(listener){
26-
listener(self.location.href);
38+
try {
39+
listener(self.location.href);
40+
} catch (e) {
41+
error(e);
42+
}
2743
});
2844
self.expectedUrl = self.location.href;
2945
}

src/Compiler.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Compiler.prototype = {
7171
$init: function() {
7272
template.init(element, scope);
7373
scope.$eval();
74+
delete scope.$init;
7475
return scope;
7576
}
7677
});

src/Scope.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,8 @@ function parserNewScopeAdapter(fn) {
7070
};
7171
}
7272

73-
function isRenderableElement(element) {
74-
var name = element && element[0] && element[0].nodeName;
75-
return name && name.charAt(0) != '#' &&
76-
!includes(['TR', 'COL', 'COLGROUP', 'TBODY', 'THEAD', 'TFOOT'], name);
77-
}
78-
7973
function rethrow(e) { throw e; }
8074
function errorHandlerFor(element, error) {
81-
while (!isRenderableElement(element)) {
82-
element = element.parent() || jqLite(document.body);
83-
}
8475
elementError(element, NG_EXCEPTION, isDefined(error) ? toJson(error) : error);
8576
}
8677

@@ -132,14 +123,16 @@ function createScope(parent, services, existing) {
132123

133124
$watch: function(watchExp, listener, exceptionHandler) {
134125
var watch = expressionCompile(watchExp),
135-
last = watch.call(instance);
136-
instance.$onEval(PRIORITY_WATCH, function(){
126+
last;
127+
function watcher(){
137128
var value = watch.call(instance);
138129
if (last !== value) {
139130
instance.$tryEval(listener, exceptionHandler, value, last);
140131
last = value;
141132
}
142-
});
133+
}
134+
instance.$onEval(PRIORITY_WATCH, watcher);
135+
watcher();
143136
},
144137

145138
$onEval: function(priority, expr, exceptionHandler){

src/UrlWatcher.js

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/Widgets.js

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -156,40 +156,47 @@ angularWidget('SELECT', function(element){
156156
});
157157

158158

159-
angularWidget('INLINE', function(element){
160-
element.replaceWith(this.element("div"));
159+
angularWidget('NG:INCLUDE', function(element){
161160
var compiler = this,
162-
behavior = element.attr("behavior"),
163-
template = element.attr("template"),
164-
initExpr = element.attr("init");
165-
return function(boundElement){
166-
var scope = this;
167-
boundElement.load(template, function(){
168-
var templateScope = compiler.compile(boundElement)(boundElement, scope);
169-
templateScope.$tryEval(initExpr, boundElement);
170-
templateScope.$init();
161+
src = element.attr("src");
162+
return element.attr('switch-instance') ? null : function(element){
163+
var scope = this, childScope;
164+
element.attr('switch-instance', 'compiled');
165+
scope.$browser.xhr('GET', src, function(code, response){
166+
element.html(response);
167+
childScope = createScope(scope);
168+
compiler.compile(element)(element, childScope);
169+
childScope.$init();
171170
});
171+
scope.$onEval(function(){ if (childScope) childScope.$eval(); });
172172
};
173173
});
174174

175-
angularWidget('INCLUDE', function(element){
176-
element.replaceWith(this.element("div"));
177-
var matches = [];
178-
element.find("INLINE").each(function(){
179-
matches.push({match: jQuery(this).attr("match"), element: jQuery(this)});
180-
});
175+
angularWidget('NG:SWITCH', function(element){
181176
var compiler = this,
182-
watchExpr = element.attr("watch");
183-
return function(boundElement){
177+
watchExpr = element.attr("on"),
178+
cases = [];
179+
eachNode(element, function(caseElement){
180+
var when = caseElement.attr('ng-switch-when');
181+
if (when) {
182+
cases.push({
183+
when: function(value){ return value == when; },
184+
element: caseElement,
185+
template: compiler.compile(caseElement)
186+
});
187+
}
188+
});
189+
element.html('');
190+
return function(element){
184191
var scope = this;
185192
this.$watch(watchExpr, function(value){
186-
foreach(matches, function(inline){
187-
if(inline.match == value) {
188-
var template = inline.element.attr("template");
189-
boundElement.load(template, function(){
190-
var templateScope = compiler.compile(boundElement)(boundElement, scope);
191-
templateScope.$init();
192-
});
193+
element.html('');
194+
foreach(cases, function(switchCase){
195+
if (switchCase.when(value)) {
196+
element.append(switchCase.element);
197+
var childScope = createScope(scope);
198+
switchCase.template(switchCase.element, childScope);
199+
childScope.$init();
193200
}
194201
});
195202
});

src/angular-bootstrap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
addScript("/Parser.js");
4848
addScript("/Resource.js");
4949
addScript("/Browser.js");
50-
addScript("/AngularPublic.js");
50+
addScript("/~AngularPublic.js");
5151

5252
// Extension points
5353
addScript("/apis.js");

src/jqLite.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ JQLite.prototype = {
109109
this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]);
110110
},
111111

112+
append: function(node) {
113+
this[0].appendChild(jqLite(node)[0]);
114+
},
115+
112116
remove: function() {
113117
this.dealoc();
114118
this[0].parentNode.removeChild(this[0]);
@@ -182,6 +186,9 @@ JQLite.prototype = {
182186

183187
html: function(value) {
184188
if (isDefined(value)) {
189+
for ( var i = 0, children = this[0].childNodes; i < children.length; i++) {
190+
jqLite(children[i]).dealoc();
191+
}
185192
this[0].innerHTML = value;
186193
}
187194
return this[0].innerHTML;

src/services.js

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ angularService("$document", function(window){
66
var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.]*)(:([0-9]+))?([^\?#]+)(\?([^#]*))?((#([^\?]*))?(\?([^\?]*))?)$/;
77
var DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21};
88
angularService("$location", function(browser){
9-
var scope = this;
10-
function location(url){
9+
var scope = this, location = {parse:parse, toString:toString};
10+
function parse(url){
1111
if (isDefined(url)) {
1212
var match = URL_MATCH.exec(url);
1313
if (match) {
@@ -23,17 +23,19 @@ angularService("$location", function(browser){
2323
location.hashSearch = parseKeyValue(match[13]);
2424
}
2525
}
26-
var hashKeyValue = toKeyValue(location.hashSearch);
27-
var hash = (location.hashPath ? location.hashPath : '') +
28-
(hashKeyValue ? '?' + hashKeyValue : '');
26+
}
27+
function toString() {
28+
var hashKeyValue = toKeyValue(location.hashSearch),
29+
hash = (location.hashPath ? location.hashPath : '') + (hashKeyValue ? '?' + hashKeyValue : '');
2930
return location.href.split('#')[0] + '#' + (hash ? hash : '');
3031
}
3132
browser.watchUrl(function(url){
32-
location(url);
33+
parse(url);
34+
scope.$root.$eval();
3335
});
34-
location(browser.getUrl());
36+
parse(browser.getUrl());
3537
this.$onEval(PRIORITY_LAST, function(){
36-
var href = location();
38+
var href = toString();
3739
if (href != location.href) {
3840
browser.setUrl(href);
3941
location.href = href;
@@ -42,14 +44,3 @@ angularService("$location", function(browser){
4244
return location;
4345
}, {inject: ['$browser']});
4446

45-
if (!angularService['$browser']) {
46-
var browserSingleton;
47-
angularService('$browser', function browserFactory(){
48-
if (!browserSingleton) {
49-
browserSingleton = new Browser(window.location);
50-
browserSingleton.startUrlWatcher();
51-
}
52-
return browserSingleton;
53-
});
54-
}
55-

0 commit comments

Comments
 (0)