d3_rails 2.9.1 → 2.9.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.DS_Store +0 -0
  2. data/Gemfile +0 -1
  3. data/README.md +3 -36
  4. data/lib/.DS_Store +0 -0
  5. data/{vendor/assets/javascripts/morris → lib/d3_rails}/.DS_Store +0 -0
  6. data/lib/d3_rails/version.rb +1 -1
  7. data/vendor/.DS_Store +0 -0
  8. data/vendor/assets/.DS_Store +0 -0
  9. data/vendor/assets/javascripts/.DS_Store +0 -0
  10. data/vendor/assets/javascripts/d3.v2.js +7 -5
  11. data/vendor/assets/stylesheets/.DS_Store +0 -0
  12. metadata +13 -72
  13. data/vendor/assets/javascripts/chart/box.js +0 -297
  14. data/vendor/assets/javascripts/chart/bullet.js +0 -237
  15. data/vendor/assets/javascripts/chart/chart.js +0 -1
  16. data/vendor/assets/javascripts/chart/horizon.js +0 -203
  17. data/vendor/assets/javascripts/chart/qq.js +0 -245
  18. data/vendor/assets/javascripts/d3_chart_module.js +0 -1
  19. data/vendor/assets/javascripts/morris.js +0 -1
  20. data/vendor/assets/javascripts/morris/Makefile +0 -10
  21. data/vendor/assets/javascripts/morris/README.md +0 -87
  22. data/vendor/assets/javascripts/morris/examples/_template.html +0 -18
  23. data/vendor/assets/javascripts/morris/examples/days.html +0 -36
  24. data/vendor/assets/javascripts/morris/examples/decimal.html +0 -31
  25. data/vendor/assets/javascripts/morris/examples/lib/example.css +0 -13
  26. data/vendor/assets/javascripts/morris/examples/lib/example.js +0 -4
  27. data/vendor/assets/javascripts/morris/examples/lib/prettify.css +0 -1
  28. data/vendor/assets/javascripts/morris/examples/lib/prettify.js +0 -28
  29. data/vendor/assets/javascripts/morris/examples/months-no-smooth.html +0 -37
  30. data/vendor/assets/javascripts/morris/examples/negative.html +0 -35
  31. data/vendor/assets/javascripts/morris/examples/non-date.html +0 -36
  32. data/vendor/assets/javascripts/morris/examples/quarters.html +0 -53
  33. data/vendor/assets/javascripts/morris/examples/timestamps.html +0 -37
  34. data/vendor/assets/javascripts/morris/examples/weeks.html +0 -52
  35. data/vendor/assets/javascripts/morris/morris.coffee +0 -444
  36. data/vendor/assets/javascripts/morris/morris.js +0 -493
  37. data/vendor/assets/javascripts/morris/morris.min.js +0 -1
  38. data/vendor/assets/javascripts/tesseract.js +0 -1
  39. data/vendor/assets/javascripts/tesseract/.gitignore +0 -2
  40. data/vendor/assets/javascripts/tesseract/LICENSE +0 -12
  41. data/vendor/assets/javascripts/tesseract/Makefile +0 -48
  42. data/vendor/assets/javascripts/tesseract/README.md +0 -11
  43. data/vendor/assets/javascripts/tesseract/index.js +0 -1
  44. data/vendor/assets/javascripts/tesseract/lib/dart/AUTHORS +0 -9
  45. data/vendor/assets/javascripts/tesseract/lib/dart/LICENSE +0 -25
  46. data/vendor/assets/javascripts/tesseract/lib/dart/dual_pivot_quicksort.dart +0 -342
  47. data/vendor/assets/javascripts/tesseract/package.json +0 -11
  48. data/vendor/assets/javascripts/tesseract/src/array.js +0 -32
  49. data/vendor/assets/javascripts/tesseract/src/bisect.js +0 -44
  50. data/vendor/assets/javascripts/tesseract/src/filter.js +0 -19
  51. data/vendor/assets/javascripts/tesseract/src/heap.js +0 -44
  52. data/vendor/assets/javascripts/tesseract/src/heapselect.js +0 -36
  53. data/vendor/assets/javascripts/tesseract/src/identity.js +0 -3
  54. data/vendor/assets/javascripts/tesseract/src/insertionsort.js +0 -18
  55. data/vendor/assets/javascripts/tesseract/src/null.js +0 -3
  56. data/vendor/assets/javascripts/tesseract/src/package.js +0 -14
  57. data/vendor/assets/javascripts/tesseract/src/permute.js +0 -8
  58. data/vendor/assets/javascripts/tesseract/src/quicksort.js +0 -282
  59. data/vendor/assets/javascripts/tesseract/src/reduce.js +0 -19
  60. data/vendor/assets/javascripts/tesseract/src/tesseract.js +0 -663
  61. data/vendor/assets/javascripts/tesseract/src/version.js +0 -1
  62. data/vendor/assets/javascripts/tesseract/src/zero.js +0 -3
  63. data/vendor/assets/javascripts/tesseract/tesseract.js +0 -1177
  64. data/vendor/assets/javascripts/tesseract/tesseract.min.js +0 -1
  65. data/vendor/assets/javascripts/tesseract/test/benchmark.js +0 -177
  66. data/vendor/assets/javascripts/tesseract/test/bisect-test.js +0 -206
  67. data/vendor/assets/javascripts/tesseract/test/heap-test.js +0 -44
  68. data/vendor/assets/javascripts/tesseract/test/permute-test.js +0 -51
  69. data/vendor/assets/javascripts/tesseract/test/select-test.js +0 -63
  70. data/vendor/assets/javascripts/tesseract/test/sort-test.js +0 -83
  71. data/vendor/assets/javascripts/tesseract/test/tesseract-test.js +0 -655
  72. data/vendor/assets/javascripts/tesseract/test/version-test.js +0 -16
