-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathObserver.js
More file actions
122 lines (112 loc) · 3.39 KB
/
Observer.js
File metadata and controls
122 lines (112 loc) · 3.39 KB
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* @class Observer
*
* @fires _oa_update ObservableArray change event
* @author Stefano Sergio
*/
//TODO rename in Observer and option in 'observe'
Refuel.define('Observer',{require: ['ObservableArray'], inherits: 'Events'},
function Observer() {
if (this.observe) return;
var mountpoint, label;
var _map = {};
this.getObservers = function() {
return _map;
}
this.clearObservers = function() {
_map = {};
}
this.enableAutoUpdate = function(mpDataSource) {
mountpoint = mpDataSource;
}
function makeObservable(name, value, parent) {
if (name && name != '.') {
var path = name.split('.');
var propName = path[path.length-1];
var resolvedData = Refuel.resolveChain(name, mountpoint, true);
value = resolvedData.value;
parent = resolvedData.parent;
}
else {
parent = this.dataSource; // facciamo mountpoint = ds?
}
//XXX if _map = {} doesnt work the second time you rebind
if (Refuel.refuelClass(parent) == 'DataSource') {
value = parent.data;
propName = 'data';
}
//console.log('makeObservable(resolved):',name);
//Observe an Array
if (Refuel.isArray(value)) {
parent[propName] = Refuel.createInstance('ObservableArray', {'value': value});
makeObservable.call(this, name);
}
//Observe (an already) ObservableArray
else if (Refuel.refuelClass(value) == 'ObservableArray') {
parent[propName].subscribe('_oa_update', function(e) {
e.observer = _map[name];
this.notify('_oa_update', e);
}, this);
}
//Observe an Object
else {
Object.defineProperty(parent, propName, {
configurable: true,
set: function(val) {
//if (_map[name].value !== val) {
_map[name].value = val;
notifyChange(_map[name]);
//}
},
get: function() {
return _map[name].value;
}
});
}
_map[name] = {
'name': name
,'value': value
,'owner': parent
}
return _map[name];
}
function notifyChange(obs) {
var callList = obs['callbackList'];
if (callList && callList.length) {
var len = callList.length;
for (var i = 0, call; call = callList[i]; i++) {
call.callback.call(call.context, obs, call.params);
}
}
}
/**
* this.observe(propName, callback);
* this.observe(propName, data, callback);
**/
this.observe = function(name, data, callback) {
var context = this;
if (!callback) {
callback = data;
data = null;
}
if (!mountpoint) {
console.error('Before making',name,'observable you should enableAutoUpdate on',name,'or it\'s parent');
return;
}
//XXX shouldnt re-make an already observed property, only add callbacks
//but doing this causes the need to reset _map when re-rendering
var callbackList = (_map[name] && _map[name].callbackList) ? _map[name].callbackList : [];
var obj = makeObservable.call(this, name);
obj.callbackList = callbackList;
_map[name] = obj;
// Add Callback
if (callback) {
obj.callbackList.push({
'callback': callback,
'context' : this,
'params' : data
});
}
return obj;
}
});