d3_rails 0.0.9 → 0.0.10

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