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

Commit 861bac1

Browse files
committed
started to add services
1 parent 35a9108 commit 861bac1

File tree

11 files changed

+251
-132
lines changed

11 files changed

+251
-132
lines changed

src/Angular.js

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ if (typeof document.getAttribute == 'undefined')
44
if (!window['console']) window['console']={'log':noop, 'error':noop};
55

66
var consoleNode,
7+
PRIORITY_FIRST = -99999;
8+
PRIORITY_WATCH = -1000;
9+
PRIORITY_LAST = 99999;
710
NOOP = 'noop',
811
NG_ERROR = 'ng-error',
912
NG_EXCEPTION = 'ng-exception',
@@ -21,11 +24,30 @@ var consoleNode,
2124
angularValidator = extensionMap(angular, 'validator'),
2225
angularFilter = extensionMap(angular, 'filter'),
2326
angularFormatter = extensionMap(angular, 'formatter'),
27+
angularService = extensionMap(angular, 'service'),
2428
angularCallbacks = extensionMap(angular, 'callbacks'),
25-
angularAlert = angular['alert'] || (angular['alert'] = function(){
26-
log(arguments); window.alert.apply(window, arguments);
27-
});
28-
angular['copy'] = copy;
29+
urlWatcher = new UrlWatcher(window.location);
30+
31+
function angularAlert(){
32+
log(arguments); window.alert.apply(window, arguments);
33+
};
34+
35+
extend(angular, {
36+
'compile': compile,
37+
'startUrlWatch': bind(urlWatcher, urlWatcher.start),
38+
'copy': copy,
39+
'extend': extend,
40+
'foreach': foreach,
41+
'noop':noop,
42+
'identity':identity,
43+
'isUndefined': isUndefined,
44+
'isDefined': isDefined,
45+
'isString': isString,
46+
'isFunction': isFunction,
47+
'isNumber': isNumber,
48+
'isArray': isArray,
49+
'alert': angularAlert
50+
});
2951

