d3_rails 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ })()