d3_rails 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  module D3Rails
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -1,26 +1,22 @@
1
- (function(){if (!Date.now) Date.now = function() {
2
- return +new Date;
1
+ (function(){d3 = {version: "1.11.0"}; // semver
2
+ if (!Date.now) Date.now = function() {
3
+ return +new Date();
4
+ };
5
+ if (!Object.create) Object.create = function(o) {
6
+ /** @constructor */ function f() {}
7
+ f.prototype = o;
8
+ return new f();
3
9
  };
4
- try {
5
- document.createElement("div").style.setProperty("opacity", 0, "");
6
- } catch (error) {
7
- var d3_style_prototype = CSSStyleDeclaration.prototype,
8
- d3_style_setProperty = d3_style_prototype.setProperty;
9
- d3_style_prototype.setProperty = function(name, value, priority) {
10
- d3_style_setProperty.call(this, name, value + "", priority);
11
- };
12
- }
13
- d3 = {version: "2.4.4"}; // semver
14
10
  var d3_array = d3_arraySlice; // conversion for NodeLists
15
11
 
16
- function d3_arrayCopy(pseudoarray) {
17
- var i = -1, n = pseudoarray.length, array = [];
18
- while (++i < n) array.push(pseudoarray[i]);
12
+ function d3_arrayCopy(psuedoarray) {
13
+ var i = -1, n = psuedoarray.length, array = [];
14
+ while (++i < n) array.push(psuedoarray[i]);
19
15
  return array;
20
16
  }
21
17
 
22
- function d3_arraySlice(pseudoarray) {
23
- return Array.prototype.slice.call(pseudoarray);
18
+ function d3_arraySlice(psuedoarray) {
19
+ return Array.prototype.slice.call(psuedoarray);
24
20
  }
25
21
 
26
22
  try {
@@ -28,23 +24,8 @@ try {
28
24
  } catch(e) {
29
25
  d3_array = d3_arrayCopy;
30
26
  }
31
-
32
- var d3_arraySubclass = [].__proto__?
33
-
34
- // Until ECMAScript supports array subclassing, prototype injection works well.
35
- function(array, prototype) {
36
- array.__proto__ = prototype;
37
- }:
38
-
39
- // And if your browser doesn't support __proto__, we'll use direct extension.
40
- function(array, prototype) {
41
- for (var property in prototype) array[property] = prototype[property];
42
- };
43
- function d3_this() {
44
- return this;
45
- }
46
27
  d3.functor = function(v) {
47
- return typeof v === "function" ? v : function() { return v; };
28
+ return typeof v == "function" ? v : function() { return v; };
48
29
  };
49
30
  // A getter-setter method that preserves the appropriate `this` context.
50
31
  d3.rebind = function(object, method) {
@@ -54,156 +35,34 @@ d3.rebind = function(object, method) {
54
35
  };
55
36
  };
56
37
  d3.ascending = function(a, b) {
57
- return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
38
+ return a < b ? -1 : a > b ? 1 : 0;
58
39
  };
59
40
  d3.descending = function(a, b) {
60
- return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
61
- };
62
- d3.mean = function(array, f) {
63
- var n = array.length,
64
- a,
65
- m = 0,
66
- i = -1,
67
- j = 0;
68
- if (arguments.length === 1) {
69
- while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
70
- } else {
71
- while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
72
- }
73
- return j ? m : undefined;
74
- };
75
- d3.median = function(array, f) {
76
- if (arguments.length > 1) array = array.map(f);
77
- array = array.filter(d3_number);
78
- return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
41
+ return b < a ? -1 : b > a ? 1 : 0;
79
42
  };
80
43
  d3.min = function(array, f) {
81
- var i = -1,
82
- n = array.length,
83
- a,
84
- b;
85
- if (arguments.length === 1) {
86
- while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
87
- while (++i < n) if ((b = array[i]) != null && a > b) a = b;
88
- } else {
89
- while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
90
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
91
- }
92
- return a;
93
- };
94
- d3.max = function(array, f) {
95
- var i = -1,
96
- n = array.length,
97
- a,
98
- b;
99
- if (arguments.length === 1) {
100
- while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
101
- while (++i < n) if ((b = array[i]) != null && b > a) a = b;
102
- } else {
103
- while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
104
- while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
105
- }
106
- return a;
107
- };
108
- function d3_number(x) {
109
- return x != null && !isNaN(x);
110
- }
111
- d3.sum = function(array, f) {
112
- var s = 0,
113
- n = array.length,
114
- a,
115
- i = -1;
116
-
117
- if (arguments.length === 1) {
118
- while (++i < n) if (!isNaN(a = +array[i])) s += a;
119
- } else {
120
- while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
121
- }
122
-
123
- return s;
124
- };
125
- // R-7 per <http://en.wikipedia.org/wiki/Quantile>
126
- d3.quantile = function(values, p) {
127
- var H = (values.length - 1) * p + 1,
128
- h = Math.floor(H),
129
- v = values[h - 1],
130
- e = H - h;
131
- return e ? v + e * (values[h] - v) : v;
132
- };
133
- d3.zip = function() {
134
- if (!(n = arguments.length)) return [];
135
- for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m;) {
136
- for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n;) {
137
- zip[j] = arguments[j][i];
138
- }
139
- }
140
- return zips;
141
- };
142
-
143
- function d3_zipLength(d) {
144
- return d.length;
145
- }
146
- // Locate the insertion point for x in a to maintain sorted order. The
147
- // arguments lo and hi may be used to specify a subset of the array which should
148
- // be considered; by default the entire array is used. If x is already present
149
- // in a, the insertion point will be before (to the left of) any existing
150
- // entries. The return value is suitable for use as the first argument to
151
- // `array.splice` assuming that a is already sorted.
152
- //
153
- // The returned insertion point i partitions the array a into two halves so that
154
- // all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi]
155
- // for the right side.
156
- d3.bisectLeft = function(a, x, lo, hi) {
157
- if (arguments.length < 3) lo = 0;
158
- if (arguments.length < 4) hi = a.length;
159
- while (lo < hi) {
160
- var mid = (lo + hi) >> 1;
161
- if (a[mid] < x) lo = mid + 1;
162
- else hi = mid;
163
- }
164
- return lo;
165
- };
166
-
167
- // Similar to bisectLeft, but returns an insertion point which comes after (to
168
- // the right of) any existing entries of x in a.
169
- //
170
- // The returned insertion point i partitions the array into two halves so that
171
- // all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi]
172
- // for the right side.
173
- d3.bisect =
174
- d3.bisectRight = function(a, x, lo, hi) {
175
- if (arguments.length < 3) lo = 0;
176
- if (arguments.length < 4) hi = a.length;
177
- while (lo < hi) {
178
- var mid = (lo + hi) >> 1;
179
- if (x < a[mid]) hi = mid;
180
- else lo = mid + 1;
181
- }
182
- return lo;
183
- };
184
- d3.first = function(array, f) {
185
44
  var i = 0,
186
45
  n = array.length,
187
46
  a = array[0],
188
47
  b;
189
- if (arguments.length === 1) f = d3.ascending;
190
- while (++i < n) {
191
- if (f.call(array, a, b = array[i]) > 0) {
192
- a = b;
193
- }
48
+ if (arguments.length == 1) {
49
+ while (++i < n) if (a > (b = array[i])) a = b;
50
+ } else {
51
+ a = f(array[0]);
52
+ while (++i < n) if (a > (b = f(array[i]))) a = b;
194
53
  }
195
54
  return a;
196
55
  };
197
- d3.last = function(array, f) {
56
+ d3.max = function(array, f) {
198
57
  var i = 0,
199
58
  n = array.length,
200
59
  a = array[0],
201
60
  b;
202
- if (arguments.length === 1) f = d3.ascending;
203
- while (++i < n) {
204
- if (f.call(array, a, b = array[i]) <= 0) {
205
- a = b;
206
- }
61
+ if (arguments.length == 1) {
62
+ while (++i < n) if (a < (b = array[i])) a = b;
63
+ } else {
64
+ a = f(a);
65
+ while (++i < n) if (a < (b = f(array[i]))) a = b;
207
66
  }
208
67
  return a;
209
68
  };
@@ -309,13 +168,6 @@ d3.entries = function(map) {
309
168
  for (var key in map) entries.push({key: key, value: map[key]});
310
169
  return entries;
311
170
  };
312
- d3.permute = function(array, indexes) {
313
- var permutes = [],
314
- i = -1,
315
- n = indexes.length;
316
- while (++i < n) permutes[i] = array[indexes[i]];
317
- return permutes;
318
- };
319
171
  d3.merge = function(arrays) {
320
172
  return Array.prototype.concat.apply([], arrays);
321
173
  };
@@ -343,19 +195,27 @@ function d3_splitter(d) {
343
195
  function d3_collapse(s) {
344
196
  return s.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " ");
345
197
  }
198
+ //
199
+ // Note: assigning to the arguments array simultaneously changes the value of
200
+ // the corresponding argument!
201
+ //
202
+ // TODO The `this` argument probably shouldn't be the first argument to the
203
+ // callback, anyway, since it's redundant. However, that will require a major
204
+ // version bump due to backwards compatibility, so I'm not changing it right
205
+ // away.
206
+ //
207
+ function d3_call(callback) {
208
+ callback.apply(this, (arguments[0] = this, arguments));
209
+ return this;
210
+ }
346
211
  /**
347
212
  * @param {number} start
348
213
  * @param {number=} stop
349
214
  * @param {number=} step
350
215
  */
351
216
  d3.range = function(start, stop, step) {
352
- if (arguments.length < 3) {
353
- step = 1;
354
- if (arguments.length < 2) {
355
- stop = start;
356
- start = 0;
357
- }
358
- }
217
+ if (arguments.length == 1) { stop = start; start = 0; }
218
+ if (step == null) step = 1;
359
219
  if ((stop - start) / step == Infinity) throw new Error("infinite range");
360
220
  var range = [],
361
221
  i = -1,
@@ -368,19 +228,14 @@ d3.requote = function(s) {
368
228
  return s.replace(d3_requote_re, "\\$&");
369
229
  };
370
230
 
371
- var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
372
- d3.round = function(x, n) {
373
- return n
374
- ? Math.round(x * Math.pow(10, n)) * Math.pow(10, -n)
375
- : Math.round(x);
376
- };
231
+ var d3_requote_re = /[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g;
377
232
  d3.xhr = function(url, mime, callback) {
378
- var req = new XMLHttpRequest;
233
+ var req = new XMLHttpRequest();
379
234
  if (arguments.length < 3) callback = mime;
380
235
  else if (mime && req.overrideMimeType) req.overrideMimeType(mime);
381
236
  req.open("GET", url, true);
382
237
  req.onreadystatechange = function() {
383
- if (req.readyState === 4) callback(req.status < 300 ? req : null);
238
+ if (req.readyState == 4) callback(req.status < 300 ? req : null);
384
239
  };
385
240
  req.send(null);
386
241
  };
@@ -483,7 +338,7 @@ function d3_dispatch(type) {
483
338
 
484
339
  return dispatch;
485
340
  };
486
- // TODO align
341
+ // TODO align, type
487
342
  d3.format = function(specifier) {
488
343
  var match = d3_format_re.exec(specifier),
489
344
  fill = match[1] || " ",
@@ -492,50 +347,23 @@ d3.format = function(specifier) {
492
347
  width = +match[6],
493
348
  comma = match[7],
494
349
  precision = match[8],
495
- type = match[9],
496
- scale = 1,
497
- suffix = "",
498
- integer = false;
499
-
500
- if (precision) precision = +precision.substring(1);
501
-
350
+ type = match[9];
351
+ if (precision) precision = precision.substring(1);
502
352
  if (zfill) {
503
353
  fill = "0"; // TODO align = "=";
504
354
  if (comma) width -= Math.floor((width - 1) / 4);
505
355
  }
506
-
507
- switch (type) {
508
- case "n": comma = true; type = "g"; break;
509
- case "%": scale = 100; suffix = "%"; type = "f"; break;
510
- case "p": scale = 100; suffix = "%"; type = "r"; break;
511
- case "d": integer = true; precision = 0; break;
512
- case "s": scale = -1; type = "r"; break;
513
- }
514
-
515
- // If no precision is specified for r, fallback to general notation.
516
- if (type == "r" && !precision) type = "g";
517
-
518
- type = d3_format_types[type] || d3_format_typeDefault;
519
-
356
+ if (type == "d") precision = "0";
520
357
  return function(value) {
358
+ var number = +value,
359
+ negative = (number < 0) && (number = -number) ? "\u2212" : sign;
521
360
 
522
361
  // Return the empty string for floats formatted as ints.
523
- if (integer && (value % 1)) return "";
524
-
525
- // Convert negative to positive, and record the sign prefix.
526
- var negative = (value < 0) && (value = -value) ? "\u2212" : sign;
527
-
528
- // Apply the scale, computing it from the value's exponent for si format.
529
- if (scale < 0) {
530
- var prefix = d3.formatPrefix(value, precision);
531
- value *= prefix.scale;
532
- suffix = prefix.symbol;
533
- } else {
534
- value *= scale;
535
- }
362
+ if ((type == "d") && (number % 1)) return "";
536
363
 
537
- // Convert to the desired precision.
538
- value = type(value, precision);
364
+ // Convert the input value to the desired precision.
365
+ if (precision) value = number.toFixed(precision);
366
+ else value = "" + number;
539
367
 
540
368
  // If the fill character is 0, the sign and group is applied after the fill.
541
369
  if (zfill) {
@@ -553,28 +381,13 @@ d3.format = function(specifier) {
553
381
  if (length < width) value = new Array(width - length + 1).join(fill) + value;
554
382
  }
555
383
 
556
- return value + suffix;
384
+ return value;
557
385
  };
558
386
  };
559
387
 
560
388
  // [[fill]align][sign][#][0][width][,][.precision][type]
561
389
  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
562
390
 
563
- var d3_format_types = {
564
- g: function(x, p) { return x.toPrecision(p); },
565
- e: function(x, p) { return x.toExponential(p); },
566
- f: function(x, p) { return x.toFixed(p); },
567
- r: function(x, p) { return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); }
568
- };
569
-
570
- function d3_format_precision(x, p) {
571
- return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1);
572
- }
573
-
574
- function d3_format_typeDefault(x) {
575
- return x + "";
576
- }
577
-
578
391
  // Apply comma grouping for thousands.
579
392
  function d3_format_group(value) {
580
393
  var i = value.lastIndexOf("."),
@@ -583,26 +396,6 @@ function d3_format_group(value) {
583
396
  while (i > 0) t.push(value.substring(i -= 3, i + 3));
584
397
  return t.reverse().join(",") + f;
585
398
  }
586
- var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix);
587
-
588
- d3.formatPrefix = function(value, precision) {
589
- var i = 0;
590
- if (value) {
591
- if (value < 0) value *= -1;
592
- if (precision) value = d3.round(value, d3_format_precision(value, precision));
593
- i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
594
- i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
595
- }
596
- return d3_formatPrefixes[8 + i / 3];
597
- };
598
-
599
- function d3_formatPrefix(d, i) {
600
- return {
601
- scale: Math.pow(10, (8 - i) * 3),
602
- symbol: d
603
- };
604
- }
605
-
606
399
  /*
607
400
  * TERMS OF USE - EASING EQUATIONS
608
401
  *
@@ -665,15 +458,9 @@ d3.ease = function(name) {
665
458
  var i = name.indexOf("-"),
666
459
  t = i >= 0 ? name.substring(0, i) : name,
667
460
  m = i >= 0 ? name.substring(i + 1) : "in";
668
- return d3_ease_clamp(d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1))));
461
+ return d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1)));
669
462
  };
670
463
 
671
- function d3_ease_clamp(f) {
672
- return function(t) {
673
- return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
674
- };
675
- }
676
-
677
464
  function d3_ease_reverse(f) {
678
465
  return function(t) {
679
466
  return 1 - f(1 - t);
@@ -701,7 +488,7 @@ function d3_ease_sin(t) {
701
488
  }
702
489
 
703
490
  function d3_ease_exp(t) {
704
- return Math.pow(2, 10 * (t - 1));
491
+ return t ? Math.pow(2, 10 * (t - 1)) - 1e-3 : 0;
705
492
  }
706
493
 
707
494
  function d3_ease_circle(t) {
@@ -733,9 +520,14 @@ function d3_ease_bounce(t) {
733
520
  }
734
521
  d3.event = null;
735
522
  d3.interpolate = function(a, b) {
736
- var i = d3.interpolators.length, f;
737
- while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
738
- return f;
523
+ if (typeof b == "number") return d3.interpolateNumber(+a, b);
524
+ if (typeof b == "string") {
525
+ return (b in d3_rgb_names) || /^(#|rgb\(|hsl\()/.test(b)
526
+ ? d3.interpolateRgb(String(a), b)
527
+ : d3.interpolateString(String(a), b);
528
+ }
529
+ if (b instanceof Array) return d3.interpolateArray(a, b);
530
+ return d3.interpolateObject(a, b);
739
531
  };
740
532
 
741
533
  d3.interpolateNumber = function(a, b) {
@@ -815,7 +607,7 @@ d3.interpolateString = function(a, b) {
815
607
  }
816
608
 
817
609
  // Special optimization for only a single match.
818
- if (s.length === 1) {
610
+ if (s.length == 1) {
819
611
  return s[0] == null ? q[0].x : function() { return b; };
820
612
  }
821
613
 
@@ -836,10 +628,10 @@ d3.interpolateRgb = function(a, b) {
836
628
  bg = b.g - ag,
837
629
  bb = b.b - ab;
838
630
  return function(t) {
839
- return "#"
840
- + d3_rgb_hex(Math.round(ar + br * t))
841
- + d3_rgb_hex(Math.round(ag + bg * t))
842
- + d3_rgb_hex(Math.round(ab + bb * t));
631
+ return "rgb(" + Math.round(ar + br * t)
632
+ + "," + Math.round(ag + bg * t)
633
+ + "," + Math.round(ab + bb * t)
634
+ + ")";
843
635
  };
844
636
  };
845
637
 
@@ -904,76 +696,27 @@ function d3_interpolateByName(n) {
904
696
  ? d3.interpolateRgb
905
697
  : d3.interpolate;
906
698
  }
907
-
908
- d3.interpolators = [
909
- d3.interpolateObject,
910
- function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); },
911
- function(a, b) { return (typeof b === "string") && d3.interpolateString(String(a), b); },
912
- function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(String(a), b); },
913
- function(a, b) { return (typeof b === "number") && d3.interpolateNumber(+a, b); }
914
- ];
915
- function d3_uninterpolateNumber(a, b) {
916
- b = b - (a = +a) ? 1 / (b - a) : 0;
917
- return function(x) { return (x - a) * b; };
918
- }
919
-
920
- function d3_uninterpolateClamp(a, b) {
921
- b = b - (a = +a) ? 1 / (b - a) : 0;
922
- return function(x) { return Math.max(0, Math.min(1, (x - a) * b)); };
923
- }
699
+ /**
700
+ * @param {number=} g
701
+ * @param {number=} b
702
+ */
924
703
  d3.rgb = function(r, g, b) {
925
- return arguments.length === 1
926
- ? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b)
927
- : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
704
+ return arguments.length == 1
705
+ ? d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb)
928
706
  : d3_rgb(~~r, ~~g, ~~b);
929
707
  };
930
708
 
931
709
  function d3_rgb(r, g, b) {
932
- return new d3_Rgb(r, g, b);
933
- }
934
-
935
- function d3_Rgb(r, g, b) {
936
- this.r = r;
937
- this.g = g;
938
- this.b = b;
710
+ return {r: r, g: g, b: b, toString: d3_rgb_format};
939
711
  }
940
712
 
941
- d3_Rgb.prototype.brighter = function(k) {
942
- k = Math.pow(0.7, arguments.length ? k : 1);
943
- var r = this.r,
944
- g = this.g,
945
- b = this.b,
946
- i = 30;
947
- if (!r && !g && !b) return d3_rgb(i, i, i);
948
- if (r && r < i) r = i;
949
- if (g && g < i) g = i;
950
- if (b && b < i) b = i;
951
- return d3_rgb(
952
- Math.min(255, Math.floor(r / k)),
953
- Math.min(255, Math.floor(g / k)),
954
- Math.min(255, Math.floor(b / k)));
955
- };
956
-
957
- d3_Rgb.prototype.darker = function(k) {
958
- k = Math.pow(0.7, arguments.length ? k : 1);
959
- return d3_rgb(
960
- Math.floor(k * this.r),
961
- Math.floor(k * this.g),
962
- Math.floor(k * this.b));
963
- };
964
-
965
- d3_Rgb.prototype.hsl = function() {
966
- return d3_rgb_hsl(this.r, this.g, this.b);
967
- };
968
-
969
- d3_Rgb.prototype.toString = function() {
713
+ /** @this d3_rgb */
714
+ function d3_rgb_format() {
970
715
  return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
971
- };
716
+ }
972
717
 
973
718
  function d3_rgb_hex(v) {
974
- return v < 0x10
975
- ? "0" + Math.max(0, v).toString(16)
976
- : Math.min(255, v).toString(16);
719
+ return v < 0x10 ? "0" + v.toString(16) : v.toString(16);
977
720
  }
978
721
 
979
722
  function d3_rgb_parse(format, rgb, hsl) {
@@ -1010,12 +753,12 @@ function d3_rgb_parse(format, rgb, hsl) {
1010
753
  if (name = d3_rgb_names[format]) return rgb(name.r, name.g, name.b);
1011
754
 
1012
755
  /* Hexadecimal colors: #rgb and #rrggbb. */
1013
- if (format != null && format.charAt(0) === "#") {
1014
- if (format.length === 4) {
756
+ if (format != null && format.charAt(0) == "#") {
757
+ if (format.length == 4) {
1015
758
  r = format.charAt(1); r += r;
1016
759
  g = format.charAt(2); g += g;
1017
760
  b = format.charAt(3); b += b;
1018
- } else if (format.length === 7) {
761
+ } else if (format.length == 7) {
1019
762
  r = format.substring(1, 3);
1020
763
  g = format.substring(3, 5);
1021
764
  b = format.substring(5, 7);
@@ -1049,7 +792,7 @@ function d3_rgb_hsl(r, g, b) {
1049
792
 
1050
793
  function d3_rgb_parseNumber(c) { // either integer or percentage
1051
794
  var f = parseFloat(c);
1052
- return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
795
+ return c.charAt(c.length - 1) == "%" ? Math.round(f * 2.55) : f;
1053
796
  }
1054
797
 
1055
798
  var d3_rgb_names = {
@@ -1208,41 +951,25 @@ for (var d3_rgb_name in d3_rgb_names) {
1208
951
  d3_rgb,
1209
952
  d3_hsl_rgb);
1210
953
  }
954
+ /**
955
+ * @param {number=} s
956
+ * @param {number=} l
957
+ */
1211
958
  d3.hsl = function(h, s, l) {
1212
- return arguments.length === 1
1213
- ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l)
1214
- : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
959
+ return arguments.length == 1
960
+ ? d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl)
1215
961
  : d3_hsl(+h, +s, +l);
1216
962
  };
1217
963
 
1218
964
  function d3_hsl(h, s, l) {
1219
- return new d3_Hsl(h, s, l);
965
+ return {h: h, s: s, l: l, toString: d3_hsl_format};
1220
966
  }
1221
967
 
1222
- function d3_Hsl(h, s, l) {
1223
- this.h = h;
1224
- this.s = s;
1225
- this.l = l;
968
+ /** @this d3_hsl */
969
+ function d3_hsl_format() {
970
+ return "hsl(" + this.h + "," + this.s * 100 + "%," + this.l * 100 + "%)";
1226
971
  }
1227
972
 
1228
- d3_Hsl.prototype.brighter = function(k) {
1229
- k = Math.pow(0.7, arguments.length ? k : 1);
1230
- return d3_hsl(this.h, this.s, this.l / k);
1231
- };
1232
-
1233
- d3_Hsl.prototype.darker = function(k) {
1234
- k = Math.pow(0.7, arguments.length ? k : 1);
1235
- return d3_hsl(this.h, this.s, k * this.l);
1236
- };
1237
-
1238
- d3_Hsl.prototype.rgb = function() {
1239
- return d3_hsl_rgb(this.h, this.s, this.l);
1240
- };
1241
-
1242
- d3_Hsl.prototype.toString = function() {
1243
- return this.rgb().toString();
1244
- };
1245
-
1246
973
  function d3_hsl_rgb(h, s, l) {
1247
974
  var m1,
1248
975
  m2;
@@ -1271,844 +998,898 @@ function d3_hsl_rgb(h, s, l) {
1271
998
 
1272
999
  return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
1273
1000
  }
1274
- function d3_selection(groups) {
1275
- d3_arraySubclass(groups, d3_selectionPrototype);
1276
- return groups;
1277
- }
1278
-
1279
1001
  var d3_select = function(s, n) { return n.querySelector(s); },
1280
- d3_selectAll = function(s, n) { return n.querySelectorAll(s); };
1002
+ d3_selectAll = function(s, n) { return d3_array(n.querySelectorAll(s)); };
1281
1003
 
1282
- // Prefer Sizzle, if available.
1283
- if (typeof Sizzle === "function") {
1004
+ // Use Sizzle, if available.
1005
+ if (typeof Sizzle == "function") {
1284
1006
  d3_select = function(s, n) { return Sizzle(s, n)[0]; };
1285
1007
  d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); };
1286
1008
  }
1287
1009
 
1288
- var d3_selectionPrototype = [];
1010
+ var d3_root = d3_selection([[document]]);
1011
+ d3_root[0].parentNode = document.documentElement;
1012
+
1013
+ // TODO fast singleton implementation!
1014
+ d3.select = function(selector) {
1015
+ return typeof selector == "string"
1016
+ ? d3_root.select(selector)
1017
+ : d3_selection([[selector]]); // assume node
1018
+ };
1289
1019
 
1290
- d3.selection = function() {
1291
- return d3_selectionRoot;
1020
+ d3.selectAll = function(selector) {
1021
+ return typeof selector == "string"
1022
+ ? d3_root.selectAll(selector)
1023
+ : d3_selection([d3_array(selector)]); // assume node[]
1292
1024
  };
1293
1025
 
1294
- d3.selection.prototype = d3_selectionPrototype;
1295
- d3_selectionPrototype.select = function(selector) {
1296
- var subgroups = [],
1297
- subgroup,
1298
- subnode,
1299
- group,
1300
- node;
1301
-
1302
- if (typeof selector !== "function") selector = d3_selection_selector(selector);
1303
-
1304
- for (var j = -1, m = this.length; ++j < m;) {
1305
- subgroups.push(subgroup = []);
1306
- subgroup.parentNode = (group = this[j]).parentNode;
1307
- for (var i = -1, n = group.length; ++i < n;) {
1308
- if (node = group[i]) {
1309
- subgroup.push(subnode = selector.call(node, node.__data__, i));
1310
- if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
1311
- } else {
1312
- subgroup.push(null);
1026
+ function d3_selection(groups) {
1027
+
1028
+ function select(select) {
1029
+ var subgroups = [],
1030
+ subgroup,
1031
+ subnode,
1032
+ group,
1033
+ node;
1034
+ for (var j = 0, m = groups.length; j < m; j++) {
1035
+ group = groups[j];
1036
+ subgroups.push(subgroup = []);
1037
+ subgroup.parentNode = group.parentNode;
1038
+ for (var i = 0, n = group.length; i < n; i++) {
1039
+ if (node = group[i]) {
1040
+ subgroup.push(subnode = select(node));
1041
+ if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
1042
+ } else {
1043
+ subgroup.push(null);
1044
+ }
1045
+ }
1046
+ }
1047
+ return d3_selection(subgroups);
1048
+ }
1049
+
1050
+ function selectAll(selectAll) {
1051
+ var subgroups = [],
1052
+ subgroup,
1053
+ group,
1054
+ node;
1055
+ for (var j = 0, m = groups.length; j < m; j++) {
1056
+ group = groups[j];
1057
+ for (var i = 0, n = group.length; i < n; i++) {
1058
+ if (node = group[i]) {
1059
+ subgroups.push(subgroup = selectAll(node));
1060
+ subgroup.parentNode = node;
1061
+ }
1313
1062
  }
1314
1063
  }
1064
+ return d3_selection(subgroups);
1315
1065
  }
1316
1066
 
1317
- return d3_selection(subgroups);
1318
- };
1067
+ // TODO select(function)?
1068
+ groups.select = function(selector) {
1069
+ return select(function(node) {
1070
+ return d3_select(selector, node);
1071
+ });
1072
+ };
1319
1073
 
1320
- function d3_selection_selector(selector) {
1321
- return function() {
1322
- return d3_select(selector, this);
1074
+ // TODO selectAll(function)?
1075
+ groups.selectAll = function(selector) {
1076
+ return selectAll(function(node) {
1077
+ return d3_selectAll(selector, node);
1078
+ });
1323
1079
  };
1324
- }
1325
- d3_selectionPrototype.selectAll = function(selector) {
1326
- var subgroups = [],
1327
- subgroup,
1328
- node;
1329
-
1330
- if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
1331
-
1332
- for (var j = -1, m = this.length; ++j < m;) {
1333
- for (var group = this[j], i = -1, n = group.length; ++i < n;) {
1334
- if (node = group[i]) {
1335
- subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));
1336
- subgroup.parentNode = node;
1080
+
1081
+ // TODO preserve null elements to maintain index?
1082
+ groups.filter = function(filter) {
1083
+ var subgroups = [],
1084
+ subgroup,
1085
+ group,
1086
+ node;
1087
+ for (var j = 0, m = groups.length; j < m; j++) {
1088
+ group = groups[j];
1089
+ subgroups.push(subgroup = []);
1090
+ subgroup.parentNode = group.parentNode;
1091
+ for (var i = 0, n = group.length; i < n; i++) {
1092
+ if ((node = group[i]) && filter.call(node, node.__data__, i)) {
1093
+ subgroup.push(node);
1094
+ }
1337
1095
  }
1338
1096
  }
1339
- }
1340
-
1341
- return d3_selection(subgroups);
1342
- };
1097
+ return d3_selection(subgroups);
1098
+ };
1343
1099
 
1344
- function d3_selection_selectorAll(selector) {
1345
- return function() {
1346
- return d3_selectAll(selector, this);
1100
+ groups.map = function(map) {
1101
+ var group,
1102
+ node;
1103
+ for (var j = 0, m = groups.length; j < m; j++) {
1104
+ group = groups[j];
1105
+ for (var i = 0, n = group.length; i < n; i++) {
1106
+ if (node = group[i]) node.__data__ = map.call(node, node.__data__, i);
1107
+ }
1108
+ }
1109
+ return groups;
1347
1110
  };
1348
- }
1349
- d3_selectionPrototype.attr = function(name, value) {
1350
- name = d3.ns.qualify(name);
1351
-
1352
- // If no value is specified, return the first value.
1353
- if (arguments.length < 2) {
1354
- var node = this.node();
1355
- return name.local
1356
- ? node.getAttributeNS(name.space, name.local)
1357
- : node.getAttribute(name);
1358
- }
1359
1111
 
1360
- function attrNull() {
1361
- this.removeAttribute(name);
1362
- }
1112
+ // TODO data(null) for clearing data?
1113
+ groups.data = function(data, join) {
1114
+ var enter = [],
1115
+ update = [],
1116
+ exit = [];
1117
+
1118
+ function bind(group, groupData) {
1119
+ var i = 0,
1120
+ n = group.length,
1121
+ m = groupData.length,
1122
+ n0 = Math.min(n, m),
1123
+ n1 = Math.max(n, m),
1124
+ updateNodes = [],
1125
+ enterNodes = [],
1126
+ exitNodes = [],
1127
+ node,
1128
+ nodeData;
1129
+
1130
+ if (join) {
1131
+ var nodeByKey = {},
1132
+ keys = [],
1133
+ key,
1134
+ j = groupData.length;
1135
+
1136
+ for (i = 0; i < n; i++) {
1137
+ key = join.call(node = group[i], node.__data__, i);
1138
+ if (key in nodeByKey) {
1139
+ exitNodes[j++] = group[i]; // duplicate key
1140
+ } else {
1141
+ nodeByKey[key] = node;
1142
+ }
1143
+ keys.push(key);
1144
+ }
1363
1145
 
1364
- function attrNullNS() {
1365
- this.removeAttributeNS(name.space, name.local);
1366
- }
1146
+ for (i = 0; i < m; i++) {
1147
+ node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)];
1148
+ if (node) {
1149
+ node.__data__ = nodeData;
1150
+ updateNodes[i] = node;
1151
+ enterNodes[i] = exitNodes[i] = null;
1152
+ } else {
1153
+ enterNodes[i] = d3_selection_enterNode(nodeData);
1154
+ updateNodes[i] = exitNodes[i] = null;
1155
+ }
1156
+ delete nodeByKey[key];
1157
+ }
1367
1158
 
1368
- function attrConstant() {
1369
- this.setAttribute(name, value);
1370
- }
1159
+ for (i = 0; i < n; i++) {
1160
+ if (keys[i] in nodeByKey) {
1161
+ exitNodes[i] = group[i];
1162
+ }
1163
+ }
1164
+ } else {
1165
+ for (; i < n0; i++) {
1166
+ node = group[i];
1167
+ nodeData = groupData[i];
1168
+ if (node) {
1169
+ node.__data__ = nodeData;
1170
+ updateNodes[i] = node;
1171
+ enterNodes[i] = exitNodes[i] = null;
1172
+ } else {
1173
+ enterNodes[i] = d3_selection_enterNode(nodeData);
1174
+ updateNodes[i] = exitNodes[i] = null;
1175
+ }
1176
+ }
1177
+ for (; i < m; i++) {
1178
+ enterNodes[i] = d3_selection_enterNode(groupData[i]);
1179
+ updateNodes[i] = exitNodes[i] = null;
1180
+ }
1181
+ for (; i < n1; i++) {
1182
+ exitNodes[i] = group[i];
1183
+ enterNodes[i] = updateNodes[i] = null;
1184
+ }
1185
+ }
1371
1186
 
1372
- function attrConstantNS() {
1373
- this.setAttributeNS(name.space, name.local, value);
1374
- }
1187
+ enterNodes.parentNode
1188
+ = updateNodes.parentNode
1189
+ = exitNodes.parentNode
1190
+ = group.parentNode;
1375
1191
 
1376
- function attrFunction() {
1377
- var x = value.apply(this, arguments);
1378
- if (x == null) this.removeAttribute(name);
1379
- else this.setAttribute(name, x);
1380
- }
1192
+ enter.push(enterNodes);
1193
+ update.push(updateNodes);
1194
+ exit.push(exitNodes);
1195
+ }
1381
1196
 
1382
- function attrFunctionNS() {
1383
- var x = value.apply(this, arguments);
1384
- if (x == null) this.removeAttributeNS(name.space, name.local);
1385
- else this.setAttributeNS(name.space, name.local, x);
1386
- }
1197
+ var i = -1,
1198
+ n = groups.length,
1199
+ group;
1200
+ if (typeof data == "function") {
1201
+ while (++i < n) {
1202
+ bind(group = groups[i], data.call(group, group.parentNode.__data__, i));
1203
+ }
1204
+ } else {
1205
+ while (++i < n) {
1206
+ bind(group = groups[i], data);
1207
+ }
1208
+ }
1387
1209
 
1388
- return this.each(value == null
1389
- ? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
1390
- ? (name.local ? attrFunctionNS : attrFunction)
1391
- : (name.local ? attrConstantNS : attrConstant)));
1392
- };
1393
- d3_selectionPrototype.classed = function(name, value) {
1394
- var names = name.split(d3_selection_classedWhitespace),
1395
- n = names.length,
1396
- i = -1;
1397
- if (arguments.length > 1) {
1398
- while (++i < n) d3_selection_classed.call(this, names[i], value);
1399
- return this;
1400
- } else {
1401
- while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false;
1402
- return true;
1210
+ var selection = d3_selection(update);
1211
+ selection.enter = function() {
1212
+ return d3_selectionEnter(enter);
1213
+ };
1214
+ selection.exit = function() {
1215
+ return d3_selection(exit);
1216
+ };
1217
+ return selection;
1218
+ };
1219
+
1220
+ // TODO mask forEach? or rename for eachData?
1221
+ // TODO offer the same semantics for map, reduce, etc.?
1222
+ groups.each = function(callback) {
1223
+ for (var j = 0, m = groups.length; j < m; j++) {
1224
+ var group = groups[j];
1225
+ for (var i = 0, n = group.length; i < n; i++) {
1226
+ var node = group[i];
1227
+ if (node) callback.call(node, node.__data__, i);
1228
+ }
1229
+ }
1230
+ return groups;
1231
+ };
1232
+
1233
+ function first(callback) {
1234
+ for (var j = 0, m = groups.length; j < m; j++) {
1235
+ var group = groups[j];
1236
+ for (var i = 0, n = group.length; i < n; i++) {
1237
+ var node = group[i];
1238
+ if (node) return callback.call(node, node.__data__, i);
1239
+ }
1240
+ }
1241
+ return null;
1403
1242
  }
1404
- };
1405
1243
 
1406
- var d3_selection_classedWhitespace = /\s+/g;
1244
+ groups.empty = function() {
1245
+ return !first(function() { return true; });
1246
+ };
1407
1247
 
1408
- function d3_selection_classed(name, value) {
1409
- var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
1248
+ groups.node = function() {
1249
+ return first(function() { return this; });
1250
+ };
1410
1251
 
1411
- // If no value is specified, return the first value.
1412
- if (arguments.length < 2) {
1413
- var node = this.node();
1414
- if (c = node.classList) return c.contains(name);
1415
- var c = node.className;
1416
- re.lastIndex = 0;
1417
- return re.test(c.baseVal != null ? c.baseVal : c);
1418
- }
1252
+ groups.attr = function(name, value) {
1253
+ name = d3.ns.qualify(name);
1419
1254
 
1420
- function classedAdd() {
1421
- if (c = this.classList) return c.add(name);
1422
- var c = this.className,
1423
- cb = c.baseVal != null,
1424
- cv = cb ? c.baseVal : c;
1425
- re.lastIndex = 0;
1426
- if (!re.test(cv)) {
1427
- cv = d3_collapse(cv + " " + name);
1428
- if (cb) c.baseVal = cv;
1429
- else this.className = cv;
1255
+ // If no value is specified, return the first value.
1256
+ if (arguments.length < 2) {
1257
+ return first(name.local
1258
+ ? function() { return this.getAttributeNS(name.space, name.local); }
1259
+ : function() { return this.getAttribute(name); });
1430
1260
  }
1431
- }
1432
1261
 
1433
- function classedRemove() {
1434
- if (c = this.classList) return c.remove(name);
1435
- var c = this.className,
1436
- cb = c.baseVal != null,
1437
- cv = cb ? c.baseVal : c;
1438
- cv = d3_collapse(cv.replace(re, " "));
1439
- if (cb) c.baseVal = cv;
1440
- else this.className = cv;
1441
- }
1262
+ /** @this {Element} */
1263
+ function attrNull() {
1264
+ this.removeAttribute(name);
1265
+ }
1442
1266
 
1443
- function classedFunction() {
1444
- (value.apply(this, arguments)
1445
- ? classedAdd
1446
- : classedRemove).call(this);
1447
- }
1267
+ /** @this {Element} */
1268
+ function attrNullNS() {
1269
+ this.removeAttributeNS(name.space, name.local);
1270
+ }
1448
1271
 
1449
- return this.each(typeof value === "function"
1450
- ? classedFunction : value
1451
- ? classedAdd
1452
- : classedRemove);
1453
- }
1454
- d3_selectionPrototype.style = function(name, value, priority) {
1455
- if (arguments.length < 3) priority = "";
1272
+ /** @this {Element} */
1273
+ function attrConstant() {
1274
+ this.setAttribute(name, value);
1275
+ }
1456
1276
 
1457
- // If no value is specified, return the first value.
1458
- if (arguments.length < 2) return window
1459
- .getComputedStyle(this.node(), null)
1460
- .getPropertyValue(name);
1277
+ /** @this {Element} */
1278
+ function attrConstantNS() {
1279
+ this.setAttributeNS(name.space, name.local, value);
1280
+ }
1461
1281
 
1462
- function styleNull() {
1463
- this.style.removeProperty(name);
1464
- }
1282
+ /** @this {Element} */
1283
+ function attrFunction() {
1284
+ var x = value.apply(this, arguments);
1285
+ if (x == null) this.removeAttribute(name);
1286
+ else this.setAttribute(name, x);
1287
+ }
1465
1288
 
1466
- function styleConstant() {
1467
- this.style.setProperty(name, value, priority);
1468
- }
1289
+ /** @this {Element} */
1290
+ function attrFunctionNS() {
1291
+ var x = value.apply(this, arguments);
1292
+ if (x == null) this.removeAttributeNS(name.space, name.local);
1293
+ else this.setAttributeNS(name.space, name.local, x);
1294
+ }
1469
1295
 
1470
- function styleFunction() {
1471
- var x = value.apply(this, arguments);
1472
- if (x == null) this.style.removeProperty(name);
1473
- else this.style.setProperty(name, x, priority);
1474
- }
1296
+ return groups.each(value == null
1297
+ ? (name.local ? attrNullNS : attrNull) : (typeof value == "function"
1298
+ ? (name.local ? attrFunctionNS : attrFunction)
1299
+ : (name.local ? attrConstantNS : attrConstant)));
1300
+ };
1475
1301
 
1476
- return this.each(value == null
1477
- ? styleNull : (typeof value === "function"
1478
- ? styleFunction : styleConstant));
1479
- };
1480
- d3_selectionPrototype.property = function(name, value) {
1302
+ groups.classed = function(name, value) {
1303
+ var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
1481
1304
 
1482
- // If no value is specified, return the first value.
1483
- if (arguments.length < 2) return this.node()[name];
1305
+ // If no value is specified, return the first value.
1306
+ if (arguments.length < 2) {
1307
+ return first(function() {
1308
+ re.lastIndex = 0;
1309
+ return re.test(this.className);
1310
+ });
1311
+ }
1484
1312
 
1485
- function propertyNull() {
1486
- delete this[name];
1487
- }
1313
+ /** @this {Element} */
1314
+ function classedAdd() {
1315
+ var classes = this.className;
1316
+ re.lastIndex = 0;
1317
+ if (!re.test(classes)) {
1318
+ this.className = d3_collapse(classes + " " + name);
1319
+ }
1320
+ }
1488
1321
 
1489
- function propertyConstant() {
1490
- this[name] = value;
1491
- }
1322
+ /** @this {Element} */
1323
+ function classedRemove() {
1324
+ var classes = d3_collapse(this.className.replace(re, " "));
1325
+ this.className = classes.length ? classes : null;
1326
+ }
1492
1327
 
1493
- function propertyFunction() {
1494
- var x = value.apply(this, arguments);
1495
- if (x == null) delete this[name];
1496
- else this[name] = x;
1497
- }
1328
+ /** @this {Element} */
1329
+ function classedFunction() {
1330
+ (value.apply(this, arguments)
1331
+ ? classedAdd
1332
+ : classedRemove).call(this);
1333
+ }
1498
1334
 
1499
- return this.each(value == null
1500
- ? propertyNull : (typeof value === "function"
1501
- ? propertyFunction : propertyConstant));
1502
- };
1503
- d3_selectionPrototype.text = function(value) {
1504
- return arguments.length < 1 ? this.node().textContent
1505
- : (this.each(typeof value === "function"
1506
- ? function() { this.textContent = value.apply(this, arguments); }
1507
- : function() { this.textContent = value; }));
1508
- };
1509
- d3_selectionPrototype.html = function(value) {
1510
- return arguments.length < 1 ? this.node().innerHTML
1511
- : (this.each(typeof value === "function"
1512
- ? function() { this.innerHTML = value.apply(this, arguments); }
1513
- : function() { this.innerHTML = value; }));
1514
- };
1515
- // TODO append(node)?
1516
- // TODO append(function)?
1517
- d3_selectionPrototype.append = function(name) {
1518
- name = d3.ns.qualify(name);
1335
+ return groups.each(typeof value == "function"
1336
+ ? classedFunction : value
1337
+ ? classedAdd
1338
+ : classedRemove);
1339
+ };
1519
1340
 
1520
- function append() {
1521
- return this.appendChild(document.createElement(name));
1522
- }
1341
+ groups.style = function(name, value, priority) {
1342
+ if (arguments.length < 3) priority = null;
1523
1343
 
1524
- function appendNS() {
1525
- return this.appendChild(document.createElementNS(name.space, name.local));
1526
- }
1344
+ // If no value is specified, return the first value.
1345
+ if (arguments.length < 2) {
1346
+ return first(function() {
1347
+ return window.getComputedStyle(this, null).getPropertyValue(name);
1348
+ });
1349
+ }
1527
1350
 
1528
- return this.select(name.local ? appendNS : append);
1529
- };
1530
- // TODO insert(node, function)?
1531
- // TODO insert(function, string)?
1532
- // TODO insert(function, function)?
1533
- d3_selectionPrototype.insert = function(name, before) {
1534
- name = d3.ns.qualify(name);
1535
-
1536
- function insert() {
1537
- return this.insertBefore(
1538
- document.createElement(name),
1539
- d3_select(before, this));
1540
- }
1351
+ /** @this {Element} */
1352
+ function styleNull() {
1353
+ this.style.removeProperty(name);
1354
+ }
1541
1355
 
1542
- function insertNS() {
1543
- return this.insertBefore(
1544
- document.createElementNS(name.space, name.local),
1545
- d3_select(before, this));
1546
- }
1356
+ /** @this {Element} */
1357
+ function styleConstant() {
1358
+ this.style.setProperty(name, value, priority);
1359
+ }
1547
1360
 
1548
- return this.select(name.local ? insertNS : insert);
1549
- };
1550
- // TODO remove(selector)?
1551
- // TODO remove(node)?
1552
- // TODO remove(function)?
1553
- d3_selectionPrototype.remove = function() {
1554
- return this.each(function() {
1555
- var parent = this.parentNode;
1556
- if (parent) parent.removeChild(this);
1557
- });
1558
- };
1559
- // TODO data(null) for clearing data?
1560
- d3_selectionPrototype.data = function(data, join) {
1561
- var enter = [],
1562
- update = [],
1563
- exit = [];
1564
-
1565
- function bind(group, groupData) {
1566
- var i,
1567
- n = group.length,
1568
- m = groupData.length,
1569
- n0 = Math.min(n, m),
1570
- n1 = Math.max(n, m),
1571
- updateNodes = [],
1572
- enterNodes = [],
1573
- exitNodes = [],
1574
- node,
1575
- nodeData;
1576
-
1577
- if (join) {
1578
- var nodeByKey = {},
1579
- keys = [],
1580
- key,
1581
- j = groupData.length;
1582
-
1583
- for (i = -1; ++i < n;) {
1584
- key = join.call(node = group[i], node.__data__, i);
1585
- if (key in nodeByKey) {
1586
- exitNodes[j++] = node; // duplicate key
1587
- } else {
1588
- nodeByKey[key] = node;
1589
- }
1590
- keys.push(key);
1591
- }
1361
+ /** @this {Element} */
1362
+ function styleFunction() {
1363
+ var x = value.apply(this, arguments);
1364
+ if (x == null) this.style.removeProperty(name);
1365
+ else this.style.setProperty(name, x, priority);
1366
+ }
1592
1367
 
1593
- for (i = -1; ++i < m;) {
1594
- node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)];
1595
- if (node) {
1596
- node.__data__ = nodeData;
1597
- updateNodes[i] = node;
1598
- enterNodes[i] = exitNodes[i] = null;
1599
- } else {
1600
- enterNodes[i] = d3_selection_dataNode(nodeData);
1601
- updateNodes[i] = exitNodes[i] = null;
1602
- }
1603
- delete nodeByKey[key];
1604
- }
1605
-
1606
- for (i = -1; ++i < n;) {
1607
- if (keys[i] in nodeByKey) {
1608
- exitNodes[i] = group[i];
1609
- }
1610
- }
1611
- } else {
1612
- for (i = -1; ++i < n0;) {
1613
- node = group[i];
1614
- nodeData = groupData[i];
1615
- if (node) {
1616
- node.__data__ = nodeData;
1617
- updateNodes[i] = node;
1618
- enterNodes[i] = exitNodes[i] = null;
1619
- } else {
1620
- enterNodes[i] = d3_selection_dataNode(nodeData);
1621
- updateNodes[i] = exitNodes[i] = null;
1622
- }
1623
- }
1624
- for (; i < m; ++i) {
1625
- enterNodes[i] = d3_selection_dataNode(groupData[i]);
1626
- updateNodes[i] = exitNodes[i] = null;
1627
- }
1628
- for (; i < n1; ++i) {
1629
- exitNodes[i] = group[i];
1630
- enterNodes[i] = updateNodes[i] = null;
1631
- }
1632
- }
1368
+ return groups.each(value == null
1369
+ ? styleNull : (typeof value == "function"
1370
+ ? styleFunction : styleConstant));
1371
+ };
1633
1372
 
1634
- enterNodes.update
1635
- = updateNodes;
1373
+ groups.property = function(name, value) {
1374
+ name = d3.ns.qualify(name);
1636
1375
 
1637
- enterNodes.parentNode
1638
- = updateNodes.parentNode
1639
- = exitNodes.parentNode
1640
- = group.parentNode;
1376
+ // If no value is specified, return the first value.
1377
+ if (arguments.length < 2) {
1378
+ return first(function() {
1379
+ return this[name];
1380
+ });
1381
+ }
1641
1382
 
1642
- enter.push(enterNodes);
1643
- update.push(updateNodes);
1644
- exit.push(exitNodes);
1645
- }
1383
+ /** @this {Element} */
1384
+ function propertyNull() {
1385
+ delete this[name];
1386
+ }
1646
1387
 
1647
- var i = -1,
1648
- n = this.length,
1649
- group;
1650
- if (typeof data === "function") {
1651
- while (++i < n) {
1652
- bind(group = this[i], data.call(group, group.parentNode.__data__, i));
1388
+ /** @this {Element} */
1389
+ function propertyConstant() {
1390
+ this[name] = value;
1653
1391
  }
1654
- } else {
1655
- while (++i < n) {
1656
- bind(group = this[i], data);
1392
+
1393
+ /** @this {Element} */
1394
+ function propertyFunction() {
1395
+ var x = value.apply(this, arguments);
1396
+ if (x == null) delete this[name];
1397
+ else this[name] = x;
1657
1398
  }
1658
- }
1659
1399
 
1660
- var selection = d3_selection(update);
1661
- selection.enter = function() { return d3_selection_enter(enter); };
1662
- selection.exit = function() { return d3_selection(exit); };
1663
- return selection;
1664
- };
1400
+ return groups.each(value == null
1401
+ ? propertyNull : (typeof value == "function"
1402
+ ? propertyFunction : propertyConstant));
1403
+ };
1665
1404
 
1666
- function d3_selection_dataNode(data) {
1667
- return {__data__: data};
1668
- }
1669
- function d3_selection_enter(selection) {
1670
- d3_arraySubclass(selection, d3_selection_enterPrototype);
1671
- return selection;
1672
- }
1405
+ groups.text = function(value) {
1673
1406
 
1674
- var d3_selection_enterPrototype = [];
1675
-
1676
- d3_selection_enterPrototype.append = d3_selectionPrototype.append;
1677
- d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;
1678
- d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
1679
- d3_selection_enterPrototype.select = function(selector) {
1680
- var subgroups = [],
1681
- subgroup,
1682
- subnode,
1683
- upgroup,
1684
- group,
1685
- node;
1686
-
1687
- for (var j = -1, m = this.length; ++j < m;) {
1688
- upgroup = (group = this[j]).update;
1689
- subgroups.push(subgroup = []);
1690
- subgroup.parentNode = group.parentNode;
1691
- for (var i = -1, n = group.length; ++i < n;) {
1692
- if (node = group[i]) {
1693
- subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));
1694
- subnode.__data__ = node.__data__;
1695
- } else {
1696
- subgroup.push(null);
1697
- }
1407
+ // If no value is specified, return the first value.
1408
+ if (arguments.length < 1) {
1409
+ return first(function() {
1410
+ return this.textContent;
1411
+ });
1698
1412
  }
1699
- }
1700
1413
 
1701
- return d3_selection(subgroups);
1702
- };
1703
- // TODO preserve null elements to maintain index?
1704
- d3_selectionPrototype.filter = function(filter) {
1705
- var subgroups = [],
1706
- subgroup,
1707
- group,
1708
- node;
1709
-
1710
- for (var j = 0, m = this.length; j < m; j++) {
1711
- subgroups.push(subgroup = []);
1712
- subgroup.parentNode = (group = this[j]).parentNode;
1713
- for (var i = 0, n = group.length; i < n; i++) {
1714
- if ((node = group[i]) && filter.call(node, node.__data__, i)) {
1715
- subgroup.push(node);
1716
- }
1414
+ /** @this {Element} */
1415
+ function textConstant() {
1416
+ this.textContent = value;
1717
1417
  }
1718
- }
1719
1418
 
1720
- return d3_selection(subgroups);
1721
- };
1722
- d3_selectionPrototype.map = function(map) {
1723
- return this.each(function() {
1724
- this.__data__ = map.apply(this, arguments);
1725
- });
1726
- };
1727
- d3_selectionPrototype.sort = function(comparator) {
1728
- comparator = d3_selection_sortComparator.apply(this, arguments);
1729
- for (var j = 0, m = this.length; j < m; j++) {
1730
- for (var group = this[j].sort(comparator), i = 1, n = group.length, prev = group[0]; i < n; i++) {
1731
- var node = group[i];
1732
- if (node) {
1733
- if (prev) prev.parentNode.insertBefore(node, prev.nextSibling);
1734
- prev = node;
1735
- }
1419
+ /** @this {Element} */
1420
+ function textFunction() {
1421
+ this.textContent = value.apply(this, arguments);
1736
1422
  }
1737
- }
1738
- return this;
1739
- };
1740
1423
 
1741
- function d3_selection_sortComparator(comparator) {
1742
- if (!arguments.length) comparator = d3.ascending;
1743
- return function(a, b) {
1744
- return comparator(a && a.__data__, b && b.__data__);
1424
+ return groups.each(typeof value == "function"
1425
+ ? textFunction : textConstant);
1745
1426
  };
1746
- }
1747
- // type can be namespaced, e.g., "click.foo"
1748
- // listener can be null for removal
1749
- d3_selectionPrototype.on = function(type, listener, capture) {
1750
- if (arguments.length < 3) capture = false;
1751
-
1752
- // parse the type specifier
1753
- var name = "__on" + type, i = type.indexOf(".");
1754
- if (i > 0) type = type.substring(0, i);
1755
-
1756
- // if called with only one argument, return the current listener
1757
- if (arguments.length < 2) return (i = this.node()[name]) && i._;
1758
-
1759
- // remove the old event listener, and add the new event listener
1760
- return this.each(function(d, i) {
1761
- var node = this;
1762
-
1763
- if (node[name]) node.removeEventListener(type, node[name], capture);
1764
- if (listener) node.addEventListener(type, node[name] = l, capture);
1765
-
1766
- // wrapped event listener that preserves i
1767
- function l(e) {
1768
- var o = d3.event; // Events can be reentrant (e.g., focus).
1769
- d3.event = e;
1770
- try {
1771
- listener.call(node, node.__data__, i);
1772
- } finally {
1773
- d3.event = o;
1774
- }
1775
- }
1776
1427
 
1777
- // stash the unwrapped listener for retrieval
1778
- l._ = listener;
1779
- });
1780
- };
1781
- d3_selectionPrototype.each = function(callback) {
1782
- for (var j = -1, m = this.length; ++j < m;) {
1783
- for (var group = this[j], i = -1, n = group.length; ++i < n;) {
1784
- var node = group[i];
1785
- if (node) callback.call(node, node.__data__, i, j);
1428
+ groups.html = function(value) {
1429
+
1430
+ // If no value is specified, return the first value.
1431
+ if (arguments.length < 1) {
1432
+ return first(function() {
1433
+ return this.innerHTML;
1434
+ });
1786
1435
  }
1787
- }
1788
- return this;
1789
- };
1790
- //
1791
- // Note: assigning to the arguments array simultaneously changes the value of
1792
- // the corresponding argument!
1793
- //
1794
- // TODO The `this` argument probably shouldn't be the first argument to the
1795
- // callback, anyway, since it's redundant. However, that will require a major
1796
- // version bump due to backwards compatibility, so I'm not changing it right
1797
- // away.
1798
- //
1799
- d3_selectionPrototype.call = function(callback) {
1800
- callback.apply(this, (arguments[0] = this, arguments));
1801
- return this;
1802
- };
1803
- d3_selectionPrototype.empty = function() {
1804
- return !this.node();
1805
- };
1806
- d3_selectionPrototype.node = function(callback) {
1807
- for (var j = 0, m = this.length; j < m; j++) {
1808
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
1809
- var node = group[i];
1810
- if (node) return node;
1436
+
1437
+ /** @this {Element} */
1438
+ function htmlConstant() {
1439
+ this.innerHTML = value;
1811
1440
  }
1812
- }
1813
- return null;
1814
- };
1815
- d3_selectionPrototype.transition = function() {
1816
- var subgroups = [],
1817
- subgroup,
1818
- node;
1819
-
1820
- for (var j = -1, m = this.length; ++j < m;) {
1821
- subgroups.push(subgroup = []);
1822
- for (var group = this[j], i = -1, n = group.length; ++i < n;) {
1823
- subgroup.push((node = group[i]) ? {node: node, delay: 0, duration: 250} : null);
1441
+
1442
+ /** @this {Element} */
1443
+ function htmlFunction() {
1444
+ this.innerHTML = value.apply(this, arguments);
1824
1445
  }
1825
- }
1826
1446
 
1827
- return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId, Date.now());
1828
- };
1829
- var d3_selectionRoot = d3_selection([[document]]);
1447
+ return groups.each(typeof value == "function"
1448
+ ? htmlFunction : htmlConstant);
1449
+ };
1830
1450
 
1831
- d3_selectionRoot[0].parentNode = document.documentElement;
1451
+ // TODO append(node)?
1452
+ // TODO append(function)?
1453
+ groups.append = function(name) {
1454
+ name = d3.ns.qualify(name);
1832
1455
 
1833
- // TODO fast singleton implementation!
1834
- // TODO select(function)
1835
- d3.select = function(selector) {
1836
- return typeof selector === "string"
1837
- ? d3_selectionRoot.select(selector)
1838
- : d3_selection([[selector]]); // assume node
1839
- };
1456
+ function append(node) {
1457
+ return node.appendChild(document.createElement(name));
1458
+ }
1840
1459
 
1841
- // TODO selectAll(function)
1842
- d3.selectAll = function(selector) {
1843
- return typeof selector === "string"
1844
- ? d3_selectionRoot.selectAll(selector)
1845
- : d3_selection([d3_array(selector)]); // assume node[]
1846
- };
1847
- function d3_transition(groups, id, time) {
1848
- d3_arraySubclass(groups, d3_transitionPrototype);
1460
+ function appendNS(node) {
1461
+ return node.appendChild(document.createElementNS(name.space, name.local));
1462
+ }
1849
1463
 
1850
- var tweens = {},
1851
- event = d3.dispatch("start", "end"),
1852
- ease = d3_transitionEase;
1464
+ return select(name.local ? appendNS : append);
1465
+ };
1853
1466
 
1854
- groups.id = id;
1467
+ // TODO insert(node, function)?
1468
+ // TODO insert(function, string)?
1469
+ // TODO insert(function, function)?
1470
+ groups.insert = function(name, before) {
1471
+ name = d3.ns.qualify(name);
1855
1472
 
1856
- groups.time = time;
1473
+ function insert(node) {
1474
+ return node.insertBefore(
1475
+ document.createElement(name),
1476
+ d3_select(before, node));
1477
+ }
1857
1478
 
1858
- groups.tween = function(name, tween) {
1859
- if (arguments.length < 2) return tweens[name];
1860
- if (tween == null) delete tweens[name];
1861
- else tweens[name] = tween;
1862
- return groups;
1479
+ function insertNS(node) {
1480
+ return node.insertBefore(
1481
+ document.createElementNS(name.space, name.local),
1482
+ d3_select(before, node));
1483
+ }
1484
+
1485
+ return select(name.local ? insertNS : insert);
1863
1486
  };
1864
1487
 
1865
- groups.ease = function(value) {
1866
- if (!arguments.length) return ease;
1867
- ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments);
1868
- return groups;
1488
+ // TODO remove(selector)?
1489
+ // TODO remove(node)?
1490
+ // TODO remove(function)?
1491
+ groups.remove = function() {
1492
+ return groups.each(function() {
1493
+ var parent = this.parentNode;
1494
+ if (parent) parent.removeChild(this);
1495
+ });
1869
1496
  };
1870
1497
 
1871
- groups.each = function(type, listener) {
1872
- if (arguments.length < 2) return d3_transition_each.call(groups, type);
1873
- event[type].add(listener);
1498
+ groups.sort = function(comparator) {
1499
+ comparator = d3_selection_comparator.apply(this, arguments);
1500
+ for (var j = 0, m = groups.length; j < m; j++) {
1501
+ var group = groups[j];
1502
+ group.sort(comparator);
1503
+ for (var i = 1, n = group.length, prev = group[0]; i < n; i++) {
1504
+ var node = group[i];
1505
+ if (node) {
1506
+ if (prev) prev.parentNode.insertBefore(node, prev.nextSibling);
1507
+ prev = node;
1508
+ }
1509
+ }
1510
+ }
1874
1511
  return groups;
1875
1512
  };
1876
1513
 
1877
- d3.timer(function(elapsed) {
1878
- groups.each(function(d, i, j) {
1879
- var tweened = [],
1880
- node = this,
1881
- delay = groups[j][i].delay,
1882
- duration = groups[j][i].duration,
1883
- lock = node.__transition__ || (node.__transition__ = {active: 0, count: 0});
1884
-
1885
- ++lock.count;
1514
+ // type can be namespaced, e.g., "click.foo"
1515
+ // listener can be null for removal
1516
+ groups.on = function(type, listener) {
1886
1517
 
1887
- delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time);
1518
+ // parse the type specifier
1519
+ var i = type.indexOf("."),
1520
+ typo = i == -1 ? type : type.substring(0, i),
1521
+ name = "__on" + type;
1888
1522
 
1889
- function start(elapsed) {
1890
- if (lock.active > id) return stop();
1891
- lock.active = id;
1523
+ // remove the old event listener, and add the new event listener
1524
+ return groups.each(function(d, i) {
1525
+ if (this[name]) this.removeEventListener(typo, this[name], false);
1526
+ if (listener) this.addEventListener(typo, this[name] = l, false);
1892
1527
 
1893
- for (var tween in tweens) {
1894
- if (tween = tweens[tween].call(node, d, i)) {
1895
- tweened.push(tween);
1896
- }
1528
+ // wrapped event listener that preserves d, i
1529
+ function l(e) {
1530
+ var o = d3.event; // Events can be reentrant (e.g., focus).
1531
+ d3.event = e;
1532
+ try {
1533
+ listener.call(this, d, i);
1534
+ } finally {
1535
+ d3.event = o;
1897
1536
  }
1898
-
1899
- event.start.dispatch.call(node, d, i);
1900
- if (!tick(elapsed)) d3.timer(tick, 0, time);
1901
- return 1;
1902
1537
  }
1538
+ });
1539
+ };
1903
1540
 
1904
- function tick(elapsed) {
1905
- if (lock.active !== id) return stop();
1541
+ // TODO slice?
1906
1542
 
1907
- var t = (elapsed - delay) / duration,
1908
- e = ease(t),
1909
- n = tweened.length;
1543
+ groups.transition = function() {
1544
+ return d3_transition(groups);
1545
+ };
1910
1546
 
1911
- while (n > 0) {
1912
- tweened[--n].call(node, e);
1913
- }
1547
+ groups.call = d3_call;
1914
1548
 
1915
- if (t >= 1) {
1916
- stop();
1917
- d3_transitionInheritId = id;
1918
- event.end.dispatch.call(node, d, i);
1919
- d3_transitionInheritId = 0;
1920
- return 1;
1549
+ return groups;
1550
+ }
1551
+
1552
+ function d3_selectionEnter(groups) {
1553
+
1554
+ function select(select) {
1555
+ var subgroups = [],
1556
+ subgroup,
1557
+ subnode,
1558
+ group,
1559
+ node;
1560
+ for (var j = 0, m = groups.length; j < m; j++) {
1561
+ group = groups[j];
1562
+ subgroups.push(subgroup = []);
1563
+ subgroup.parentNode = group.parentNode;
1564
+ for (var i = 0, n = group.length; i < n; i++) {
1565
+ if (node = group[i]) {
1566
+ subgroup.push(subnode = select(group.parentNode));
1567
+ subnode.__data__ = node.__data__;
1568
+ } else {
1569
+ subgroup.push(null);
1921
1570
  }
1922
1571
  }
1572
+ }
1573
+ return d3_selection(subgroups);
1574
+ }
1923
1575
 
1924
- function stop() {
1925
- if (!--lock.count) delete node.__transition__;
1926
- return 1;
1927
- }
1928
- });
1929
- return 1;
1930
- }, 0, time);
1576
+ // TODO append(node)?
1577
+ // TODO append(function)?
1578
+ groups.append = function(name) {
1579
+ name = d3.ns.qualify(name);
1931
1580
 
1932
- return groups;
1933
- }
1581
+ function append(node) {
1582
+ return node.appendChild(document.createElement(name));
1583
+ }
1934
1584
 
1935
- var d3_transitionRemove = {};
1585
+ function appendNS(node) {
1586
+ return node.appendChild(document.createElementNS(name.space, name.local));
1587
+ }
1936
1588
 
1937
- function d3_transitionNull(d, i, a) {
1938
- return a != "" && d3_transitionRemove;
1939
- }
1589
+ return select(name.local ? appendNS : append);
1590
+ };
1940
1591
 
1941
- function d3_transitionTween(b) {
1592
+ // TODO insert(node, function)?
1593
+ // TODO insert(function, string)?
1594
+ // TODO insert(function, function)?
1595
+ groups.insert = function(name, before) {
1596
+ name = d3.ns.qualify(name);
1942
1597
 
1943
- function transitionFunction(d, i, a) {
1944
- var v = b.call(this, d, i);
1945
- return v == null
1946
- ? a != "" && d3_transitionRemove
1947
- : a != v && d3.interpolate(a, v);
1948
- }
1598
+ function insert(node) {
1599
+ return node.insertBefore(
1600
+ document.createElement(name),
1601
+ d3_select(before, node));
1602
+ }
1949
1603
 
1950
- function transitionString(d, i, a) {
1951
- return a != b && d3.interpolate(a, b);
1952
- }
1604
+ function insertNS(node) {
1605
+ return node.insertBefore(
1606
+ document.createElementNS(name.space, name.local),
1607
+ d3_select(before, node));
1608
+ }
1609
+
1610
+ return select(name.local ? insertNS : insert);
1611
+ };
1612
+
1613
+ return groups;
1614
+ }
1615
+
1616
+ function d3_selection_comparator(comparator) {
1617
+ if (!arguments.length) comparator = d3.ascending;
1618
+ return function(a, b) {
1619
+ return comparator(a && a.__data__, b && b.__data__);
1620
+ };
1621
+ }
1953
1622
 
1954
- return typeof b === "function" ? transitionFunction
1955
- : b == null ? d3_transitionNull
1956
- : (b += "", transitionString);
1623
+ function d3_selection_enterNode(data) {
1624
+ return {__data__: data};
1957
1625
  }
1626
+ d3.transition = d3_root.transition;
1958
1627
 
1959
- var d3_transitionPrototype = [],
1960
- d3_transitionId = 0,
1961
- d3_transitionInheritId = 0,
1962
- d3_transitionEase = d3.ease("cubic-in-out");
1628
+ var d3_transitionId = 0,
1629
+ d3_transitionInheritId = 0;
1963
1630
 
1964
- d3_transitionPrototype.call = d3_selectionPrototype.call;
1631
+ function d3_transition(groups) {
1632
+ var transition = {},
1633
+ transitionId = d3_transitionInheritId || ++d3_transitionId,
1634
+ tweens = {},
1635
+ interpolators = [],
1636
+ remove = false,
1637
+ event = d3.dispatch("start", "end"),
1638
+ stage = [],
1639
+ delay = [],
1640
+ duration = [],
1641
+ durationMax,
1642
+ ease = d3.ease("cubic-in-out");
1643
+
1644
+ //
1645
+ // Be careful with concurrent transitions!
1646
+ //
1647
+ // Say transition A causes an exit. Before A finishes, a transition B is
1648
+ // created, and believes it only needs to do an update, because the elements
1649
+ // haven't been removed yet (which happens at the very end of the exit
1650
+ // transition).
1651
+ //
1652
+ // Even worse, what if either transition A or B has a staggered delay? Then,
1653
+ // some elements may be removed, while others remain. Transition B does not
1654
+ // know to enter the elements because they were still present at the time
1655
+ // the transition B was created (but not yet started).
1656
+ //
1657
+ // To prevent such confusion, we only trigger end events for transitions if
1658
+ // the transition ending is the only one scheduled for the given element.
1659
+ // Similarly, we only allow one transition to be active for any given
1660
+ // element, so that concurrent transitions do not overwrite each other's
1661
+ // properties.
1662
+ //
1663
+ // TODO Support transition namespaces, so that transitions can proceed
1664
+ // concurrently on the same element if needed. Hopefully, this is rare!
1665
+ //
1666
+
1667
+ groups.each(function() {
1668
+ (this.__transition__ || (this.__transition__ = {})).owner = transitionId;
1669
+ });
1965
1670
 
1966
- d3.transition = function() {
1967
- return d3_selectionRoot.transition();
1968
- };
1671
+ function step(elapsed) {
1672
+ var clear = true,
1673
+ k = -1;
1674
+ groups.each(function() {
1675
+ if (stage[++k] == 2) return; // ended
1676
+ var t = (elapsed - delay[k]) / duration[k],
1677
+ tx = this.__transition__,
1678
+ te, // ease(t)
1679
+ tk, // tween key
1680
+ ik = interpolators[k];
1681
+
1682
+ // Check if the (un-eased) time is outside the range [0,1].
1683
+ if (t < 1) {
1684
+ clear = false;
1685
+ if (t < 0) return;
1686
+ } else {
1687
+ t = 1;
1688
+ }
1969
1689
 
1970
- d3.transition.prototype = d3_transitionPrototype;
1971
- d3_transitionPrototype.select = function(selector) {
1972
- var subgroups = [],
1973
- subgroup,
1974
- subnode,
1975
- node;
1976
-
1977
- if (typeof selector !== "function") selector = d3_selection_selector(selector);
1978
-
1979
- for (var j = -1, m = this.length; ++j < m;) {
1980
- subgroups.push(subgroup = []);
1981
- for (var group = this[j], i = -1, n = group.length; ++i < n;) {
1982
- if ((node = group[i]) && (subnode = selector.call(node.node, node.node.__data__, i))) {
1983
- if ("__data__" in node.node) subnode.__data__ = node.node.__data__;
1984
- subgroup.push({node: subnode, delay: node.delay, duration: node.duration});
1690
+ // Determine the stage of this transition.
1691
+ // 0 - Not yet started.
1692
+ // 1 - In progress.
1693
+ // 2 - Ended.
1694
+ if (stage[k]) {
1695
+ if (!tx || tx.active != transitionId) {
1696
+ stage[k] = 2;
1697
+ return;
1698
+ }
1699
+ } else if (!tx || tx.active > transitionId) {
1700
+ stage[k] = 2;
1701
+ return;
1985
1702
  } else {
1986
- subgroup.push(null);
1703
+ stage[k] = 1;
1704
+ event.start.dispatch.apply(this, arguments);
1705
+ ik = interpolators[k] = {};
1706
+ tx.active = transitionId;
1707
+ for (tk in tweens) {
1708
+ if (te = tweens[tk].apply(this, arguments)) {
1709
+ ik[tk] = te;
1710
+ }
1711
+ }
1987
1712
  }
1988
- }
1989
- }
1990
1713
 
1991
- return d3_transition(subgroups, this.id, this.time).ease(this.ease());
1992
- };
1993
- d3_transitionPrototype.selectAll = function(selector) {
1994
- var subgroups = [],
1995
- subgroup,
1996
- subnodes,
1997
- node;
1998
-
1999
- if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
2000
-
2001
- for (var j = -1, m = this.length; ++j < m;) {
2002
- for (var group = this[j], i = -1, n = group.length; ++i < n;) {
2003
- if (node = group[i]) {
2004
- subnodes = selector.call(node.node, node.node.__data__, i);
2005
- subgroups.push(subgroup = []);
2006
- for (var k = -1, o = subnodes.length; ++k < o;) {
2007
- subgroup.push({node: subnodes[k], delay: node.delay, duration: node.duration});
1714
+ // Apply the interpolators!
1715
+ te = ease(t);
1716
+ for (tk in ik) ik[tk].call(this, te);
1717
+
1718
+ // Handle ending transitions.
1719
+ if (t == 1) {
1720
+ stage[k] = 2;
1721
+ if (tx.active == transitionId) {
1722
+ var owner = tx.owner;
1723
+ if (owner == transitionId) {
1724
+ delete this.__transition__;
1725
+ if (remove) this.parentNode.removeChild(this);
1726
+ }
1727
+ d3_transitionInheritId = transitionId;
1728
+ event.end.dispatch.apply(this, arguments);
1729
+ d3_transitionInheritId = 0;
1730
+ tx.owner = owner;
2008
1731
  }
2009
1732
  }
2010
- }
1733
+ });
1734
+ return clear;
2011
1735
  }
2012
1736
 
2013
- return d3_transition(subgroups, this.id, this.time).ease(this.ease());
2014
- };
2015
- d3_transitionPrototype.attr = function(name, value) {
2016
- return this.attrTween(name, d3_transitionTween(value));
2017
- };
1737
+ transition.delay = function(value) {
1738
+ var delayMin = Infinity,
1739
+ k = -1;
1740
+ if (typeof value == "function") {
1741
+ groups.each(function(d, i) {
1742
+ var x = delay[++k] = +value.apply(this, arguments);
1743
+ if (x < delayMin) delayMin = x;
1744
+ });
1745
+ } else {
1746
+ delayMin = +value;
1747
+ groups.each(function(d, i) {
1748
+ delay[++k] = delayMin;
1749
+ });
1750
+ }
1751
+ d3_timer(step, delayMin);
1752
+ return transition;
1753
+ };
1754
+
1755
+ transition.duration = function(value) {
1756
+ var k = -1;
1757
+ if (typeof value == "function") {
1758
+ durationMax = 0;
1759
+ groups.each(function(d, i) {
1760
+ var x = duration[++k] = +value.apply(this, arguments);
1761
+ if (x > durationMax) durationMax = x;
1762
+ });
1763
+ } else {
1764
+ durationMax = +value;
1765
+ groups.each(function(d, i) {
1766
+ duration[++k] = durationMax;
1767
+ });
1768
+ }
1769
+ return transition;
1770
+ };
2018
1771
 
2019
- d3_transitionPrototype.attrTween = function(nameNS, tween) {
2020
- var name = d3.ns.qualify(nameNS);
1772
+ transition.ease = function(value) {
1773
+ ease = typeof value == "function" ? value : d3.ease.apply(d3, arguments);
1774
+ return transition;
1775
+ };
2021
1776
 
2022
- function attrTween(d, i) {
2023
- var f = tween.call(this, d, i, this.getAttribute(name));
2024
- return f === d3_transitionRemove
2025
- ? (this.removeAttribute(name), null)
2026
- : f && function(t) { this.setAttribute(name, f(t)); };
2027
- }
1777
+ transition.attrTween = function(name, tween) {
2028
1778
 
2029
- function attrTweenNS(d, i) {
2030
- var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
2031
- return f === d3_transitionRemove
2032
- ? (this.removeAttributeNS(name.space, name.local), null)
2033
- : f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); };
2034
- }
1779
+ /** @this {Element} */
1780
+ function attrTween(d, i) {
1781
+ var f = tween.call(this, d, i, this.getAttribute(name));
1782
+ return function(t) {
1783
+ this.setAttribute(name, f(t));
1784
+ };
1785
+ }
2035
1786
 
2036
- return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
2037
- };
2038
- d3_transitionPrototype.style = function(name, value, priority) {
2039
- if (arguments.length < 3) priority = "";
2040
- return this.styleTween(name, d3_transitionTween(value), priority);
2041
- };
1787
+ /** @this {Element} */
1788
+ function attrTweenNS(d, i) {
1789
+ var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
1790
+ return function(t) {
1791
+ this.setAttributeNS(name.space, name.local, f(t));
1792
+ };
1793
+ }
2042
1794
 
2043
- d3_transitionPrototype.styleTween = function(name, tween, priority) {
2044
- if (arguments.length < 3) priority = "";
2045
- return this.tween("style." + name, function(d, i) {
2046
- var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
2047
- return f === d3_transitionRemove
2048
- ? (this.style.removeProperty(name), null)
2049
- : f && function(t) { this.style.setProperty(name, f(t), priority); };
2050
- });
2051
- };
2052
- d3_transitionPrototype.text = function(value) {
2053
- return this.tween("text", function(d, i) {
2054
- this.textContent = typeof value === "function"
2055
- ? value.call(this, d, i)
2056
- : value;
2057
- });
2058
- };
2059
- d3_transitionPrototype.remove = function() {
2060
- return this.each("end", function() {
2061
- var p;
2062
- if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
2063
- });
2064
- };
2065
- d3_transitionPrototype.delay = function(value) {
2066
- var groups = this;
2067
- return groups.each(typeof value === "function"
2068
- ? function(d, i, j) { groups[j][i].delay = +value.apply(this, arguments); }
2069
- : (value = +value, function(d, i, j) { groups[j][i].delay = value; }));
2070
- };
2071
- d3_transitionPrototype.duration = function(value) {
2072
- var groups = this;
2073
- return groups.each(typeof value === "function"
2074
- ? function(d, i, j) { groups[j][i].duration = +value.apply(this, arguments); }
2075
- : (value = +value, function(d, i, j) { groups[j][i].duration = value; }));
2076
- };
2077
- function d3_transition_each(callback) {
2078
- for (var j = 0, m = this.length; j < m; j++) {
2079
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
2080
- var node = group[i];
2081
- if (node) callback.call(node = node.node, node.__data__, i, j);
1795
+ tweens["attr." + name] = name.local ? attrTweenNS : attrTween;
1796
+ return transition;
1797
+ };
1798
+
1799
+ transition.attr = function(name, value) {
1800
+ return transition.attrTween(name, d3_transitionTween(value));
1801
+ };
1802
+
1803
+ transition.styleTween = function(name, tween, priority) {
1804
+ if (arguments.length < 3) priority = null;
1805
+
1806
+ /** @this {Element} */
1807
+ function styleTween(d, i) {
1808
+ var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
1809
+ return function(t) {
1810
+ this.style.setProperty(name, f(t), priority);
1811
+ };
2082
1812
  }
2083
- }
2084
- return this;
1813
+
1814
+ tweens["style." + name] = styleTween;
1815
+ return transition;
1816
+ };
1817
+
1818
+ transition.style = function(name, value, priority) {
1819
+ if (arguments.length < 3) priority = null;
1820
+ return transition.styleTween(name, d3_transitionTween(value), priority);
1821
+ };
1822
+
1823
+ transition.text = function(value) {
1824
+ tweens.text = function(d, i) {
1825
+ this.textContent = typeof value == "function"
1826
+ ? value.call(this, d, i)
1827
+ : value;
1828
+ };
1829
+ return transition;
1830
+ };
1831
+
1832
+ transition.select = function(query) {
1833
+ var k, t = d3_transition(groups.select(query)).ease(ease);
1834
+ k = -1; t.delay(function(d, i) { return delay[++k]; });
1835
+ k = -1; t.duration(function(d, i) { return duration[++k]; });
1836
+ return t;
1837
+ };
1838
+
1839
+ transition.selectAll = function(query) {
1840
+ var k, t = d3_transition(groups.selectAll(query)).ease(ease);
1841
+ k = -1; t.delay(function(d, i) { return delay[i ? k : ++k]; })
1842
+ k = -1; t.duration(function(d, i) { return duration[i ? k : ++k]; });
1843
+ return t;
1844
+ };
1845
+
1846
+ transition.remove = function() {
1847
+ remove = true;
1848
+ return transition;
1849
+ };
1850
+
1851
+ transition.each = function(type, listener) {
1852
+ event[type].add(listener);
1853
+ return transition;
1854
+ };
1855
+
1856
+ transition.call = d3_call;
1857
+
1858
+ return transition.delay(0).duration(250);
1859
+ }
1860
+
1861
+ function d3_transitionTween(b) {
1862
+ return typeof b == "function"
1863
+ ? function(d, i, a) { return d3.interpolate(a, String(b.call(this, d, i))); }
1864
+ : (b = String(b), function(d, i, a) { return d3.interpolate(a, b); });
2085
1865
  }
2086
- d3_transitionPrototype.transition = function() {
2087
- return this.select(d3_this);
2088
- };
2089
1866
  var d3_timer_queue = null,
2090
- d3_timer_interval, // is an interval (or frame) active?
2091
- d3_timer_timeout; // is a timeout active?
1867
+ d3_timer_timeout = 0,
1868
+ d3_timer_interval;
2092
1869
 
2093
1870
  // The timer will continue to fire until callback returns true.
2094
- d3.timer = function(callback, delay, then) {
2095
- var found = false,
1871
+ d3.timer = function(callback) {
1872
+ d3_timer(callback, 0);
1873
+ };
1874
+
1875
+ function d3_timer(callback, delay) {
1876
+ var now = Date.now(),
1877
+ found = false,
1878
+ start = now + delay,
2096
1879
  t0,
2097
1880
  t1 = d3_timer_queue;
2098
1881
 
2099
- if (arguments.length < 3) {
2100
- if (arguments.length < 2) delay = 0;
2101
- else if (!isFinite(delay)) return;
2102
- then = Date.now();
2103
- }
1882
+ if (!isFinite(delay)) return;
2104
1883
 
2105
- // See if the callback's already in the queue.
1884
+ // Scan the queue for earliest callback.
2106
1885
  while (t1) {
2107
- if (t1.callback === callback) {
2108
- t1.then = then;
1886
+ if (t1.callback == callback) {
1887
+ t1.then = now;
2109
1888
  t1.delay = delay;
2110
1889
  found = true;
2111
- break;
1890
+ } else {
1891
+ var x = t1.then + t1.delay;
1892
+ if (x < start) start = x;
2112
1893
  }
2113
1894
  t0 = t1;
2114
1895
  t1 = t1.next;
@@ -2117,71 +1898,47 @@ d3.timer = function(callback, delay, then) {
2117
1898
  // Otherwise, add the callback to the queue.
2118
1899
  if (!found) d3_timer_queue = {
2119
1900
  callback: callback,
2120
- then: then,
1901
+ then: now,
2121
1902
  delay: delay,
2122
1903
  next: d3_timer_queue
2123
1904
  };
2124
1905
 
2125
- // Start animatin'!
2126
1906
  if (!d3_timer_interval) {
2127
- d3_timer_timeout = clearTimeout(d3_timer_timeout);
2128
- d3_timer_interval = 1;
2129
- d3_timer_frame(d3_timer_step);
1907
+ clearTimeout(d3_timer_timeout);
1908
+ d3_timer_timeout = setTimeout(d3_timer_start, Math.max(24, start - now));
2130
1909
  }
2131
1910
  }
2132
1911
 
2133
- function d3_timer_step() {
2134
- var elapsed,
2135
- now = Date.now(),
2136
- t1 = d3_timer_queue;
2137
-
2138
- while (t1) {
2139
- elapsed = now - t1.then;
2140
- if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
2141
- t1 = t1.next;
2142
- }
2143
-
2144
- var delay = d3_timer_flush() - now;
2145
- if (delay > 24) {
2146
- if (isFinite(delay)) {
2147
- clearTimeout(d3_timer_timeout);
2148
- d3_timer_timeout = setTimeout(d3_timer_step, delay);
2149
- }
2150
- d3_timer_interval = 0;
2151
- } else {
2152
- d3_timer_interval = 1;
2153
- d3_timer_frame(d3_timer_step);
2154
- }
1912
+ function d3_timer_start() {
1913
+ d3_timer_interval = 1;
1914
+ d3_timer_timeout = 0;
1915
+ d3_timer_frame(d3_timer_step);
2155
1916
  }
2156
1917
 
2157
- d3.timer.flush = function() {
1918
+ function d3_timer_step() {
2158
1919
  var elapsed,
2159
1920
  now = Date.now(),
1921
+ t0 = null,
2160
1922
  t1 = d3_timer_queue;
2161
-
2162
1923
  while (t1) {
2163
1924
  elapsed = now - t1.then;
2164
- if (!t1.delay) t1.flush = t1.callback(elapsed);
2165
- t1 = t1.next;
1925
+ if (elapsed > t1.delay) t1.flush = t1.callback(elapsed);
1926
+ t1 = (t0 = t1).next;
2166
1927
  }
2167
-
2168
1928
  d3_timer_flush();
2169
- };
1929
+ if (d3_timer_interval) d3_timer_frame(d3_timer_step);
1930
+ }
2170
1931
 
2171
1932
  // Flush after callbacks, to avoid concurrent queue modification.
2172
1933
  function d3_timer_flush() {
2173
1934
  var t0 = null,
2174
- t1 = d3_timer_queue,
2175
- then = Infinity;
1935
+ t1 = d3_timer_queue;
2176
1936
  while (t1) {
2177
- if (t1.flush) {
2178
- t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
2179
- } else {
2180
- then = Math.min(then, t1.then + t1.delay);
2181
- t1 = (t0 = t1).next;
2182
- }
1937
+ t1 = t1.flush
1938
+ ? (t0 ? t0.next = t1.next : d3_timer_queue = t1.next)
1939
+ : (t0 = t1).next;
2183
1940
  }
2184
- return then;
1941
+ if (!t0) d3_timer_interval = 0;
2185
1942
  }
2186
1943
 
2187
1944
  var d3_timer_frame = window.requestAnimationFrame
@@ -2190,72 +1947,44 @@ var d3_timer_frame = window.requestAnimationFrame
2190
1947
  || window.oRequestAnimationFrame
2191
1948
  || window.msRequestAnimationFrame
2192
1949
  || function(callback) { setTimeout(callback, 17); };
2193
- function d3_noop() {}
2194
1950
  d3.scale = {};
2195
-
2196
- function d3_scaleExtent(domain) {
2197
- var start = domain[0], stop = domain[domain.length - 1];
2198
- return start < stop ? [start, stop] : [stop, start];
2199
- }
2200
- function d3_scale_nice(domain, nice) {
2201
- var i0 = 0,
2202
- i1 = domain.length - 1,
2203
- x0 = domain[i0],
2204
- x1 = domain[i1],
2205
- dx;
2206
-
2207
- if (x1 < x0) {
2208
- dx = i0; i0 = i1; i1 = dx;
2209
- dx = x0; x0 = x1; x1 = dx;
2210
- }
2211
-
2212
- if (dx = x1 - x0) {
2213
- nice = nice(dx);
2214
- domain[i0] = nice.floor(x0);
2215
- domain[i1] = nice.ceil(x1);
2216
- }
2217
-
2218
- return domain;
2219
- }
2220
-
2221
- function d3_scale_niceDefault() {
2222
- return Math;
2223
- }
2224
1951
  d3.scale.linear = function() {
2225
- return d3_scale_linear([0, 1], [0, 1], d3.interpolate, false);
2226
- };
2227
-
2228
- function d3_scale_linear(domain, range, interpolate, clamp) {
2229
- var output,
2230
- input;
2231
-
2232
- function rescale() {
2233
- var linear = domain.length == 2 ? d3_scale_bilinear : d3_scale_polylinear,
2234
- uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
2235
- output = linear(domain, range, uninterpolate, interpolate);
2236
- input = linear(range, domain, uninterpolate, d3.interpolate);
2237
- return scale;
2238
- }
1952
+ var x0 = 0,
1953
+ x1 = 1,
1954
+ y0 = 0,
1955
+ y1 = 1,
1956
+ kx = 1, // 1 / (x1 - x0)
1957
+ ky = 1, // (x1 - x0) / (y1 - y0)
1958
+ interpolate = d3.interpolate,
1959
+ i = interpolate(y0, y1),
1960
+ clamp = false;
2239
1961
 
2240
1962
  function scale(x) {
2241
- return output(x);
1963
+ x = (x - x0) * kx;
1964
+ return i(clamp ? Math.max(0, Math.min(1, x)) : x);
2242
1965
  }
2243
1966
 
2244
1967
  // Note: requires range is coercible to number!
2245
1968
  scale.invert = function(y) {
2246
- return input(y);
1969
+ return (y - y0) * ky + x0;
2247
1970
  };
2248
1971
 
2249
1972
  scale.domain = function(x) {
2250
- if (!arguments.length) return domain;
2251
- domain = x.map(Number);
2252
- return rescale();
1973
+ if (!arguments.length) return [x0, x1];
1974
+ x0 = +x[0];
1975
+ x1 = +x[1];
1976
+ kx = 1 / (x1 - x0);
1977
+ ky = (x1 - x0) / (y1 - y0);
1978
+ return scale;
2253
1979
  };
2254
1980
 
2255
1981
  scale.range = function(x) {
2256
- if (!arguments.length) return range;
2257
- range = x;
2258
- return rescale();
1982
+ if (!arguments.length) return [y0, y1];
1983
+ y0 = x[0];
1984
+ y1 = x[1];
1985
+ ky = (x1 - x0) / (y1 - y0);
1986
+ i = interpolate(y0, y1);
1987
+ return scale;
2259
1988
  };
2260
1989
 
2261
1990
  scale.rangeRound = function(x) {
@@ -2265,106 +1994,52 @@ function d3_scale_linear(domain, range, interpolate, clamp) {
2265
1994
  scale.clamp = function(x) {
2266
1995
  if (!arguments.length) return clamp;
2267
1996
  clamp = x;
2268
- return rescale();
1997
+ return scale;
2269
1998
  };
2270
1999
 
2271
2000
  scale.interpolate = function(x) {
2272
2001
  if (!arguments.length) return interpolate;
2273
- interpolate = x;
2274
- return rescale();
2275
- };
2276
-
2277
- scale.ticks = function(m) {
2278
- return d3_scale_linearTicks(domain, m);
2279
- };
2280
-
2281
- scale.tickFormat = function(m) {
2282
- return d3_scale_linearTickFormat(domain, m);
2283
- };
2284
-
2285
- scale.nice = function() {
2286
- d3_scale_nice(domain, d3_scale_linearNice);
2287
- return rescale();
2002
+ i = (interpolate = x)(y0, y1);
2003
+ return scale;
2288
2004
  };
2289
2005
 
2290
- scale.copy = function() {
2291
- return d3_scale_linear(domain, range, interpolate, clamp);
2292
- };
2006
+ // TODO Dates? Ugh.
2007
+ function tickRange(m) {
2008
+ var start = Math.min(x0, x1),
2009
+ stop = Math.max(x0, x1),
2010
+ span = stop - start,
2011
+ step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)),
2012
+ err = m / (span / step);
2293
2013
 
2294
- return rescale();
2295
- };
2014
+ // Filter ticks to get closer to the desired count.
2015
+ if (err <= .15) step *= 10;
2016
+ else if (err <= .35) step *= 5;
2017
+ else if (err <= .75) step *= 2;
2296
2018
 
2297
- function d3_scale_linearRebind(scale, linear) {
2298
- scale.range = d3.rebind(scale, linear.range);
2299
- scale.rangeRound = d3.rebind(scale, linear.rangeRound);
2300
- scale.interpolate = d3.rebind(scale, linear.interpolate);
2301
- scale.clamp = d3.rebind(scale, linear.clamp);
2302
- return scale;
2303
- }
2019
+ // Round start and stop values to step interval.
2020
+ return {
2021
+ start: Math.ceil(start / step) * step,
2022
+ stop: Math.floor(stop / step) * step + step * .5, // inclusive
2023
+ step: step
2024
+ };
2025
+ }
2304
2026
 
2305
- function d3_scale_linearNice(dx) {
2306
- dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
2307
- return {
2308
- floor: function(x) { return Math.floor(x / dx) * dx; },
2309
- ceil: function(x) { return Math.ceil(x / dx) * dx; }
2027
+ scale.ticks = function(m) {
2028
+ var range = tickRange(m);
2029
+ return d3.range(range.start, range.stop, range.step);
2310
2030
  };
2311
- }
2312
-
2313
- // TODO Dates? Ugh.
2314
- function d3_scale_linearTickRange(domain, m) {
2315
- var extent = d3_scaleExtent(domain),
2316
- span = extent[1] - extent[0],
2317
- step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)),
2318
- err = m / span * step;
2319
-
2320
- // Filter ticks to get closer to the desired count.
2321
- if (err <= .15) step *= 10;
2322
- else if (err <= .35) step *= 5;
2323
- else if (err <= .75) step *= 2;
2324
-
2325
- // Round start and stop values to step interval.
2326
- extent[0] = Math.ceil(extent[0] / step) * step;
2327
- extent[1] = Math.floor(extent[1] / step) * step + step * .5; // inclusive
2328
- extent[2] = step;
2329
- return extent;
2330
- }
2331
2031
 
2332
- function d3_scale_linearTicks(domain, m) {
2333
- return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
2334
- }
2335
-
2336
- function d3_scale_linearTickFormat(domain, m) {
2337
- return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f");
2338
- }
2339
- function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
2340
- var u = uninterpolate(domain[0], domain[1]),
2341
- i = interpolate(range[0], range[1]);
2342
- return function(x) {
2343
- return i(u(x));
2032
+ scale.tickFormat = function(m) {
2033
+ var n = Math.max(0, -Math.floor(Math.log(tickRange(m).step) / Math.LN10 + .01));
2034
+ return d3.format(",." + n + "f");
2344
2035
  };
2345
- }
2346
- function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
2347
- var u = [],
2348
- i = [],
2349
- j = 0,
2350
- n = domain.length;
2351
-
2352
- while (++j < n) {
2353
- u.push(uninterpolate(domain[j - 1], domain[j]));
2354
- i.push(interpolate(range[j - 1], range[j]));
2355
- }
2356
2036
 
2357
- return function(x) {
2358
- var j = d3.bisect(domain, x, 1, domain.length - 1) - 1;
2359
- return i[j](u[j](x));
2360
- };
2361
- }
2362
- d3.scale.log = function() {
2363
- return d3_scale_log(d3.scale.linear(), d3_scale_logp);
2037
+ return scale;
2364
2038
  };
2365
-
2366
- function d3_scale_log(linear, log) {
2367
- var pow = log.pow;
2039
+ d3.scale.log = function() {
2040
+ var linear = d3.scale.linear(),
2041
+ log = d3_scale_log,
2042
+ pow = log.pow;
2368
2043
 
2369
2044
  function scale(x) {
2370
2045
  return linear(log(x));
@@ -2376,25 +2051,25 @@ function d3_scale_log(linear, log) {
2376
2051
 
2377
2052
  scale.domain = function(x) {
2378
2053
  if (!arguments.length) return linear.domain().map(pow);
2379
- log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;
2054
+ log = (x[0] || x[1]) < 0 ? d3_scale_logn : d3_scale_log;
2380
2055
  pow = log.pow;
2381
2056
  linear.domain(x.map(log));
2382
2057
  return scale;
2383
2058
  };
2384
2059
 
2385
- scale.nice = function() {
2386
- linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
2387
- return scale;
2388
- };
2060
+ scale.range = d3.rebind(scale, linear.range);
2061
+ scale.rangeRound = d3.rebind(scale, linear.rangeRound);
2062
+ scale.interpolate = d3.rebind(scale, linear.interpolate);
2063
+ scale.clamp = d3.rebind(scale, linear.clamp);
2389
2064
 
2390
2065
  scale.ticks = function() {
2391
- var extent = d3_scaleExtent(linear.domain()),
2066
+ var d = linear.domain(),
2392
2067
  ticks = [];
2393
- if (extent.every(isFinite)) {
2394
- var i = Math.floor(extent[0]),
2395
- j = Math.ceil(extent[1]),
2396
- u = Math.round(pow(extent[0])),
2397
- v = Math.round(pow(extent[1]));
2068
+ if (d.every(isFinite)) {
2069
+ var i = Math.floor(d[0]),
2070
+ j = Math.ceil(d[1]),
2071
+ u = pow(d[0]),
2072
+ v = pow(d[1]);
2398
2073
  if (log === d3_scale_logn) {
2399
2074
  ticks.push(pow(i));
2400
2075
  for (; i++ < j;) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
@@ -2409,27 +2084,14 @@ function d3_scale_log(linear, log) {
2409
2084
  return ticks;
2410
2085
  };
2411
2086
 
2412
- scale.tickFormat = function(n, format) {
2413
- if (arguments.length < 2) format = d3_scale_logFormat;
2414
- if (arguments.length < 1) return format;
2415
- var k = n / scale.ticks().length,
2416
- f = log === d3_scale_logn ? (e = -1e-15, Math.floor) : (e = 1e-15, Math.ceil),
2417
- e;
2418
- return function(d) {
2419
- return d / pow(f(log(d) + e)) < k ? format(d) : "";
2420
- };
2421
- };
2422
-
2423
- scale.copy = function() {
2424
- return d3_scale_log(linear.copy(), log);
2087
+ scale.tickFormat = function() {
2088
+ return function(d) { return d.toPrecision(1); };
2425
2089
  };
2426
2090
 
2427
- return d3_scale_linearRebind(scale, linear);
2091
+ return scale;
2428
2092
  };
2429
2093
 
2430
- var d3_scale_logFormat = d3.format("e");
2431
-
2432
- function d3_scale_logp(x) {
2094
+ function d3_scale_log(x) {
2433
2095
  return Math.log(x) / Math.LN10;
2434
2096
  }
2435
2097
 
@@ -2437,7 +2099,7 @@ function d3_scale_logn(x) {
2437
2099
  return -Math.log(-x) / Math.LN10;
2438
2100
  }
2439
2101
 
2440
- d3_scale_logp.pow = function(x) {
2102
+ d3_scale_log.pow = function(x) {
2441
2103
  return Math.pow(10, x);
2442
2104
  };
2443
2105
 
@@ -2445,12 +2107,11 @@ d3_scale_logn.pow = function(x) {
2445
2107
  return -Math.pow(10, -x);
2446
2108
  };
2447
2109
  d3.scale.pow = function() {
2448
- return d3_scale_pow(d3.scale.linear(), 1);
2449
- };
2450
-
2451
- function d3_scale_pow(linear, exponent) {
2452
- var powp = d3_scale_powPow(exponent),
2453
- powb = d3_scale_powPow(1 / exponent);
2110
+ var linear = d3.scale.linear(),
2111
+ tick = d3.scale.linear(), // TODO better tick formatting...
2112
+ exponent = 1,
2113
+ powp = Number,
2114
+ powb = powp;
2454
2115
 
2455
2116
  function scale(x) {
2456
2117
  return linear(powp(x));
@@ -2462,72 +2123,70 @@ function d3_scale_pow(linear, exponent) {
2462
2123
 
2463
2124
  scale.domain = function(x) {
2464
2125
  if (!arguments.length) return linear.domain().map(powb);
2126
+ var pow = (x[0] || x[1]) < 0 ? d3_scale_pown : d3_scale_pow;
2127
+ powp = pow(exponent);
2128
+ powb = pow(1 / exponent);
2465
2129
  linear.domain(x.map(powp));
2130
+ tick.domain(x);
2466
2131
  return scale;
2467
2132
  };
2468
2133
 
2469
- scale.ticks = function(m) {
2470
- return d3_scale_linearTicks(scale.domain(), m);
2471
- };
2472
-
2473
- scale.tickFormat = function(m) {
2474
- return d3_scale_linearTickFormat(scale.domain(), m);
2475
- };
2476
-
2477
- scale.nice = function() {
2478
- return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
2479
- };
2134
+ scale.range = d3.rebind(scale, linear.range);
2135
+ scale.rangeRound = d3.rebind(scale, linear.rangeRound);
2136
+ scale.interpolate = d3.rebind(scale, linear.interpolate);
2137
+ scale.clamp = d3.rebind(scale, linear.clamp);
2138
+ scale.ticks = tick.ticks;
2139
+ scale.tickFormat = tick.tickFormat;
2480
2140
 
2481
2141
  scale.exponent = function(x) {
2482
2142
  if (!arguments.length) return exponent;
2483
2143
  var domain = scale.domain();
2484
- powp = d3_scale_powPow(exponent = x);
2485
- powb = d3_scale_powPow(1 / exponent);
2144
+ exponent = x;
2486
2145
  return scale.domain(domain);
2487
2146
  };
2488
2147
 
2489
- scale.copy = function() {
2490
- return d3_scale_pow(linear.copy(), exponent);
2491
- };
2492
-
2493
- return d3_scale_linearRebind(scale, linear);
2148
+ return scale;
2494
2149
  };
2495
2150
 
2496
- function d3_scale_powPow(e) {
2151
+ function d3_scale_pow(e) {
2152
+ return function(x) {
2153
+ return Math.pow(x, e);
2154
+ };
2155
+ }
2156
+
2157
+ function d3_scale_pown(e) {
2497
2158
  return function(x) {
2498
- return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
2159
+ return -Math.pow(-x, e);
2499
2160
  };
2500
2161
  }
2501
2162
  d3.scale.sqrt = function() {
2502
2163
  return d3.scale.pow().exponent(.5);
2503
2164
  };
2504
2165
  d3.scale.ordinal = function() {
2505
- return d3_scale_ordinal([], {t: "range", x: []});
2506
- };
2507
-
2508
- function d3_scale_ordinal(domain, ranger) {
2509
- var index,
2510
- range,
2511
- rangeBand;
2166
+ var domain = [],
2167
+ index = {},
2168
+ range = [],
2169
+ rangeBand = 0;
2512
2170
 
2513
2171
  function scale(x) {
2514
- return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length];
2172
+ var i = x in index ? index[x] : (index[x] = domain.push(x) - 1);
2173
+ return range[i % range.length];
2515
2174
  }
2516
2175
 
2517
2176
  scale.domain = function(x) {
2518
2177
  if (!arguments.length) return domain;
2519
- domain = [];
2178
+ domain = x;
2520
2179
  index = {};
2521
- var i = -1, n = x.length, xi;
2522
- while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi);
2523
- return scale[ranger.t](ranger.x, ranger.p);
2180
+ var i = -1, j = -1, n = domain.length; while (++i < n) {
2181
+ x = domain[i];
2182
+ if (!(x in index)) index[x] = ++j;
2183
+ }
2184
+ return scale;
2524
2185
  };
2525
2186
 
2526
2187
  scale.range = function(x) {
2527
2188
  if (!arguments.length) return range;
2528
2189
  range = x;
2529
- rangeBand = 0;
2530
- ranger = {t: "range", x: x};
2531
2190
  return scale;
2532
2191
  };
2533
2192
 
@@ -2536,9 +2195,10 @@ function d3_scale_ordinal(domain, ranger) {
2536
2195
  var start = x[0],
2537
2196
  stop = x[1],
2538
2197
  step = (stop - start) / (domain.length - 1 + padding);
2539
- range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
2198
+ range = domain.length == 1
2199
+ ? [(start + stop) / 2]
2200
+ : d3.range(start + step * padding / 2, stop + step / 2, step);
2540
2201
  rangeBand = 0;
2541
- ranger = {t: "rangePoints", x: x, p: padding};
2542
2202
  return scale;
2543
2203
  };
2544
2204
 
@@ -2549,7 +2209,6 @@ function d3_scale_ordinal(domain, ranger) {
2549
2209
  step = (stop - start) / (domain.length + padding);
2550
2210
  range = d3.range(start + step * padding, stop, step);
2551
2211
  rangeBand = step * (1 - padding);
2552
- ranger = {t: "rangeBands", x: x, p: padding};
2553
2212
  return scale;
2554
2213
  };
2555
2214
 
@@ -2557,11 +2216,11 @@ function d3_scale_ordinal(domain, ranger) {
2557
2216
  if (arguments.length < 2) padding = 0;
2558
2217
  var start = x[0],
2559
2218
  stop = x[1],
2560
- step = Math.floor((stop - start) / (domain.length + padding)),
2561
- err = stop - start - (domain.length - padding) * step;
2219
+ diff = stop - start,
2220
+ step = Math.floor(diff / (domain.length + padding)),
2221
+ err = diff - (domain.length - padding) * step;
2562
2222
  range = d3.range(start + Math.round(err / 2), stop, step);
2563
2223
  rangeBand = Math.round(step * (1 - padding));
2564
- ranger = {t: "rangeRoundBands", x: x, p: padding};
2565
2224
  return scale;
2566
2225
  };
2567
2226
 
@@ -2569,11 +2228,7 @@ function d3_scale_ordinal(domain, ranger) {
2569
2228
  return rangeBand;
2570
2229
  };
2571
2230
 
2572
- scale.copy = function() {
2573
- return d3_scale_ordinal(domain, ranger);
2574
- };
2575
-
2576
- return scale.domain(domain);
2231
+ return scale;
2577
2232
  };
2578
2233
  /*
2579
2234
  * This product includes color specifications and designs developed by Cynthia
@@ -2630,83 +2285,81 @@ var d3_category20c = [
2630
2285
  "#636363", "#969696", "#bdbdbd", "#d9d9d9"
2631
2286
  ];
2632
2287
  d3.scale.quantile = function() {
2633
- return d3_scale_quantile([], []);
2634
- };
2635
-
2636
- function d3_scale_quantile(domain, range) {
2637
- var thresholds;
2288
+ var domain = [],
2289
+ range = [],
2290
+ thresholds = [];
2638
2291
 
2639
2292
  function rescale() {
2640
- var k = 0,
2641
- n = domain.length,
2642
- q = range.length;
2643
- thresholds = [];
2644
- while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
2645
- return scale;
2293
+ var i = -1,
2294
+ n = thresholds.length = range.length,
2295
+ k = domain.length / n;
2296
+ while (++i < n) thresholds[i] = domain[~~(i * k)];
2297
+ }
2298
+
2299
+ function quantile(value) {
2300
+ if (isNaN(value = +value)) return NaN;
2301
+ var low = 0, high = thresholds.length - 1;
2302
+ while (low <= high) {
2303
+ var mid = (low + high) >> 1, midValue = thresholds[mid];
2304
+ if (midValue < value) low = mid + 1;
2305
+ else if (midValue > value) high = mid - 1;
2306
+ else return mid;
2307
+ }
2308
+ return high < 0 ? 0 : high;
2646
2309
  }
2647
2310
 
2648
2311
  function scale(x) {
2649
- if (isNaN(x = +x)) return NaN;
2650
- return range[d3.bisect(thresholds, x)];
2312
+ return range[quantile(x)];
2651
2313
  }
2652
2314
 
2653
2315
  scale.domain = function(x) {
2654
2316
  if (!arguments.length) return domain;
2655
2317
  domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending);
2656
- return rescale();
2318
+ rescale();
2319
+ return scale;
2657
2320
  };
2658
2321
 
2659
2322
  scale.range = function(x) {
2660
2323
  if (!arguments.length) return range;
2661
2324
  range = x;
2662
- return rescale();
2325
+ rescale();
2326
+ return scale;
2663
2327
  };
2664
2328
 
2665
2329
  scale.quantiles = function() {
2666
2330
  return thresholds;
2667
2331
  };
2668
2332
 
2669
- scale.copy = function() {
2670
- return d3_scale_quantile(domain, range); // copy on write!
2671
- };
2672
-
2673
- return rescale();
2333
+ return scale;
2674
2334
  };
2675
2335
  d3.scale.quantize = function() {
2676
- return d3_scale_quantize(0, 1, [0, 1]);
2677
- };
2678
-
2679
- function d3_scale_quantize(x0, x1, range) {
2680
- var kx, i;
2336
+ var x0 = 0,
2337
+ x1 = 1,
2338
+ kx = 2,
2339
+ i = 1,
2340
+ range = [0, 1];
2681
2341
 
2682
2342
  function scale(x) {
2683
2343
  return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
2684
2344
  }
2685
2345
 
2686
- function rescale() {
2687
- kx = range.length / (x1 - x0);
2688
- i = range.length - 1;
2689
- return scale;
2690
- }
2691
-
2692
2346
  scale.domain = function(x) {
2693
2347
  if (!arguments.length) return [x0, x1];
2694
- x0 = +x[0];
2695
- x1 = +x[x.length - 1];
2696
- return rescale();
2348
+ x0 = x[0];
2349
+ x1 = x[1];
2350
+ kx = range.length / (x1 - x0);
2351
+ return scale;
2697
2352
  };
2698
2353
 
2699
2354
  scale.range = function(x) {
2700
2355
  if (!arguments.length) return range;
2701
2356
  range = x;
2702
- return rescale();
2703
- };
2704
-
2705
- scale.copy = function() {
2706
- return d3_scale_quantize(x0, x1, range); // copy on write
2357
+ kx = range.length / (x1 - x0);
2358
+ i = range.length - 1;
2359
+ return scale;
2707
2360
  };
2708
2361
 
2709
- return rescale();
2362
+ return scale;
2710
2363
  };
2711
2364
  d3.svg = {};
2712
2365
  d3.svg.arc = function() {
@@ -2720,7 +2373,7 @@ d3.svg.arc = function() {
2720
2373
  r1 = outerRadius.apply(this, arguments),
2721
2374
  a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset,
2722
2375
  a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset,
2723
- da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0),
2376
+ da = a1 - a0,
2724
2377
  df = da < Math.PI ? "0" : "1",
2725
2378
  c0 = Math.cos(a0),
2726
2379
  s0 = Math.sin(a0),
@@ -2732,8 +2385,8 @@ d3.svg.arc = function() {
2732
2385
  + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
2733
2386
  + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
2734
2387
  + "M0," + r0
2735
- + "A" + r0 + "," + r0 + " 0 1,0 0," + (-r0)
2736
- + "A" + r0 + "," + r0 + " 0 1,0 0," + r0
2388
+ + "A" + r0 + "," + r0 + " 0 1,1 0," + (-r0)
2389
+ + "A" + r0 + "," + r0 + " 0 1,1 0," + r0
2737
2390
  + "Z"
2738
2391
  : "M0," + r1
2739
2392
  + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
@@ -2804,7 +2457,7 @@ function d3_svg_arcStartAngle(d) {
2804
2457
  function d3_svg_arcEndAngle(d) {
2805
2458
  return d.endAngle;
2806
2459
  }
2807
- function d3_svg_line(projection) {
2460
+ d3.svg.line = function() {
2808
2461
  var x = d3_svg_lineX,
2809
2462
  y = d3_svg_lineY,
2810
2463
  interpolate = "linear",
@@ -2812,7 +2465,8 @@ function d3_svg_line(projection) {
2812
2465
  tension = .7;
2813
2466
 
2814
2467
  function line(d) {
2815
- return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension);
2468
+ return d.length < 1 ? null
2469
+ : "M" + interpolator(d3_svg_linePoints(this, d, x, y), tension);
2816
2470
  }
2817
2471
 
2818
2472
  line.x = function(v) {
@@ -2839,11 +2493,7 @@ function d3_svg_line(projection) {
2839
2493
  return line;
2840
2494
  };
2841
2495
 
2842
- return line;
2843
- }
2844
-
2845
- d3.svg.line = function() {
2846
- return d3_svg_line(Object);
2496
+ return line;
2847
2497
  };
2848
2498
 
2849
2499
  // Converts the specified array of data into an array of points
@@ -2854,8 +2504,8 @@ function d3_svg_linePoints(self, d, x, y) {
2854
2504
  var points = [],
2855
2505
  i = -1,
2856
2506
  n = d.length,
2857
- fx = typeof x === "function",
2858
- fy = typeof y === "function",
2507
+ fx = typeof x == "function",
2508
+ fy = typeof y == "function",
2859
2509
  value;
2860
2510
  if (fx && fy) {
2861
2511
  while (++i < n) points.push([
@@ -2888,53 +2538,44 @@ var d3_svg_lineInterpolators = {
2888
2538
  "step-before": d3_svg_lineStepBefore,
2889
2539
  "step-after": d3_svg_lineStepAfter,
2890
2540
  "basis": d3_svg_lineBasis,
2891
- "basis-open": d3_svg_lineBasisOpen,
2892
2541
  "basis-closed": d3_svg_lineBasisClosed,
2893
- "bundle": d3_svg_lineBundle,
2894
2542
  "cardinal": d3_svg_lineCardinal,
2895
- "cardinal-open": d3_svg_lineCardinalOpen,
2896
- "cardinal-closed": d3_svg_lineCardinalClosed,
2897
- "monotone": d3_svg_lineMonotone
2543
+ "cardinal-closed": d3_svg_lineCardinalClosed
2898
2544
  };
2899
2545
 
2900
2546
  // Linear interpolation; generates "L" commands.
2901
2547
  function d3_svg_lineLinear(points) {
2902
- var i = 0,
2548
+ var path = [],
2549
+ i = 0,
2903
2550
  n = points.length,
2904
- p = points[0],
2905
- path = [p[0], ",", p[1]];
2551
+ p = points[0];
2552
+ path.push(p[0], ",", p[1]);
2906
2553
  while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]);
2907
2554
  return path.join("");
2908
2555
  }
2909
2556
 
2910
2557
  // Step interpolation; generates "H" and "V" commands.
2911
2558
  function d3_svg_lineStepBefore(points) {
2912
- var i = 0,
2559
+ var path = [],
2560
+ i = 0,
2913
2561
  n = points.length,
2914
- p = points[0],
2915
- path = [p[0], ",", p[1]];
2562
+ p = points[0];
2563
+ path.push(p[0], ",", p[1]);
2916
2564
  while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
2917
2565
  return path.join("");
2918
2566
  }
2919
2567
 
2920
2568
  // Step interpolation; generates "H" and "V" commands.
2921
2569
  function d3_svg_lineStepAfter(points) {
2922
- var i = 0,
2570
+ var path = [],
2571
+ i = 0,
2923
2572
  n = points.length,
2924
- p = points[0],
2925
- path = [p[0], ",", p[1]];
2573
+ p = points[0];
2574
+ path.push(p[0], ",", p[1]);
2926
2575
  while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
2927
2576
  return path.join("");
2928
2577
  }
2929
2578
 
2930
- // Open cardinal spline interpolation; generates "C" commands.
2931
- function d3_svg_lineCardinalOpen(points, tension) {
2932
- return points.length < 4
2933
- ? d3_svg_lineLinear(points)
2934
- : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1),
2935
- d3_svg_lineCardinalTangents(points, tension));
2936
- }
2937
-
2938
2579
  // Closed cardinal spline interpolation; generates "C" commands.
2939
2580
  function d3_svg_lineCardinalClosed(points, tension) {
2940
2581
  return points.length < 3
@@ -3017,17 +2658,18 @@ function d3_svg_lineCardinalTangents(points, tension) {
3017
2658
  return tangents;
3018
2659
  }
3019
2660
 
3020
- // B-spline interpolation; generates "C" commands.
2661
+ // Open B-spline interpolation; generates "C" commands.
3021
2662
  function d3_svg_lineBasis(points) {
3022
2663
  if (points.length < 3) return d3_svg_lineLinear(points);
3023
- var i = 1,
2664
+ var path = [],
2665
+ i = 1,
3024
2666
  n = points.length,
3025
2667
  pi = points[0],
3026
2668
  x0 = pi[0],
3027
2669
  y0 = pi[1],
3028
2670
  px = [x0, x0, x0, (pi = points[1])[0]],
3029
- py = [y0, y0, y0, pi[1]],
3030
- path = [x0, ",", y0];
2671
+ py = [y0, y0, y0, pi[1]];
2672
+ path.push(x0, ",", y0);
3031
2673
  d3_svg_lineBasisBezier(path, px, py);
3032
2674
  while (++i < n) {
3033
2675
  pi = points[i];
@@ -3044,31 +2686,6 @@ function d3_svg_lineBasis(points) {
3044
2686
  return path.join("");
3045
2687
  }
3046
2688
 
3047
- // Open B-spline interpolation; generates "C" commands.
3048
- function d3_svg_lineBasisOpen(points) {
3049
- if (points.length < 4) return d3_svg_lineLinear(points);
3050
- var path = [],
3051
- i = -1,
3052
- n = points.length,
3053
- pi,
3054
- px = [0],
3055
- py = [0];
3056
- while (++i < 3) {
3057
- pi = points[i];
3058
- px.push(pi[0]);
3059
- py.push(pi[1]);
3060
- }
3061
- path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px)
3062
- + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
3063
- --i; while (++i < n) {
3064
- pi = points[i];
3065
- px.shift(); px.push(pi[0]);
3066
- py.shift(); py.push(pi[1]);
3067
- d3_svg_lineBasisBezier(path, px, py);
3068
- }
3069
- return path.join("");
3070
- }
3071
-
3072
2689
  // Closed B-spline interpolation; generates "C" commands.
3073
2690
  function d3_svg_lineBasisClosed(points) {
3074
2691
  var path,
@@ -3096,24 +2713,6 @@ function d3_svg_lineBasisClosed(points) {
3096
2713
  return path.join("");
3097
2714
  }
3098
2715
 
3099
- function d3_svg_lineBundle(points, tension) {
3100
- var n = points.length - 1,
3101
- x0 = points[0][0],
3102
- y0 = points[0][1],
3103
- dx = points[n][0] - x0,
3104
- dy = points[n][1] - y0,
3105
- i = -1,
3106
- p,
3107
- t;
3108
- while (++i <= n) {
3109
- p = points[i];
3110
- t = i / n;
3111
- p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
3112
- p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
3113
- }
3114
- return d3_svg_lineBasis(points);
3115
- }
3116
-
3117
2716
  // Returns the dot product of the given four-element vectors.
3118
2717
  function d3_svg_lineDot4(a, b) {
3119
2718
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
@@ -3125,7 +2724,7 @@ var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0],
3125
2724
  d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0],
3126
2725
  d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6];
3127
2726
 
3128
- // Pushes a "C" Bézier curve onto the specified path array, given the
2727
+ // Pushes a "C" Bézier curve onto the specified path array, given the
3129
2728
  // two specified four-element arrays which define the control points.
3130
2729
  function d3_svg_lineBasisBezier(path, x, y) {
3131
2730
  path.push(
@@ -3136,210 +2735,59 @@ function d3_svg_lineBasisBezier(path, x, y) {
3136
2735
  ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x),
3137
2736
  ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
3138
2737
  }
3139
-
3140
- // Computes the slope from points p0 to p1.
3141
- function d3_svg_lineSlope(p0, p1) {
3142
- return (p1[1] - p0[1]) / (p1[0] - p0[0]);
3143
- }
3144
-
3145
- // Compute three-point differences for the given points.
3146
- // http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Finite_difference
3147
- function d3_svg_lineFiniteDifferences(points) {
3148
- var i = 0,
3149
- j = points.length - 1,
3150
- m = [],
3151
- p0 = points[0],
3152
- p1 = points[1],
3153
- d = m[0] = d3_svg_lineSlope(p0, p1);
3154
- while (++i < j) {
3155
- m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]));
3156
- }
3157
- m[i] = d;
3158
- return m;
3159
- }
3160
-
3161
- // Interpolates the given points using Fritsch-Carlson Monotone cubic Hermite
3162
- // interpolation. Returns an array of tangent vectors. For details, see
3163
- // http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
3164
- function d3_svg_lineMonotoneTangents(points) {
3165
- var tangents = [],
3166
- d,
3167
- a,
3168
- b,
3169
- s,
3170
- m = d3_svg_lineFiniteDifferences(points),
3171
- i = -1,
3172
- j = points.length - 1;
3173
-
3174
- // The first two steps are done by computing finite-differences:
3175
- // 1. Compute the slopes of the secant lines between successive points.
3176
- // 2. Initialize the tangents at every point as the average of the secants.
3177
-
3178
- // Then, for each segment…
3179
- while (++i < j) {
3180
- d = d3_svg_lineSlope(points[i], points[i + 1]);
3181
-
3182
- // 3. If two successive yk = y{k + 1} are equal (i.e., d is zero), then set
3183
- // mk = m{k + 1} = 0 as the spline connecting these points must be flat to
3184
- // preserve monotonicity. Ignore step 4 and 5 for those k.
3185
-
3186
- if (Math.abs(d) < 1e-6) {
3187
- m[i] = m[i + 1] = 0;
3188
- } else {
3189
- // 4. Let ak = mk / dk and bk = m{k + 1} / dk.
3190
- a = m[i] / d;
3191
- b = m[i + 1] / d;
3192
-
3193
- // 5. Prevent overshoot and ensure monotonicity by restricting the
3194
- // magnitude of vector <ak, bk> to a circle of radius 3.
3195
- s = a * a + b * b;
3196
- if (s > 9) {
3197
- s = d * 3 / Math.sqrt(s);
3198
- m[i] = s * a;
3199
- m[i + 1] = s * b;
3200
- }
3201
- }
3202
- }
3203
-
3204
- // Compute the normalized tangent vector from the slopes. Note that if x is
3205
- // not monotonic, it's possible that the slope will be infinite, so we protect
3206
- // against NaN by setting the coordinate to zero.
3207
- i = -1; while (++i <= j) {
3208
- s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0])
3209
- / (6 * (1 + m[i] * m[i]));
3210
- tangents.push([s || 0, m[i] * s || 0]);
3211
- }
3212
-
3213
- return tangents;
3214
- }
3215
-
3216
- function d3_svg_lineMonotone(points) {
3217
- return points.length < 3
3218
- ? d3_svg_lineLinear(points)
3219
- : points[0] +
3220
- d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
3221
- }
3222
- d3.svg.line.radial = function() {
3223
- var line = d3_svg_line(d3_svg_lineRadial);
3224
- line.radius = line.x, delete line.x;
3225
- line.angle = line.y, delete line.y;
3226
- return line;
3227
- };
3228
-
3229
- function d3_svg_lineRadial(points) {
3230
- var point,
3231
- i = -1,
3232
- n = points.length,
3233
- r,
3234
- a;
3235
- while (++i < n) {
3236
- point = points[i];
3237
- r = point[0];
3238
- a = point[1] + d3_svg_arcOffset;
3239
- point[0] = r * Math.cos(a);
3240
- point[1] = r * Math.sin(a);
3241
- }
3242
- return points;
3243
- }
3244
- function d3_svg_area(projection) {
3245
- var x0 = d3_svg_lineX,
3246
- x1 = d3_svg_lineX,
3247
- y0 = 0,
2738
+ d3.svg.area = function() {
2739
+ var x = d3_svg_lineX,
2740
+ y0 = d3_svg_areaY0,
3248
2741
  y1 = d3_svg_lineY,
3249
- interpolate,
3250
- i0,
3251
- i1,
2742
+ interpolate = "linear",
2743
+ interpolator = d3_svg_lineInterpolators[interpolate],
3252
2744
  tension = .7;
3253
2745
 
2746
+ // TODO horizontal / vertical / radial orientation
2747
+
3254
2748
  function area(d) {
3255
- if (d.length < 1) return null;
3256
- var points0 = d3_svg_linePoints(this, d, x0, y0),
3257
- points1 = d3_svg_linePoints(this, d, x0 === x1 ? d3_svg_areaX(points0) : x1, y0 === y1 ? d3_svg_areaY(points0) : y1);
3258
- return "M" + i0(projection(points1), tension)
3259
- + "L" + i1(projection(points0.reverse()), tension)
3260
- + "Z";
2749
+ return d.length < 1 ? null
2750
+ : "M" + interpolator(d3_svg_linePoints(this, d, x, y1), tension)
2751
+ + "L" + interpolator(d3_svg_linePoints(this, d, x, y0).reverse(), tension)
2752
+ + "Z";
3261
2753
  }
3262
2754
 
3263
- area.x = function(x) {
3264
- if (!arguments.length) return x1;
3265
- x0 = x1 = x;
3266
- return area;
3267
- };
3268
-
3269
- area.x0 = function(x) {
3270
- if (!arguments.length) return x0;
3271
- x0 = x;
3272
- return area;
3273
- };
3274
-
3275
- area.x1 = function(x) {
3276
- if (!arguments.length) return x1;
3277
- x1 = x;
3278
- return area;
3279
- };
3280
-
3281
- area.y = function(y) {
3282
- if (!arguments.length) return y1;
3283
- y0 = y1 = y;
2755
+ area.x = function(v) {
2756
+ if (!arguments.length) return x;
2757
+ x = v;
3284
2758
  return area;
3285
2759
  };
3286
2760
 
3287
- area.y0 = function(y) {
2761
+ area.y0 = function(v) {
3288
2762
  if (!arguments.length) return y0;
3289
- y0 = y;
2763
+ y0 = v;
3290
2764
  return area;
3291
2765
  };
3292
2766
 
3293
- area.y1 = function(y) {
2767
+ area.y1 = function(v) {
3294
2768
  if (!arguments.length) return y1;
3295
- y1 = y;
2769
+ y1 = v;
3296
2770
  return area;
3297
2771
  };
3298
2772
 
3299
- area.interpolate = function(x) {
2773
+ area.interpolate = function(v) {
3300
2774
  if (!arguments.length) return interpolate;
3301
- i0 = d3_svg_lineInterpolators[interpolate = x];
3302
- i1 = i0.reverse || i0;
2775
+ interpolator = d3_svg_lineInterpolators[interpolate = v];
3303
2776
  return area;
3304
2777
  };
3305
2778
 
3306
- area.tension = function(x) {
2779
+ area.tension = function(v) {
3307
2780
  if (!arguments.length) return tension;
3308
- tension = x;
2781
+ tension = v;
3309
2782
  return area;
3310
2783
  };
3311
2784
 
3312
- return area.interpolate("linear");
3313
- }
3314
-
3315
- d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
3316
- d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
3317
-
3318
- d3.svg.area = function() {
3319
- return d3_svg_area(Object);
2785
+ return area;
3320
2786
  };
3321
2787
 
3322
- function d3_svg_areaX(points) {
3323
- return function(d, i) {
3324
- return points[i][0];
3325
- };
3326
- }
3327
-
3328
- function d3_svg_areaY(points) {
3329
- return function(d, i) {
3330
- return points[i][1];
3331
- };
2788
+ function d3_svg_areaY0() {
2789
+ return 0;
3332
2790
  }
3333
- d3.svg.area.radial = function() {
3334
- var area = d3_svg_area(d3_svg_lineRadial);
3335
- area.radius = area.x, delete area.x;
3336
- area.innerRadius = area.x0, delete area.x0;
3337
- area.outerRadius = area.x1, delete area.x1;
3338
- area.angle = area.y, delete area.y;
3339
- area.startAngle = area.y0, delete area.y0;
3340
- area.endAngle = area.y1, delete area.y1;
3341
- return area;
3342
- };
3343
2791
  d3.svg.chord = function() {
3344
2792
  var source = d3_svg_chordSource,
3345
2793
  target = d3_svg_chordTarget,
@@ -3477,36 +2925,7 @@ d3.svg.diagonal = function() {
3477
2925
  function d3_svg_diagonalProjection(d) {
3478
2926
  return [d.x, d.y];
3479
2927
  }
3480
- d3.svg.diagonal.radial = function() {
3481
- var diagonal = d3.svg.diagonal(),
3482
- projection = d3_svg_diagonalProjection,
3483
- projection_ = diagonal.projection;
3484
-
3485
- diagonal.projection = function(x) {
3486
- return arguments.length
3487
- ? projection_(d3_svg_diagonalRadialProjection(projection = x))
3488
- : projection;
3489
- };
3490
-
3491
- return diagonal;
3492
- };
3493
-
3494
- function d3_svg_diagonalRadialProjection(projection) {
3495
- return function() {
3496
- var d = projection.apply(this, arguments),
3497
- r = d[0],
3498
- a = d[1] + d3_svg_arcOffset;
3499
- return [r * Math.cos(a), r * Math.sin(a)];
3500
- };
3501
- }
3502
2928
  d3.svg.mouse = function(container) {
3503
- return d3_svg_mousePoint(container, d3.event);
3504
- };
3505
-
3506
- // https://bugs.webkit.org/show_bug.cgi?id=44083
3507
- var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
3508
-
3509
- function d3_svg_mousePoint(container, e) {
3510
2929
  var point = (container.ownerSVGElement || container).createSVGPoint();
3511
2930
  if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) {
3512
2931
  var svg = d3.select(document.body)
@@ -3519,23 +2938,18 @@ function d3_svg_mousePoint(container, e) {
3519
2938
  svg.remove();
3520
2939
  }
3521
2940
  if (d3_mouse_bug44083) {
3522
- point.x = e.pageX;
3523
- point.y = e.pageY;
2941
+ point.x = d3.event.pageX;
2942
+ point.y = d3.event.pageY;
3524
2943
  } else {
3525
- point.x = e.clientX;
3526
- point.y = e.clientY;
2944
+ point.x = d3.event.clientX;
2945
+ point.y = d3.event.clientY;
3527
2946
  }
3528
2947
  point = point.matrixTransform(container.getScreenCTM().inverse());
3529
2948
  return [point.x, point.y];
3530
2949
  };
3531
- d3.svg.touches = function(container) {
3532
- var touches = d3.event.touches;
3533
- return touches ? d3_array(touches).map(function(touch) {
3534
- var point = d3_svg_mousePoint(container, touch);
3535
- point.identifier = touch.identifier;
3536
- return point;
3537
- }) : [];
3538
- };
2950
+
2951
+ // https://bugs.webkit.org/show_bug.cgi?id=44083
2952
+ var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
3539
2953
  d3.svg.symbol = function() {
3540
2954
  var type = d3_svg_symbolType,
3541
2955
  size = d3_svg_symbolSize;
@@ -3562,6 +2976,16 @@ d3.svg.symbol = function() {
3562
2976
  return symbol;
3563
2977
  };
3564
2978
 
2979
+ // TODO cross-diagonal?
2980
+ d3.svg.symbolTypes = [
2981
+ "circle",
2982
+ "cross",
2983
+ "diamond",
2984
+ "square",
2985
+ "triangle-down",
2986
+ "triangle-up"
2987
+ ];
2988
+
3565
2989
  function d3_svg_symbolSize() {
3566
2990
  return 64;
3567
2991
  }
@@ -3570,7 +2994,6 @@ function d3_svg_symbolType() {
3570
2994
  return "circle";
3571
2995
  }
3572
2996
 
3573
- // TODO cross-diagonal?
3574
2997
  var d3_svg_symbols = {
3575
2998
  "circle": function(size) {
3576
2999
  var r = Math.sqrt(size / Math.PI);
@@ -3630,520 +3053,6 @@ var d3_svg_symbols = {
3630
3053
  }
3631
3054
  };
3632
3055
 
3633
- d3.svg.symbolTypes = d3.keys(d3_svg_symbols);
3634
-
3635
3056
  var d3_svg_symbolSqrt3 = Math.sqrt(3),
3636
3057
  d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180);
3637
- d3.svg.axis = function() {
3638
- var scale = d3.scale.linear(),
3639
- orient = "bottom",
3640
- tickMajorSize = 6,
3641
- tickMinorSize = 6,
3642
- tickEndSize = 6,
3643
- tickPadding = 3,
3644
- tickArguments_ = [10],
3645
- tickFormat_,
3646
- tickSubdivide = 0;
3647
-
3648
- function axis(selection) {
3649
- selection.each(function(d, i, j) {
3650
- var g = d3.select(this);
3651
-
3652
- // If selection is a transition, create subtransitions.
3653
- var transition = selection.delay ? function(o) {
3654
- var id = d3_transitionInheritId;
3655
- try {
3656
- d3_transitionInheritId = selection.id;
3657
- return o.transition()
3658
- .delay(selection[j][i].delay)
3659
- .duration(selection[j][i].duration)
3660
- .ease(selection.ease());
3661
- } finally {
3662
- d3_transitionInheritId = id;
3663
- }
3664
- } : Object;
3665
-
3666
- // Ticks.
3667
- var ticks = scale.ticks.apply(scale, tickArguments_),
3668
- tickFormat = tickFormat_ == null ? scale.tickFormat.apply(scale, tickArguments_) : tickFormat_;
3669
-
3670
- // Minor ticks.
3671
- var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide),
3672
- subtick = g.selectAll(".minor").data(subticks, String),
3673
- subtickEnter = subtick.enter().insert("svg:line", "g").attr("class", "tick minor").style("opacity", 1e-6),
3674
- subtickExit = transition(subtick.exit()).style("opacity", 1e-6).remove(),
3675
- subtickUpdate = transition(subtick).style("opacity", 1);
3676
-
3677
- // Major ticks.
3678
- var tick = g.selectAll("g").data(ticks, String),
3679
- tickEnter = tick.enter().insert("svg:g", "path").style("opacity", 1e-6),
3680
- tickExit = transition(tick.exit()).style("opacity", 1e-6).remove(),
3681
- tickUpdate = transition(tick).style("opacity", 1),
3682
- tickTransform;
3683
-
3684
- // Domain.
3685
- var range = d3_scaleExtent(scale.range()),
3686
- path = g.selectAll(".domain").data([0]),
3687
- pathEnter = path.enter().append("svg:path").attr("class", "domain"),
3688
- pathUpdate = transition(path);
3689
-
3690
- // Stash the new scale and grab the old scale.
3691
- var scale0 = this.__chart__ || scale;
3692
- this.__chart__ = scale.copy();
3693
-
3694
- tickEnter.append("svg:line").attr("class", "tick");
3695
- tickEnter.append("svg:text");
3696
- tickUpdate.select("text").text(tickFormat);
3697
-
3698
- switch (orient) {
3699
- case "bottom": {
3700
- tickTransform = d3_svg_axisX;
3701
- subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
3702
- tickUpdate.select("line").attr("x2", 0).attr("y2", tickMajorSize);
3703
- tickUpdate.select("text").attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding).attr("dy", ".71em").attr("text-anchor", "middle");
3704
- pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
3705
- break;
3706
- }
3707
- case "top": {
3708
- tickTransform = d3_svg_axisX;
3709
- subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
3710
- tickUpdate.select("line").attr("x2", 0).attr("y2", -tickMajorSize);
3711
- tickUpdate.select("text").attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("dy", "0em").attr("text-anchor", "middle");
3712
- pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
3713
- break;
3714
- }
3715
- case "left": {
3716
- tickTransform = d3_svg_axisY;
3717
- subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
3718
- tickUpdate.select("line").attr("x2", -tickMajorSize).attr("y2", 0);
3719
- tickUpdate.select("text").attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "end");
3720
- pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
3721
- break;
3722
- }
3723
- case "right": {
3724
- tickTransform = d3_svg_axisY;
3725
- subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
3726
- tickUpdate.select("line").attr("x2", tickMajorSize).attr("y2", 0);
3727
- tickUpdate.select("text").attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0).attr("dy", ".32em").attr("text-anchor", "start");
3728
- pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
3729
- break;
3730
- }
3731
- }
3732
-
3733
- tickEnter.call(tickTransform, scale0);
3734
- tickUpdate.call(tickTransform, scale);
3735
- tickExit.call(tickTransform, scale);
3736
-
3737
- subtickEnter.call(tickTransform, scale0);
3738
- subtickUpdate.call(tickTransform, scale);
3739
- subtickExit.call(tickTransform, scale);
3740
- });
3741
- }
3742
-
3743
- axis.scale = function(x) {
3744
- if (!arguments.length) return scale;
3745
- scale = x;
3746
- return axis;
3747
- };
3748
-
3749
- axis.orient = function(x) {
3750
- if (!arguments.length) return orient;
3751
- orient = x;
3752
- return axis;
3753
- };
3754
-
3755
- axis.ticks = function() {
3756
- if (!arguments.length) return tickArguments_;
3757
- tickArguments_ = arguments;
3758
- return axis;
3759
- };
3760
-
3761
- axis.tickFormat = function(x) {
3762
- if (!arguments.length) return tickFormat_;
3763
- tickFormat_ = x;
3764
- return axis;
3765
- };
3766
-
3767
- axis.tickSize = function(x, y, z) {
3768
- if (!arguments.length) return tickMajorSize;
3769
- var n = arguments.length - 1;
3770
- tickMajorSize = +x;
3771
- tickMinorSize = n > 1 ? +y : tickMajorSize;
3772
- tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
3773
- return axis;
3774
- };
3775
-
3776
- axis.tickPadding = function(x) {
3777
- if (!arguments.length) return tickPadding;
3778
- tickPadding = +x;
3779
- return axis;
3780
- };
3781
-
3782
- axis.tickSubdivide = function(x) {
3783
- if (!arguments.length) return tickSubdivide;
3784
- tickSubdivide = +x;
3785
- return axis;
3786
- };
3787
-
3788
- return axis;
3789
- };
3790
-
3791
- function d3_svg_axisX(selection, x) {
3792
- selection.attr("transform", function(d) { return "translate(" + x(d) + ",0)"; });
3793
- }
3794
-
3795
- function d3_svg_axisY(selection, y) {
3796
- selection.attr("transform", function(d) { return "translate(0," + y(d) + ")"; });
3797
- }
3798
-
3799
- function d3_svg_axisSubdivide(scale, ticks, m) {
3800
- subticks = [];
3801
- if (m && ticks.length > 1) {
3802
- var extent = d3_scaleExtent(scale.domain()),
3803
- subticks,
3804
- i = -1,
3805
- n = ticks.length,
3806
- d = (ticks[1] - ticks[0]) / ++m,
3807
- j,
3808
- v;
3809
- while (++i < n) {
3810
- for (j = m; --j > 0;) {
3811
- if ((v = +ticks[i] - j * d) >= extent[0]) {
3812
- subticks.push(v);
3813
- }
3814
- }
3815
- }
3816
- for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
3817
- subticks.push(v);
3818
- }
3819
- }
3820
- return subticks;
3821
- }
3822
- d3.behavior = {};
3823
- d3.behavior.drag = function() {
3824
- var event = d3.dispatch("drag", "dragstart", "dragend");
3825
-
3826
- function drag() {
3827
- this
3828
- .on("mousedown.drag", mousedown)
3829
- .on("touchstart.drag", mousedown);
3830
-
3831
- d3.select(window)
3832
- .on("mousemove.drag", d3_behavior_dragMove)
3833
- .on("touchmove.drag", d3_behavior_dragMove)
3834
- .on("mouseup.drag", d3_behavior_dragUp, true)
3835
- .on("touchend.drag", d3_behavior_dragUp, true)
3836
- .on("click.drag", d3_behavior_dragClick, true);
3837
- }
3838
-
3839
- // snapshot the local context for subsequent dispatch
3840
- function start() {
3841
- d3_behavior_dragEvent = event;
3842
- d3_behavior_dragEventTarget = d3.event.target;
3843
- d3_behavior_dragOffset = d3_behavior_dragPoint((d3_behavior_dragTarget = this).parentNode);
3844
- d3_behavior_dragMoved = 0;
3845
- d3_behavior_dragArguments = arguments;
3846
- }
3847
-
3848
- function mousedown() {
3849
- start.apply(this, arguments);
3850
- d3_behavior_dragDispatch("dragstart");
3851
- }
3852
-
3853
- drag.on = function(type, listener) {
3854
- event[type].add(listener);
3855
- return drag;
3856
- };
3857
-
3858
- return drag;
3859
- };
3860
-
3861
- var d3_behavior_dragEvent,
3862
- d3_behavior_dragEventTarget,
3863
- d3_behavior_dragTarget,
3864
- d3_behavior_dragArguments,
3865
- d3_behavior_dragOffset,
3866
- d3_behavior_dragMoved,
3867
- d3_behavior_dragStopClick;
3868
-
3869
- function d3_behavior_dragDispatch(type) {
3870
- var o = d3.event, p = d3_behavior_dragTarget.parentNode, dx = 0, dy = 0;
3871
-
3872
- if (p) {
3873
- p = d3_behavior_dragPoint(p);
3874
- dx = p[0] - d3_behavior_dragOffset[0];
3875
- dy = p[1] - d3_behavior_dragOffset[1];
3876
- d3_behavior_dragOffset = p;
3877
- d3_behavior_dragMoved |= dx | dy;
3878
- }
3879
-
3880
- try {
3881
- d3.event = {dx: dx, dy: dy};
3882
- d3_behavior_dragEvent[type].dispatch.apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
3883
- } finally {
3884
- d3.event = o;
3885
- }
3886
-
3887
- o.preventDefault();
3888
- }
3889
-
3890
- function d3_behavior_dragPoint(container) {
3891
- return d3.event.touches
3892
- ? d3.svg.touches(container)[0]
3893
- : d3.svg.mouse(container);
3894
- }
3895
-
3896
- function d3_behavior_dragMove() {
3897
- if (!d3_behavior_dragTarget) return;
3898
- var parent = d3_behavior_dragTarget.parentNode;
3899
-
3900
- // O NOES! The drag element was removed from the DOM.
3901
- if (!parent) return d3_behavior_dragUp();
3902
-
3903
- d3_behavior_dragDispatch("drag");
3904
- d3_behavior_dragCancel();
3905
- }
3906
-
3907
- function d3_behavior_dragUp() {
3908
- if (!d3_behavior_dragTarget) return;
3909
- d3_behavior_dragDispatch("dragend");
3910
- d3_behavior_dragTarget = null;
3911
-
3912
- // If the node was moved, prevent the mouseup from propagating.
3913
- // Also prevent the subsequent click from propagating (e.g., for anchors).
3914
- if (d3_behavior_dragMoved && d3_behavior_dragEventTarget === d3.event.target) {
3915
- d3_behavior_dragStopClick = true;
3916
- d3_behavior_dragCancel();
3917
- }
3918
- }
3919
-
3920
- function d3_behavior_dragClick() {
3921
- if (d3_behavior_dragStopClick && d3_behavior_dragEventTarget === d3.event.target) {
3922
- d3_behavior_dragCancel();
3923
- d3_behavior_dragStopClick = false;
3924
- d3_behavior_dragEventTarget = null;
3925
- }
3926
- }
3927
-
3928
- function d3_behavior_dragCancel() {
3929
- d3.event.stopPropagation();
3930
- d3.event.preventDefault();
3931
- }
3932
- // TODO unbind zoom behavior?
3933
- // TODO unbind listener?
3934
- d3.behavior.zoom = function() {
3935
- var xyz = [0, 0, 0],
3936
- event = d3.dispatch("zoom");
3937
-
3938
- function zoom() {
3939
- this
3940
- .on("mousedown.zoom", mousedown)
3941
- .on("mousewheel.zoom", mousewheel)
3942
- .on("DOMMouseScroll.zoom", mousewheel)
3943
- .on("dblclick.zoom", dblclick)
3944
- .on("touchstart.zoom", touchstart);
3945
-
3946
- d3.select(window)
3947
- .on("mousemove.zoom", d3_behavior_zoomMousemove)
3948
- .on("mouseup.zoom", d3_behavior_zoomMouseup)
3949
- .on("touchmove.zoom", d3_behavior_zoomTouchmove)
3950
- .on("touchend.zoom", d3_behavior_zoomTouchup)
3951
- .on("click.zoom", d3_behavior_zoomClick, true);
3952
- }
3953
-
3954
- // snapshot the local context for subsequent dispatch
3955
- function start() {
3956
- d3_behavior_zoomXyz = xyz;
3957
- d3_behavior_zoomDispatch = event.zoom.dispatch;
3958
- d3_behavior_zoomEventTarget = d3.event.target;
3959
- d3_behavior_zoomTarget = this;
3960
- d3_behavior_zoomArguments = arguments;
3961
- }
3962
-
3963
- function mousedown() {
3964
- start.apply(this, arguments);
3965
- d3_behavior_zoomPanning = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget));
3966
- d3_behavior_zoomMoved = false;
3967
- d3.event.preventDefault();
3968
- window.focus();
3969
- }
3970
-
3971
- // store starting mouse location
3972
- function mousewheel() {
3973
- start.apply(this, arguments);
3974
- if (!d3_behavior_zoomZooming) d3_behavior_zoomZooming = d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget));
3975
- d3_behavior_zoomTo(d3_behavior_zoomDelta() + xyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomZooming);
3976
- }
3977
-
3978
- function dblclick() {
3979
- start.apply(this, arguments);
3980
- var mouse = d3.svg.mouse(d3_behavior_zoomTarget);
3981
- d3_behavior_zoomTo(d3.event.shiftKey ? Math.ceil(xyz[2] - 1) : Math.floor(xyz[2] + 1), mouse, d3_behavior_zoomLocation(mouse));
3982
- }
3983
-
3984
- // doubletap detection
3985
- function touchstart() {
3986
- start.apply(this, arguments);
3987
- var touches = d3_behavior_zoomTouchup(),
3988
- touch,
3989
- now = Date.now();
3990
- if ((touches.length === 1) && (now - d3_behavior_zoomLast < 300)) {
3991
- d3_behavior_zoomTo(1 + Math.floor(xyz[2]), touch = touches[0], d3_behavior_zoomLocations[touch.identifier]);
3992
- }
3993
- d3_behavior_zoomLast = now;
3994
- }
3995
-
3996
- zoom.on = function(type, listener) {
3997
- event[type].add(listener);
3998
- return zoom;
3999
- };
4000
-
4001
- return zoom;
4002
- };
4003
-
4004
- var d3_behavior_zoomDiv,
4005
- d3_behavior_zoomPanning,
4006
- d3_behavior_zoomZooming,
4007
- d3_behavior_zoomLocations = {}, // identifier -> location
4008
- d3_behavior_zoomLast = 0,
4009
- d3_behavior_zoomXyz,
4010
- d3_behavior_zoomDispatch,
4011
- d3_behavior_zoomEventTarget,
4012
- d3_behavior_zoomTarget,
4013
- d3_behavior_zoomArguments,
4014
- d3_behavior_zoomMoved,
4015
- d3_behavior_zoomStopClick;
4016
-
4017
- function d3_behavior_zoomLocation(point) {
4018
- return [
4019
- point[0] - d3_behavior_zoomXyz[0],
4020
- point[1] - d3_behavior_zoomXyz[1],
4021
- d3_behavior_zoomXyz[2]
4022
- ];
4023
- }
4024
-
4025
- // detect the pixels that would be scrolled by this wheel event
4026
- function d3_behavior_zoomDelta() {
4027
-
4028
- // mousewheel events are totally broken!
4029
- // https://bugs.webkit.org/show_bug.cgi?id=40441
4030
- // not only that, but Chrome and Safari differ in re. to acceleration!
4031
- if (!d3_behavior_zoomDiv) {
4032
- d3_behavior_zoomDiv = d3.select("body").append("div")
4033
- .style("visibility", "hidden")
4034
- .style("top", 0)
4035
- .style("height", 0)
4036
- .style("width", 0)
4037
- .style("overflow-y", "scroll")
4038
- .append("div")
4039
- .style("height", "2000px")
4040
- .node().parentNode;
4041
- }
4042
-
4043
- var e = d3.event, delta;
4044
- try {
4045
- d3_behavior_zoomDiv.scrollTop = 1000;
4046
- d3_behavior_zoomDiv.dispatchEvent(e);
4047
- delta = 1000 - d3_behavior_zoomDiv.scrollTop;
4048
- } catch (error) {
4049
- delta = e.wheelDelta || (-e.detail * 5);
4050
- }
4051
-
4052
- return delta * .005;
4053
- }
4054
-
4055
- // Note: Since we don't rotate, it's possible for the touches to become
4056
- // slightly detached from their original positions. Thus, we recompute the
4057
- // touch points on touchend as well as touchstart!
4058
- function d3_behavior_zoomTouchup() {
4059
- var touches = d3.svg.touches(d3_behavior_zoomTarget),
4060
- i = -1,
4061
- n = touches.length,
4062
- touch;
4063
- while (++i < n) d3_behavior_zoomLocations[(touch = touches[i]).identifier] = d3_behavior_zoomLocation(touch);
4064
- return touches;
4065
- }
4066
-
4067
- function d3_behavior_zoomTouchmove() {
4068
- var touches = d3.svg.touches(d3_behavior_zoomTarget);
4069
- switch (touches.length) {
4070
-
4071
- // single-touch pan
4072
- case 1: {
4073
- var touch = touches[0];
4074
- d3_behavior_zoomTo(d3_behavior_zoomXyz[2], touch, d3_behavior_zoomLocations[touch.identifier]);
4075
- break;
4076
- }
4077
-
4078
- // double-touch pan + zoom
4079
- case 2: {
4080
- var p0 = touches[0],
4081
- p1 = touches[1],
4082
- p2 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2],
4083
- l0 = d3_behavior_zoomLocations[p0.identifier],
4084
- l1 = d3_behavior_zoomLocations[p1.identifier],
4085
- l2 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2, l0[2]];
4086
- d3_behavior_zoomTo(Math.log(d3.event.scale) / Math.LN2 + l0[2], p2, l2);
4087
- break;
4088
- }
4089
- }
4090
- }
4091
-
4092
- function d3_behavior_zoomMousemove() {
4093
- d3_behavior_zoomZooming = null;
4094
- if (d3_behavior_zoomPanning) {
4095
- d3_behavior_zoomMoved = true;
4096
- d3_behavior_zoomTo(d3_behavior_zoomXyz[2], d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomPanning);
4097
- }
4098
- }
4099
-
4100
- function d3_behavior_zoomMouseup() {
4101
- if (d3_behavior_zoomPanning) {
4102
- if (d3_behavior_zoomMoved && d3_behavior_zoomEventTarget === d3.event.target) {
4103
- d3_behavior_zoomStopClick = true;
4104
- }
4105
- d3_behavior_zoomMousemove();
4106
- d3_behavior_zoomPanning = null;
4107
- }
4108
- }
4109
-
4110
- function d3_behavior_zoomClick() {
4111
- if (d3_behavior_zoomStopClick && d3_behavior_zoomEventTarget === d3.event.target) {
4112
- d3.event.stopPropagation();
4113
- d3.event.preventDefault();
4114
- d3_behavior_zoomStopClick = false;
4115
- d3_behavior_zoomEventTarget = null;
4116
- }
4117
- }
4118
-
4119
- function d3_behavior_zoomTo(z, x0, x1) {
4120
- var K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]),
4121
- x = d3_behavior_zoomXyz[0] = x0[0] - K * x1[0],
4122
- y = d3_behavior_zoomXyz[1] = x0[1] - K * x1[1],
4123
- o = d3.event, // Events can be reentrant (e.g., focus).
4124
- k = Math.pow(2, z);
4125
-
4126
- d3.event = {
4127
- scale: k,
4128
- translate: [x, y],
4129
- transform: function(sx, sy) {
4130
- if (sx) transform(sx, x);
4131
- if (sy) transform(sy, y);
4132
- }
4133
- };
4134
-
4135
- function transform(scale, o) {
4136
- var domain = scale.__domain || (scale.__domain = scale.domain()),
4137
- range = scale.range().map(function(v) { return (v - o) / k; });
4138
- scale.domain(domain).domain(range.map(scale.invert));
4139
- }
4140
-
4141
- try {
4142
- d3_behavior_zoomDispatch.apply(d3_behavior_zoomTarget, d3_behavior_zoomArguments);
4143
- } finally {
4144
- d3.event = o;
4145
- }
4146
-
4147
- o.preventDefault();
4148
- }
4149
- })();
3058
+ })()