@@ -1,19 +0,0 @@
1
- function tesseract_reduceIncrement(p) {
2
- return p + 1;
3
- }
4
-
5
- function tesseract_reduceDecrement(p) {
6
- return p - 1;
7
- }
8
-
9
- function tesseract_reduceAdd(f) {
10
- return function(p, v) {
11
- return p + +f(v);
12
- };
13
- }
14
-
15
- function tesseract_reduceSubtract(f) {
16
- return function(p, v) {
17
- return p - f(v);
18
- };
19
- }
@@ -1,663 +0,0 @@
1
- exports.tesseract = tesseract;
2
-
3
- function tesseract() {
4
- var tesseract = {
5
- add: add,
6
- dimension: dimension,
7
- groupAll: groupAll,
8
- size: size
9
- };
10
-
11
- var data = [], // the records
12
- n = 0, // the number of records; data.length
13
- m = 0, // number of dimensions in use
14
- M = 8, // number of dimensions that can fit in `filters`
15
- filters = tesseract_array8(0), // M bits per record; 1 is filtered out
16
- filterListeners = [], // when the filters change
17
- dataListeners = []; // when data is added
18
-
19
- // Adds the specified new records to this tesseract.
20
- function add(newData) {
21
- var n0 = n,
22
- n1 = newData.length;
23
-
24
- // If there's actually new data to add…
25
- // Merge the new data into the existing data.
26
- // Lengthen the filter bitset to handle the new records.
27
- // Notify listeners (dimensions and groups) that new data is available.
28
- if (n1) {
29
- data = data.concat(newData);
30
- filters = tesseract_arrayLengthen(filters, n += n1);
31
- dataListeners.forEach(function(l) { l(newData, n0, n1); });
32
- }
33
-
34
- return tesseract;
35
- }
36
-
37
- // Adds a new dimension with the specified value accessor function.
38
- function dimension(value) {
39
- var dimension = {
40
- filter: filter,
41
- filterExact: filterExact,
42
- filterRange: filterRange,
43
- filterAll: filterAll,
44
- top: top,
45
- group: group,
46
- groupAll: groupAll
47
- };
48
-
49
- var one = 1 << m++, // bit mask, e.g., 00001000
50
- zero = ~one, // inverted one, e.g., 11110111
51
- values, // sorted, cached array
52
- index, // value rank ↦ object id
53
- newValues, // temporary array storing newly-added values
54
- newIndex, // temporary array storing newly-added index
55
- sort = quicksort_by(function(i) { return newValues[i]; }),
56
- refilter = tesseract_filterAll, // for recomputing filter
57
- indexListeners = [], // when data is added
58
- lo0 = 0,
59
- hi0 = 0;
60
-
61
- // Updating a dimension is a two-stage process. First, we must update the
62
- // associated filters for the newly-added records. Once all dimensions have
63
- // updated their filters, the groups are notified to update.
64
- dataListeners.unshift(preAdd);
65
- dataListeners.push(postAdd);
66
-
67
- // Incorporate any existing data into this dimension, and make sure that the
68
- // filter bitset is wide enough to handle the new dimension.
69
- if (m > M) filters = tesseract_arrayWiden(filters, M <<= 1);
70
- preAdd(data, 0, n);
71
- postAdd(data, 0, n);
72
-
73
- // Incorporates the specified new records into this dimension.
74
- // This function is responsible for updating filters, values, and index.
75
- function preAdd(newData, n0, n1) {
76
-
77
- // Permute new values into natural order using a sorted index.
78
- newValues = newData.map(value);
79
- newIndex = sort(tesseract_range(n1), 0, n1);
80
- newValues = permute(newValues, newIndex);
81
-
82
- // Bisect newValues to determine which new records are selected.
83
- var bounds = refilter(newValues), lo1 = bounds[0], hi1 = bounds[1], i;
84
- for (i = 0; i < lo1; ++i) filters[newIndex[i] + n0] |= one;
85
- for (i = hi1; i < n1; ++i) filters[newIndex[i] + n0] |= one;
86
-
87
- // If this dimension previously had no data, then we don't need to do the
88
- // more expensive merge operation; use the new values and index as-is.
89
- if (!n0) {
90
- values = newValues;
91
- index = newIndex;
92
- lo0 = lo1;
93
- hi0 = hi1;
94
- return;
95
- }
96
-
97
- var oldValues = values,
98
- oldIndex = index,
99
- i0 = 0,
100
- i1 = 0;
101
-
102
- // Otherwise, create new arrays into which to merge new and old.
103
- values = new Array(n);
104
- index = tesseract_index(n, n);
105
-
106
- // Merge the old and new sorted values, and old and new index.
107
- for (i = 0; i0 < n0 && i1 < n1; ++i) {
108
- if (oldValues[i0] < newValues[i1]) {
109
- values[i] = oldValues[i0];
110
- index[i] = oldIndex[i0++];
111
- } else {
112
- values[i] = newValues[i1];
113
- index[i] = newIndex[i1++] + n0;
114
- }
115
- }
116
-
117
- // Add any remaining old values.
118
- for (; i0 < n0; ++i0, ++i) {
119
- values[i] = oldValues[i0];
120
- index[i] = oldIndex[i0];
121
- }
122
-
123
- // Add any remaining new values.
124
- for (; i1 < n1; ++i1, ++i) {
125
- values[i] = newValues[i1];
126
- index[i] = newIndex[i1] + n0;
127
- }
128
-
129
- // Bisect again to recompute lo0 and hi0.
130
- bounds = refilter(values), lo0 = bounds[0], hi0 = bounds[1];
131
- }
132
-
133
- // When all filters have updated, notify index listeners of the new values.
134
- function postAdd(newData, n0, n1) {
135
- indexListeners.forEach(function(l) { l(newValues, newIndex, n0, n1); });
136
- newValues = newIndex = null;
137
- }
138
-
139
- // Updates the selected values based on the specified bounds [lo, hi].
140
- // This implementation is used by all the public filter methods.
141
- function filterIndex(bounds) {
142
- var i,
143
- j,
144
- k,
145
- lo1 = bounds[0],
146
- hi1 = bounds[1],
147
- added = [],
148
- removed = [];
149
-
150
- // Fast incremental update based on previous lo index.
151
- if (lo1 < lo0) {
152
- for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) {
153
- filters[k = index[i]] ^= one;
154
- added.push(k);
155
- }
156
- } else if (lo1 > lo0) {
157
- for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) {
158
- filters[k = index[i]] ^= one;
159
- removed.push(k);
160
- }
161
- }
162
-
163
- // Fast incremental update based on previous hi index.
164
- if (hi1 > hi0) {
165
- for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) {
166
- filters[k = index[i]] ^= one;
167
- added.push(k);
168
- }
169
- } else if (hi1 < hi0) {
170
- for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) {
171
- filters[k = index[i]] ^= one;
172
- removed.push(k);
173
- }
174
- }
175
-
176
- lo0 = lo1;
177
- hi0 = hi1;
178
- filterListeners.forEach(function(l) { l(one, added, removed); });
179
- return dimension;
180
- }
181
-
182
- // Filters this dimension using the specified range, value, or null.
183
- // If the range is null, this is equivalent to filterAll.
184
- // If the range is an array, this is equivalent to filterRange.
185
- // Otherwise, this is equivalent to filterExact.
186
- function filter(range) {
187
- return range == null
188
- ? filterAll() : Array.isArray(range)
189
- ? filterRange(range)
190
- : filterExact(range);
191
- }
192
-
193
- // Filters this dimension to select the exact value.
194
- function filterExact(value) {
195
- return filterIndex((refilter = tesseract_filterExact(bisect, value))(values));
196
- }
197
-
198
- // Filters this dimension to select the specified range [lo, hi].
199
- // The lower bound is inclusive, and the upper bound is exclusive.
200
- function filterRange(range) {
201
- return filterIndex((refilter = tesseract_filterRange(bisect, range))(values));
202
- }
203
-
204
- // Clears any filters on this dimension.
205
- function filterAll() {
206
- return filterIndex((refilter = tesseract_filterAll)(values));
207
- }
208
-
209
- // Returns the top K selected records, based on this dimension's order.
210
- // Note: observes this dimension's filter, unlike group and groupAll.
211
- function top(k) {
212
- var array = [],
213
- i = hi0,
214
- j;
215
-
216
- while (--i >= lo0 && k > 0) {
217
- if (!filters[j = index[i]]) {
218
- array.push(data[j]);
219
- --k;
220
- }
221
- }
222
-
223
- return array;
224
- }
225
-
226
- // Adds a new group to this dimension, using the specified key function.
227
- function group(key) {
228
- var group = {
229
- top: top,
230
- all: all,
231
- reduce: reduce,
232
- reduceCount: reduceCount,
233
- reduceSum: reduceSum,
234
- order: order,
235
- orderNatural: orderNatural,
236
- size: size
237
- };
238
-
239
- var groups, // array of {key, value}
240
- groupIndex, // object id ↦ group id
241
- groupWidth = 8,
242
- groupCapacity = tesseract_capacity(groupWidth),
243
- k = 0, // cardinality
244
- select,
245
- heap,
246
- reduceAdd,
247
- reduceRemove,
248
- reduceInitial,
249
- update = tesseract_null,
250
- reset = tesseract_null,
251
- resetNeeded = true;
252
-
253
- if (arguments.length < 1) key = tesseract_identity;
254
-
255
- // The group listens to the tesseract for when any dimension changes, so
256
- // that it can update the associated reduce values. It must also listen to
257
- // the parent dimension for when data is added, and compute new keys.
258
- filterListeners.push(update);
259
- indexListeners.push(add);
260
-
261
- // Incorporate any existing data into the grouping.
262
- add(values, index, 0, n);
263
-
264
- // Incorporates the specified new values into this group.
265
- // This function is responsible for updating groups and groupIndex.
266
- function add(newValues, newIndex, n0, n1) {
267
- var oldGroups = groups,
268
- reIndex = tesseract_index(k, groupCapacity),
269
- add = reduceAdd,
270
- initial = reduceInitial,
271
- k0 = k, // old cardinality
272
- i0 = 0, // index of old group
273
- i1 = 0, // index of new record
274
- j, // object id
275
- g0, // old group
276
- x0, // old key
277
- x1, // new key
278
- g, // group to add
279
- x; // key of group to add
280
-
281
- // If a reset is needed, we don't need to update the reduce values.
282
- if (resetNeeded) add = initial = tesseract_null;
283
-
284
- // Reset the new groups (k is a lower bound).
285
- // Also, make sure that groupIndex exists and is long enough.
286
- groups = new Array(k), k = 0;
287
- groupIndex = k0 > 1 ? tesseract_arrayLengthen(groupIndex, n) : tesseract_index(n, groupCapacity);
288
-
289
- // Get the first old key (x0 of g0), if it exists.
290
- if (k0) x0 = (g0 = oldGroups[0]).key;
291
-
292
- // Find the first new key (x1), skipping NaN keys.
293
- while (i1 < n1 && !((x1 = key(newValues[i1])) >= x1)) ++i1;
294
-
295
- // While new keys remain…
296
- while (i1 < n1) {
297
-
298
- // Determine the lesser of the two current keys; new and old.
299
- // If there are no old keys remaining, then always add the new key.
300
- if (g0 && x0 <= x1) {
301
- g = g0, x = x0;
302
-
303
- // Record the new index of the old group.
304
- reIndex[i0] = k;
305
-
306
- // Retrieve the next old key.
307
- if (g0 = oldGroups[++i0]) x0 = g0.key;
308
- } else {
309
- g = {key: x1, value: initial()}, x = x1;
310
- }
311
-
312
- // Add the lesser group.
313
- groups[k] = g;
314
-
315
- // Add any selected records belonging to the added group, while
316
- // advancing the new key and populating the associated group index.
317
- while (!(x1 > x)) {
318
- groupIndex[j = newIndex[i1] + n0] = k;
319
- if (!(filters[j] & zero)) g.value = add(g.value, data[j]);
320
- if (++i1 >= n1) break;
321
- x1 = key(newValues[i1]);
322
- }
323
-
324
- groupIncrement();
325
- }
326
-
327
- // Add any remaining old groups that were greater than all new keys.
328
- // No incremental reduce is needed; these groups have no new records.
329
- // Also record the new index of the old group.
330
- while (i0 < k0) {
331
- groups[reIndex[i0] = k] = oldGroups[i0++];
332
- groupIncrement();
333
- }
334
-
335
- // If we added any new groups before any old groups,
336
- // update the group index of all the old records.
337
- if (k > i0) for (i0 = 0; i0 < n0; ++i0) {
338
- groupIndex[i0] = reIndex[groupIndex[i0]];
339
- }
340
-
341
- // Modify the update and reset behavior based on the cardinality.
342
- // If the cardinality is less than or equal to one, then the groupIndex
343
- // is not needed. If the cardinality is zero, then there are no records
344
- // and therefore no groups to update or reset. Note that we also must
345
- // change the registered listener to point to the new method.
346
- j = filterListeners.indexOf(update);
347
- if (k > 1) {
348
- update = updateMany;
349
- reset = resetMany;
350
- } else {
351
- if (k === 1) {
352
- update = updateOne;
353
- reset = resetOne;
354
- } else {
355
- update = tesseract_null;
356
- reset = tesseract_null;
357
- }
358
- groupIndex = null;
359
- }
360
- filterListeners[j] = update;
361
-
362
- // Count the number of added groups,
363
- // and widen the group index as needed.
364
- function groupIncrement() {
365
- if (++k === groupCapacity) {
366
- reIndex = tesseract_arrayWiden(reIndex, groupWidth <<= 1);
367
- groupIndex = tesseract_arrayWiden(groupIndex, groupWidth);
368
- groupCapacity = tesseract_capacity(groupWidth);
369
- }
370
- }
371
- }
372
-
373
- // Reduces the specified selected or deselected records.
374
- // This function is only used when the cardinality is greater than 1.
375
- function updateMany(filterOne, added, removed) {
376
- if (filterOne === one || resetNeeded) return;
377
-
378
- var i,
379
- k,
380
- n;
381
-
382
- // Add the added values.
383
- for (i = 0, n = added.length; i < n; ++i) {
384
- if (!(filters[k = added[i]] & zero)) {
385
- g = groups[groupIndex[k]];
386
- g.value = reduceAdd(g.value, data[k]);
387
- }
388
- }
389
-
390
- // Remove the removed values.
391
- for (i = 0, n = removed.length; i < n; ++i) {
392
- if ((filters[k = removed[i]] & zero) === filterOne) {
393
- g = groups[groupIndex[k]];
394
- g.value = reduceRemove(g.value, data[k]);
395
- }
396
- }
397
- }
398
-
399
- // Reduces the specified selected or deselected records.
400
- // This function is only used when the cardinality is 1.
401
- function updateOne(filterOne, added, removed) {
402
- if (filterOne === one || resetNeeded) return;
403
-
404
- var i,
405
- k,
406
- n,
407
- g = groups[0];
408
-
409
- // Add the added values.
410
- for (i = 0, n = added.length; i < n; ++i) {
411
- if (!(filters[k = added[i]] & zero)) {
412
- g.value = reduceAdd(g.value, data[k]);
413
- }
414
- }
415
-
416
- // Remove the removed values.
417
- for (i = 0, n = removed.length; i < n; ++i) {
418
- if ((filters[k = removed[i]] & zero) === filterOne) {
419
- g.value = reduceRemove(g.value, data[k]);
420
- }
421
- }
422
- }
423
-
424
- // Recomputes the group reduce values from scratch.
425
- // This function is only used when the cardinality is greater than 1.
426
- function resetMany() {
427
- var i,
428
- g;
429
-
430
- // Reset all group values.
431
- for (i = 0; i < k; ++i) {
432
- groups[i].value = reduceInitial();
433
- }
434
-
435
- // Add any selected records.
436
- for (i = 0; i < n; ++i) {
437
- if (!(filters[i] & zero)) {
438
- g = groups[groupIndex[i]];
439
- g.value = reduceAdd(g.value, data[i]);
440
- }
441
- }
442
- }
443
-
444
- // Recomputes the group reduce values from scratch.
445
- // This function is only used when the cardinality is 1.
446
- function resetOne() {
447
- var i,
448
- g = groups[0];
449
-
450
- // Reset the singleton group values.
451
- g.value = reduceInitial();
452
-
453
- // Add any selected records.
454
- for (i = 0; i < n; ++i) {
455
- if (!(filters[i] & zero)) {
456
- g.value = reduceAdd(g.value, data[i]);
457
- }
458
- }
459
- }
460
-
461
- // Returns the array of group values, in the dimension's natural order.
462
- function all() {
463
- if (resetNeeded) reset(), resetNeeded = false;
464
- return groups;
465
- }
466
-
467
- // Returns a new array containing the top K group values, in reduce order.
468
- function top(k) {
469
- var top = select(all(), 0, groups.length, k);
470
- return heap.sort(top, 0, top.length);
471
- }
472
-
473
- // Sets the reduce behavior for this group to use the specified functions.
474
- // This method lazily recomputes the reduce values, waiting until needed.
475
- function reduce(add, remove, initial) {
476
- reduceAdd = add;
477
- reduceRemove = remove;
478
- reduceInitial = initial;
479
- resetNeeded = true;
480
- return group;
481
- }
482
-
483
- // A convenience method for reducing by count.
484
- function reduceCount() {
485
- return reduce(tesseract_reduceIncrement, tesseract_reduceDecrement, tesseract_zero);
486
- }
487
-
488
- // A convenience method for reducing by sum(value).
489
- function reduceSum(value) {
490
- return reduce(tesseract_reduceAdd(value), tesseract_reduceSubtract(value), tesseract_zero);
491
- }
492
-
493
- // Sets the reduce order, using the specified accessor.
494
- function order(value) {
495
- select = heapselect_by(valueOf);
496
- heap = heap_by(valueOf);
497
- function valueOf(d) { return value(d.value); }
498
- return group;
499
- }
500
-
501
- // A convenience method for natural ordering by reduce value.
502
- function orderNatural() {
503
- return order(tesseract_identity);
504
- }
505
-
506
- // Returns the cardinality of this group, irrespective of any filters.
507
- function size() {
508
- return k;
509
- }
510
-
511
- return reduceCount().orderNatural();
512
- }
513
-
514
- // A convenience function for generating a singleton group.
515
- function groupAll() {
516
- var g = group(tesseract_null), all = g.all;
517
- delete g.all;
518
- delete g.top;
519
- delete g.order;
520
- delete g.orderNatural;
521
- delete g.size;
522
- g.value = function() { return all()[0].value; };
523
- return g;
524
- }
525
-
526
- return dimension;
527
- }
528
-
529
- // A convenience method for groupAll on a dummy dimension.
530
- // This implementation can be optimized since it is always cardinality 1.
531
- function groupAll() {
532
- var group = {
533
- reduce: reduce,
534
- reduceCount: reduceCount,
535
- reduceSum: reduceSum,
536
- value: value
537
- };
538
-
539
- var reduceValue,
540
- reduceAdd,
541
- reduceRemove,
542
- reduceInitial,
543
- resetNeeded = true;
544
-
545
- // The group listens to the tesseract for when any dimension changes, so
546
- // that it can update the reduce value. It must also listen to the parent
547
- // dimension for when data is added.
548
- filterListeners.push(update);
549
- dataListeners.push(add);
550
-
551
- // For consistency; actually a no-op since resetNeeded is true.
552
- add(data, 0, n);
553
-
554
- // Incorporates the specified new values into this group.
555
- function add(newData, n0, n1) {
556
- var i;
557
-
558
- if (resetNeeded) return;
559
-
560
- // Add the added values.
561
- for (i = n0; i < n; ++i) {
562
- if (!filters[i]) {
563
- reduceValue = reduceAdd(reduceValue, data[i]);
564
- }
565
- }
566
- }
567
-
568
- // Reduces the specified selected or deselected records.
569
- function update(filterOne, added, removed) {
570
- var i,
571
- k,
572
- n;
573
-
574
- if (resetNeeded) return;
575
-
576
- // Add the added values.
577
- for (i = 0, n = added.length; i < n; ++i) {
578
- if (!filters[k = added[i]]) {
579
- reduceValue = reduceAdd(reduceValue, data[k]);
580
- }
581
- }
582
-
583
- // Remove the removed values.
584
- for (i = 0, n = removed.length; i < n; ++i) {
585
- if (filters[k = removed[i]] === filterOne) {
586
- reduceValue = reduceRemove(reduceValue, data[k]);
587
- }
588
- }
589
- }
590
-
591
- // Recomputes the group reduce value from scratch.
592
- function reset() {
593
- var i;
594
-
595
- reduceValue = reduceInitial();
596
-
597
- for (i = 0; i < n; ++i) {
598
- if (!filters[i]) {
599
- reduceValue = reduceAdd(reduceValue, data[i]);
600
- }
601
- }
602
- }
603
-
604
- // Sets the reduce behavior for this group to use the specified functions.
605
- // This method lazily recomputes the reduce value, waiting until needed.
606
- function reduce(add, remove, initial) {
607
- reduceAdd = add;
608
- reduceRemove = remove;
609
- reduceInitial = initial;
610
- resetNeeded = true;
611
- return group;
612
- }
613
-
614
- // A convenience method for reducing by count.
615
- function reduceCount() {
616
- return reduce(tesseract_reduceIncrement, tesseract_reduceDecrement, tesseract_zero);
617
- }
618
-
619
- // A convenience method for reducing by sum(value).
620
- function reduceSum(value) {
621
- return reduce(tesseract_reduceAdd(value), tesseract_reduceSubtract(value), tesseract_zero);
622
- }
623
-
624
- // Returns the computed reduce value.
625
- function value() {
626
- if (resetNeeded) reset(), resetNeeded = false;
627
- return reduceValue;
628
- }
629
-
630
- return reduceCount();
631
- }
632
-
633
- // Returns the number of records in this tesseract, irrespective of any filters.
634
- function size() {
635
- return n;
636
- }
637
-
638
- return arguments.length
639
- ? add(arguments[0])
640
- : tesseract;
641
- }
642
-
643
- // Returns an array of size n, big enough to store ids up to m.
644
- function tesseract_index(n, m) {
645
- return (m < 0x101
646
- ? tesseract_array8 : m < 0x10001
647
- ? tesseract_array16
648
- : tesseract_array32)(n);
649
- }
650
-
651
- // Constructs a new array of size n, with sequential values from 0 to n - 1.
652
- function tesseract_range(n) {
653
- var range = tesseract_index(n, n);
654
- for (var i = -1; ++i < n;) range[i] = i;
655
- return range;
656
- }
657
-
658
- function tesseract_capacity(w) {
659
- return w === 8
660
- ? 0x100 : w === 16
661
- ? 0x10000
662
- : 0x100000000;
663
- }