Files: 117c25c0033f5aa847498c91de7027643cf61eb7 / array.js
3353 bytesRaw
1 | var LazyWatcher = require('./lib/lazy-watcher') |
2 | var isReferenceType = require('./lib/is-reference-type') |
3 | var resolve = require('./resolve') |
4 | |
5 | module.exports = Array |
6 | |
7 | function Array (defaultValues) { |
8 | var object = [] |
9 | var sources = [] |
10 | var releases = [] |
11 | |
12 | var binder = LazyWatcher(update, listen, unlisten) |
13 | binder.value = object |
14 | |
15 | if (defaultValues && defaultValues.length) { |
16 | defaultValues.forEach(add) |
17 | } |
18 | |
19 | var observable = function MutantArray (listener) { |
20 | if (!listener) { |
21 | return binder.getValue() |
22 | } |
23 | return binder.addListener(listener) |
24 | } |
25 | |
26 | observable.push = function (args) { |
27 | for (var i = 0; i < arguments.length; i++) { |
28 | add(arguments[i]) |
29 | } |
30 | binder.broadcast() |
31 | } |
32 | |
33 | observable.insert = function (valueOrObs, at) { |
34 | sources.splice(at, 0, valueOrObs) |
35 | if (binder.live) releases.splice(at, 0, bind(valueOrObs)) |
36 | object.splice(at, 0, resolve(valueOrObs)) |
37 | binder.broadcast() |
38 | } |
39 | |
40 | observable.get = function (index) { |
41 | return sources[index] |
42 | } |
43 | |
44 | observable.getLength = function (index) { |
45 | return sources.length |
46 | } |
47 | |
48 | observable.includes = function (valueOrObs) { |
49 | return !!~sources.indexOf(valueOrObs) |
50 | } |
51 | |
52 | observable.indexOf = function (valueOrObs) { |
53 | return sources.indexOf(valueOrObs) |
54 | } |
55 | |
56 | observable.forEach = function (fn, context) { |
57 | sources.slice().forEach(fn, context) |
58 | } |
59 | |
60 | observable.find = function (fn) { |
61 | return sources.find(fn) |
62 | } |
63 | |
64 | observable.indexOf |
65 | |
66 | observable.pop = function () { |
67 | var result = sources.pop() |
68 | if (binder.live) tryInvoke(releases.pop()) |
69 | object.pop() |
70 | binder.broadcast() |
71 | return result |
72 | } |
73 | |
74 | observable.shift = function () { |
75 | var result = sources.shift() |
76 | if (binder.live) tryInvoke(releases.shift()) |
77 | object.shift() |
78 | binder.broadcast() |
79 | return result |
80 | } |
81 | |
82 | observable.clear = function () { |
83 | releases.forEach(tryInvoke) |
84 | sources.length = 0 |
85 | releases.length = 0 |
86 | object.length = 0 |
87 | binder.broadcast() |
88 | } |
89 | |
90 | observable.delete = function (valueOrObs) { |
91 | var index = sources.indexOf(valueOrObs) |
92 | if (~index) { |
93 | sources.splice(index, 1) |
94 | if (binder.live) releases.splice(index, 1).forEach(tryInvoke) |
95 | object.splice(index, 1) |
96 | binder.broadcast() |
97 | } |
98 | } |
99 | |
100 | observable.set = function (values) { |
101 | unlisten() |
102 | sources.length = 0 |
103 | releases.length = 0 |
104 | object.length = 0 |
105 | values.forEach(add) |
106 | if (binder.live) { |
107 | listen() |
108 | binder.broadcast() |
109 | } |
110 | } |
111 | |
112 | return observable |
113 | |
114 | // scoped |
115 | |
116 | function add (valueOrObs) { |
117 | sources.push(valueOrObs) |
118 | if (binder.live) { |
119 | releases.push(bind(valueOrObs)) |
120 | } |
121 | object.push(resolve(valueOrObs)) |
122 | } |
123 | |
124 | function bind (valueOrObs) { |
125 | return typeof valueOrObs === 'function' ? valueOrObs(binder.onUpdate) : null |
126 | } |
127 | |
128 | function listen () { |
129 | sources.forEach(function (obs, i) { |
130 | releases[i] = bind(obs) |
131 | }) |
132 | } |
133 | |
134 | function unlisten () { |
135 | releases.forEach(tryInvoke) |
136 | releases.length = 0 |
137 | } |
138 | |
139 | function update () { |
140 | var changed = false |
141 | sources.forEach(function (key, i) { |
142 | var newValue = resolve(observable[key]) |
143 | if (newValue !== object[i] || isReferenceType(newValue)) { |
144 | object[i] = newValue |
145 | changed = true |
146 | } |
147 | }) |
148 | return changed |
149 | } |
150 | } |
151 | |
152 | function tryInvoke (func) { |
153 | if (typeof func === 'function') { |
154 | func() |
155 | } |
156 | } |
157 |
Built with git-ssb-web