git ssb

1+

Matt McKegg / mutant



Tree: 74b2772da6668585f5a6c10d0e02e7d463880464

Files: 74b2772da6668585f5a6c10d0e02e7d463880464 / array.js

3190 bytesRaw
1var LazyWatcher = require('./lib/lazy-watcher')
2var isReferenceType = require('./lib/is-reference-type')
3var resolve = require('./resolve')
4
5module.exports = Array
6
7function 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.indexOf
57
58 observable.pop = function () {
59 var result = sources.pop()
60 if (binder.live) tryInvoke(releases.pop())
61 object.pop()
62 binder.broadcast()
63 return result
64 }
65
66 observable.shift = function () {
67 var result = sources.shift()
68 if (binder.live) tryInvoke(releases.shift())
69 object.shift()
70 binder.broadcast()
71 return result
72 }
73
74 observable.clear = function () {
75 releases.forEach(tryInvoke)
76 sources.length = 0
77 releases.length = 0
78 object.length = 0
79 binder.broadcast()
80 }
81
82 observable.delete = function (valueOrObs) {
83 var index = sources.indexOf(valueOrObs)
84 if (~index) {
85 sources.splice(index, 1)
86 if (binder.live) releases.splice(index, 1).forEach(tryInvoke)
87 object.splice(index, 1)
88 binder.broadcast()
89 }
90 }
91
92 observable.set = function (values) {
93 unlisten()
94 sources.length = 0
95 releases.length = 0
96 object.length = 0
97 values.forEach(add)
98 if (binder.live) {
99 listen()
100 binder.broadcast()
101 }
102 }
103
104 return observable
105
106 // scoped
107
108 function add (valueOrObs) {
109 sources.push(valueOrObs)
110 if (binder.live) {
111 releases.push(bind(valueOrObs))
112 }
113 object.push(resolve(valueOrObs))
114 }
115
116 function bind (valueOrObs) {
117 return typeof valueOrObs === 'function' ? valueOrObs(binder.onUpdate) : null
118 }
119
120 function listen () {
121 sources.forEach(function (obs, i) {
122 releases[i] = bind(obs)
123 })
124 }
125
126 function unlisten () {
127 releases.forEach(tryInvoke)
128 releases.length = 0
129 }
130
131 function update () {
132 var changed = false
133 sources.forEach(function (key, i) {
134 var newValue = resolve(observable[key])
135 if (newValue !== object[i] || isReferenceType(newValue)) {
136 object[i] = newValue
137 changed = true
138 }
139 })
140 return changed
141 }
142}
143
144function tryInvoke (func) {
145 if (typeof func === 'function') {
146 func()
147 }
148}
149

Built with git-ssb-web