d3_rails 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module D3Rails
2
- VERSION = "0.0.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
+ })();