Files: b645b2baf1b153c97d7f9d13ee6b47556d710d1c / set.js
2628 bytesRaw
1 | var LazyWatcher = require('./lib/lazy-watcher') |
2 | |
3 | module.exports = Set |
4 | |
5 | function Set (defaultValues) { |
6 | var object = [] |
7 | var sources = [] |
8 | var releases = [] |
9 | |
10 | var binder = LazyWatcher(update, listen, unlisten) |
11 | binder.value = object |
12 | |
13 | if (defaultValues && defaultValues.length) { |
14 | defaultValues.forEach(function (valueOrObs) { |
15 | if (!~sources.indexOf(valueOrObs)) { |
16 | sources.push(valueOrObs) |
17 | } |
18 | }) |
19 | update() |
20 | } |
21 | |
22 | var observable = function MutantSet (listener) { |
23 | if (!listener) { |
24 | return binder.getValue() |
25 | } |
26 | return binder.addListener(listener) |
27 | } |
28 | |
29 | observable.add = function (valueOrObs) { |
30 | if (!~sources.indexOf(valueOrObs)) { |
31 | sources.push(valueOrObs) |
32 | if (binder.live) { |
33 | releases[sources.length - 1] = bind(valueOrObs) |
34 | } |
35 | binder.onUpdate() |
36 | } |
37 | } |
38 | |
39 | observable.clear = function () { |
40 | releases.forEach(tryInvoke) |
41 | sources.length = 0 |
42 | releases.length = 0 |
43 | binder.onUpdate() |
44 | } |
45 | |
46 | observable.delete = function (valueOrObs) { |
47 | var index = sources.indexOf(valueOrObs) |
48 | if (~index) { |
49 | sources.splice(index, 1) |
50 | releases.splice(index, 1).forEach(tryInvoke) |
51 | binder.onUpdate() |
52 | } |
53 | } |
54 | |
55 | observable.has = function (valueOrObs) { |
56 | return !!~object.indexOf(valueOrObs) |
57 | } |
58 | |
59 | observable.set = function (values) { |
60 | sources.length = 0 |
61 | values.forEach(function (value) { |
62 | sources.push(value) |
63 | }) |
64 | binder.onUpdate() |
65 | } |
66 | |
67 | observable.get = function (index) { |
68 | return sources[index] |
69 | } |
70 | |
71 | observable.getLength = function () { |
72 | return sources.length |
73 | } |
74 | |
75 | return observable |
76 | |
77 | function bind (valueOrObs) { |
78 | return typeof valueOrObs === 'function' ? valueOrObs(binder.onUpdate) : null |
79 | } |
80 | |
81 | function listen () { |
82 | sources.forEach(function (obs, i) { |
83 | releases[i] = bind(obs) |
84 | }) |
85 | } |
86 | |
87 | function unlisten () { |
88 | releases.forEach(tryInvoke) |
89 | releases.length = 0 |
90 | } |
91 | |
92 | function update () { |
93 | var currentValues = object.map(get) |
94 | var newValues = sources.map(resolve) |
95 | currentValues.filter(notIncluded, newValues).forEach(removeFrom, object) |
96 | newValues.filter(notIncluded, currentValues).forEach(addTo, object) |
97 | return true |
98 | } |
99 | } |
100 | |
101 | function get (value) { |
102 | return value |
103 | } |
104 | |
105 | function resolve (source) { |
106 | return typeof source === 'function' ? source() : source |
107 | } |
108 | |
109 | function notIncluded (value) { |
110 | return !~this.indexOf(value) |
111 | } |
112 | |
113 | function removeFrom (item) { |
114 | var index = this.indexOf(item) |
115 | if (~index) { |
116 | this.splice(index, 1) |
117 | } |
118 | } |
119 | |
120 | function addTo (item) { |
121 | this.push(item) |
122 | } |
123 | |
124 | function tryInvoke (func) { |
125 | if (typeof func === 'function') { |
126 | func() |
127 | } |
128 | } |
129 |
Built with git-ssb-web