-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
119 lines (92 loc) · 2.05 KB
/
index.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
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
var Emitter = require('emitter')
var methods = {
incr: function (val) {
return this(this.value + (val || 1))
},
toggle: function (val) {
return this(!this.value)
},
change: function(fn) {
fn
? this.on('change', fn) // setup observer
: this.emit('change', this(), this.old)
return this
},
toString: function() {
return "attr:" + JSON.stringify(this.value)
},
'constructor': Attr
}
Emitter(methods)
function extend(a, b) {
for(var i in b) a[i] = b[i]
}
/*
* simple attribute
*/
var watcher = false
function Attr(arg, deps) {
// autocreate computed attr for function values
if(Attr.autocompute && typeof arg == 'function') return Attr.computed(arg, deps)
function attr(v) {
if(arguments.length) {
// setter
attr.old = attr.value
attr.value = v
attr.emit('change', attr.value, attr.old)
}
else {
if(Dependencies.list) Dependencies.list.push(attr)
}
return attr.value
}
// mixin common methods
extend(attr, methods)
// set to initial
attr.value = arg
return attr
}
/*
* Autocompute functions
*/
Attr.autocompute = true
function Dependencies(fn) {
if(Dependencies.list) throw 'nested dependencies'
var deps = Dependencies.list = []
Dependencies.lastValue = fn()
delete Dependencies.list
return deps
}
Attr.dependencies = Dependencies
/*
* computed attribute
*/
Attr.computed = function(fn, deps) {
function attr() {
// nb - there is no setter
attr.old = attr.value
attr.value = fn()
attr.emit('change', attr.value, attr.old)
return attr.value
}
// mixin common methods
extend(attr, methods)
// setup dependencies
if(deps) {
attr.value = fn() // set to initial value
} else {
deps = Dependencies(fn)
attr.value = Dependencies.lastValue
}
attr.dependencies = deps
deps.forEach(function(dep) {
dep.on('change', changeFn)
})
// static change function
function changeFn() {
attr.change()
}
attr.computed = true
return attr
}
module.exports = Attr