3052
function foreach(obj, iterator, context) {
3153
var key;
@@ -43,6 +65,17 @@ function foreach(obj, iterator, context) {
4365
return obj;
4466
}
4567

68+
function foreachSorted(obj, iterator, context) {
69+
var keys = [];
70+
for (var key in obj) keys.push(key);
71+
keys.sort();
72+
for ( var i = 0; i < keys.length; i++) {
73+
iterator.call(context, obj[keys[i]], keys[i]);
74+
}
75+
return keys;
76+
}
77+
78+
4679
function extend(dst) {
4780
foreach(arguments, function(obj){
4881
if (obj !== dst) {
@@ -285,19 +318,21 @@ function merge(src, dst) {
285318
}
286319
}
287320

288-
/////////////////////////////////////////////////
289-
290-
angular['compile'] = function(element, config) {
291-
config = extend({
292-
'onUpdateView': noop,
293-
'server': "",
294-
'location': {'get':noop, 'set':noop, 'listen':noop}
295-
}, config||{});
296-
321+
function compile(element, config) {
297322
var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);
298323
$element = jqLite(element),
299-
rootScope = {
300-
'$window': window
301-
};
302-
return rootScope['$root'] = compiler.compile($element)($element, rootScope);
303-
};
324+
rootScope = createScope({
325+
$element: $element,
326+
$config: extend({
327+
'onUpdateView': noop,
328+
'server': "",
329+
'location': {
330+
'get':bind(urlWatcher, urlWatcher.get),
331+
'set':bind(urlWatcher, urlWatcher.set),
332+
'watch':bind(urlWatcher, urlWatcher.watch)
333+
}
334+
}, config || {})
335+
}, serviceAdapter(angularService));
336+
return compiler.compile($element)($element, rootScope);
337+
}
338+
/////////////////////////////////////////////////

src/Compiler.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ Compiler.prototype = {
6565
element = jqLite(element);
6666
parentScope = parentScope || {};
6767
var scope = createScope(parentScope);
68-
parentScope.$root = parentScope.$root || scope;
6968
return extend(scope, {
7069
$element:element,
7170
$init: function() {

src/Parser.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ Lexer.OPERATORS = {
1111
'true':function(self){return true;},
1212
'false':function(self){return false;},
1313
'undefined':noop,
14-
'+':function(self, a,b){return (a||0)+(b||0);},
15-
'-':function(self, a,b){return (a||0)-(b||0);},
14+
'+':function(self, a,b){return (isDefined(a)?a:0)+(isDefined(b)?b:0);},
15+
'-':function(self, a,b){return (isDefined(a)?a:0)-(isDefined(b)?b:0);},
1616
'*':function(self, a,b){return a*b;},
1717
'/':function(self, a,b){return a/b;},
1818
'%':function(self, a,b){return a%b;},

src/Scope.js

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ function createScope(parent, Class) {
8989
function API(){}
9090
function Behavior(){}
9191

92-
var instance, behavior, api, watchList = [], evalList = [];
92+
var instance, behavior, api, evalLists = {};
93+
if (isFunction(parent)) {
94+
Class = parent;
95+
parent = {};
96+
}
9397

9498
Class = Class || noop;
9599
parent = Parent.prototype = parent || {};
@@ -107,15 +111,10 @@ function createScope(parent, Class) {
107111
if (isDefined(exp)) {
108112
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
109113
} else {
110-
foreach(watchList, function(watch) {
111-
var value = instance.$tryEval(watch.watch, watch.handler);
112-
if (watch.last !== value) {
113-
instance.$tryEval(watch.listener, watch.handler, value, watch.last);
114-
watch.last = value;
115-
}
116-
});
117-
foreach(evalList, function(eval) {
118-
instance.$tryEval(eval.fn, eval.handler);
114+
foreachSorted(evalLists, function(list) {
115+
foreach(list, function(eval) {
116+
instance.$tryEval(eval.fn, eval.handler);
117+
});
119118
});
120119
}
121120
},
@@ -134,24 +133,46 @@ function createScope(parent, Class) {
134133
},
135134

136135
$watch: function(watchExp, listener, exceptionHandler) {
137-
var watch = expressionCompile(watchExp);
138-
watchList.push({
139-
watch: watch,
140-
last: watch.call(instance),
141-
handler: exceptionHandler,
142-
listener:expressionCompile(listener)
136+
var watch = expressionCompile(watchExp),
137+
last = watch.call(instance);
138+
instance.$onEval(PRIORITY_WATCH, function(){
139+
var value = watch.call(instance);
140+
if (last !== value) {
141+
instance.$tryEval(listener, exceptionHandler, value, last);
142+
last = value;
143+
}
143144
});
144145
},
145146

146-
$onEval: function(expr, exceptionHandler){
147+
$onEval: function(priority, expr, exceptionHandler){
148+
if (!isNumber(priority)) {
149+
exceptionHandler = expr;
150+
expr = priority;
151+
priority = 0;
152+
}
153+
var evalList = evalLists[priority] || (evalLists[priority] = []);
147154
evalList.push({
148155
fn: expressionCompile(expr),
149156
handler: exceptionHandler
150157
});
151158
}
152159
});
153160

161+
if (isUndefined(instance.$root)) {
162+
behavior.$root = instance;
163+
behavior.$parent = instance;
164+
}
165+
154166
Class.apply(instance, slice.call(arguments, 2, arguments.length));
155167

156168
return instance;
157169
}
170+
171+
function serviceAdapter(services) {
172+
return function(){
173+
var self = this;
174+
foreach(services, function(service, name){
175+
self[name] = service.call(self);
176+
});
177+
};
178+
};

src/UrlWatcher.js

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,26 @@ function UrlWatcher(location) {
99
this.setTimeout = function(fn, delay) {
1010
window.setTimeout(fn, delay);
1111
};
12-
this.listener = function(url) {
13-
return url;
14-
};
1512
this.expectedUrl = location.href;
13+
this.listeners = [];
1614
}
1715

1816
UrlWatcher.prototype = {
19-
listen: function(fn){
20-
this.listener = fn;
17+
watch: function(fn){
18+
this.listeners.push(fn);
2119
},
22-
watch: function() {
20+
21+
start: function() {
2322
var self = this;
24-
var pull = function() {
23+
(function pull () {
2524
if (self.expectedUrl !== self.location.href) {
26-
var notify = self.location.hash.match(/^#\$iframe_notify=(.*)$/);
27-
if (notify) {
28-
if (!self.expectedUrl.match(/#/)) {
29-
self.expectedUrl += "#";
30-
}
31-
self.location.href = self.expectedUrl;
32-
var id = '_iframe_notify_' + notify[1];
33-
var notifyFn = angularCallbacks[id];
34-
delete angularCallbacks[id];
35-
try {
36-
(notifyFn||noop)();
37-
} catch (e) {
38-
alert(e);
39-
}
40-
} else {
41-
self.listener(self.location.href);
42-
self.expectedUrl = self.location.href;
43-
}
25+
foreach(self.listeners, function(listener){
26+
listener(self.location.href);
27+
});
28+
self.expectedUrl = self.location.href;
4429
}
4530
self.setTimeout(pull, self.delay);
46-
};
47-
pull();
31+
})();
4832
},
4933

5034
set: function(url) {
@@ -57,6 +41,6 @@ UrlWatcher.prototype = {
5741
},
5842

5943
get: function() {
60-
return window.location.href;
44+
return this.location.href;
6145
}
6246
};

src/services.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
angularService("$window", bind(window, identity, window));
2+
3+
angularService("$anchor", function(){
4+
var scope = this;
5+
function anchor(url){
6+
if (isDefined(url)) {
7+
if (url.charAt(0) == '#') url = url.substr(1);
8+
var pathQuery = url.split('?');
9+
anchor.path = decodeURIComponent(pathQuery[0]);
10+
anchor.param = {};
11+
foreach((pathQuery[1] || "").split('&'), function(keyValue){
12+
if (keyValue) {
13+
var parts = keyValue.split('=');
14+
var key = decodeURIComponent(parts[0]);
15+
var value = parts[1];
16+
if (!value) value = true;
17+
anchor.param[key] = decodeURIComponent(value);
18+
}
19+
});
20+
}
21+
var params = [];
22+
foreach(anchor.param, function(value, key){
23+
params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
24+
});
25+
return (anchor.path ? anchor.path : '') + (params.length ? '?' + params.join('&') : '');
26+
};
27+
this.$config.location.watch(function(url){
28+
anchor(url);
29+
});
30+
this.$onEval(PRIORITY_LAST, function(){
31+
scope.$config.location.set(anchor());
32+
});
33+
return anchor;
34+
});

test/AngularTest.js

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

test/BinderTest.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -201,24 +201,6 @@ BinderTest.prototype.XtestParseAnchor = function(){
201201
assertTrue(!binder.anchor.x);
202202
};
203203

204-
BinderTest.prototype.XtestWriteAnchor = function(){
205-
var binder = this.compile("<div/>").binder;
206-
binder.location.set('a');
207-
binder.anchor.a = 'b';
208-
binder.anchor.c = ' ';
209-
binder.anchor.d = true;
210-
binder.updateAnchor();
211-
assertEquals(binder.location.get(), "a#a=b&c=%20&d");
212-
};
213-
214-
BinderTest.prototype.XtestWriteAnchorAsPartOfTheUpdateView = function(){
215-
var binder = this.compile("<div/>").binder;
216-
binder.location.set('a');
217-
binder.anchor.a = 'b';
218-
binder.updateView();
219-
assertEquals(binder.location.get(), "a#a=b");
220-
};
221-
222204
BinderTest.prototype.testRepeaterUpdateBindings = function(){
223205
var a = this.compile('<ul><LI ng-repeat="item in model.items" ng-bind="item.a"/></ul>');
224206
var form = a.node;
@@ -821,3 +803,23 @@ BinderTest.prototype.testItShouldUseFormaterForText = function() {
821803
x.scope.$eval();
822804
assertEquals('1, 2, 3', input[0].value);
823805
};
806+
807+
BinderTest.prototype.XtestWriteAnchor = function(){
808+
var binder = this.compile("<div/>").binder;
809+
binder.location.set('a');
810+
binder.anchor.a = 'b';
811+
binder.anchor.c = ' ';
812+
binder.anchor.d = true;
813+
binder.updateAnchor();
814+
assertEquals(binder.location.get(), "a#a=b&c=%20&d");
815+
};
816+
817+
BinderTest.prototype.XtestWriteAnchorAsPartOfTheUpdateView = function(){
818+
var binder = this.compile("<div/>").binder;
819+
binder.location.set('a');
820+
binder.anchor.a = 'b';
821+
binder.updateView();
822+
assertEquals(binder.location.get(), "a#a=b");
823+
};
824+
825+

0 commit comments

Comments
 (0)