-
Notifications
You must be signed in to change notification settings - Fork 16
/
observe.js
94 lines (93 loc) · 2.49 KB
/
observe.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* AOP style event handling, for listening for method calls. Very similar to dojo.connect
/* Add a listener for the execution of the given function slot on the given object.
*
* When object[eventName]() is executed the handler is called.
* The optional before parameter can be used to indicate if the listener
* should be fired before or after the default action (default is after)
*/
exports.observe = function(object, eventName, listener, before) {
if(!listener){
throw new Error("No listener provided");
}
if(typeof object.observe === "function"){
// CommonJS observable object
return object.observe(eventName, listener);
}
var listenerProxy = function(that, args){//make sure we have unique function so we can remove it
try{
listener.apply(that, args);
}catch(e){
require("./sys").print(e);
}
};
if(typeof object.addListener === "function"){
// NodeJS EventEmitter
object.addListener(eventName, listener);
return {
observe: function(listener){
return exports.observe(object, eventName, listener);
},
emit: function(event){
object.emit(eventName, event);
},
dismiss: function(){
object.removeListener(eventName, listener);
}
};
}
var afters, befores,
main = object[eventName];
if(typeof main != "function"){
main = function(){};
}
if(main._afters){
afters = main._afters;
befores = main._befores;
}
else{
befores = [];
afters = [];
var newFunc = object[eventName] = function(){
for(var i = 0; i < befores.length; i++){
befores[i](this, arguments);
}
try{
return main.apply(this, arguments);
}
finally{
for(var i = 0; i < afters.length; i++){
afters[i](this, arguments);
}
}
};
newFunc._befores = befores;
newFunc._afters = afters;
}
if(before){
befores.push(listenerProxy);
}
else{
afters.push(listenerProxy);
}
return createSignal();
function createSignal(){
var observers;
return {
observe: function(listener){
afters.push(listener);
},
emit: function(){
main.apply(object, arguments);
},
dismiss: function(){
if(before){
befores.splice(befores.indexOf(listenerProxy), 1);
}
else{
afters.splice(afters.indexOf(listenerProxy), 1);
}
}
};
};
};