1 (function(){if (!Date.now) Date.now = function() {
5 document.createElement("div").style.setProperty("opacity", 0, "");
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);
13 d3 = {version: "2.4.6"}; // semver
14 var d3_array = d3_arraySlice; // conversion for NodeLists
16 function d3_arrayCopy(pseudoarray) {
17 var i = -1, n = pseudoarray.length, array = [];
18 while (++i < n) array.push(pseudoarray[i]);
22 function d3_arraySlice(pseudoarray) {
23 return Array.prototype.slice.call(pseudoarray);
27 d3_array(document.documentElement.childNodes)[0].nodeType;
29 d3_array = d3_arrayCopy;
32 var d3_arraySubclass = [].__proto__?
34 // Until ECMAScript supports array subclassing, prototype injection works well.
35 function(array, prototype) {
36 array.__proto__ = prototype;
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];
46 d3.functor = function(v) {
47 return typeof v === "function" ? v : function() { return v; };
49 // A getter-setter method that preserves the appropriate `this` context.
50 d3.rebind = function(object, method) {
52 var x = method.apply(object, arguments);
53 return arguments.length ? object : x;
56 d3.ascending = function(a, b) {
57 return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
59 d3.descending = function(a, b) {
60 return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
62 d3.mean = function(array, f) {
68 if (arguments.length === 1) {
69 while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
71 while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
73 return j ? m : undefined;
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;
80 d3.min = function(array, f) {
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;
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;
94 d3.max = function(array, f) {
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;
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;
108 function d3_number(x) {
109 return x != null && !isNaN(x);
111 d3.sum = function(array, f) {
117 if (arguments.length === 1) {
118 while (++i < n) if (!isNaN(a = +array[i])) s += a;
120 while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
125 // R-7 per <http://en.wikipedia.org/wiki/Quantile>
126 d3.quantile = function(values, p) {
127 var H = (values.length - 1) * p + 1,
131 return e ? v + e * (values[h] - v) : v;
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];
143 function d3_zipLength(d) {
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.
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;
160 var mid = (lo + hi) >> 1;
161 if (a[mid] < x) lo = mid + 1;
167 // Similar to bisectLeft, but returns an insertion point which comes after (to
168 // the right of) any existing entries of x in a.
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.
174 d3.bisectRight = function(a, x, lo, hi) {
175 if (arguments.length < 3) lo = 0;
176 if (arguments.length < 4) hi = a.length;
178 var mid = (lo + hi) >> 1;
179 if (x < a[mid]) hi = mid;
184 d3.first = function(array, f) {
189 if (arguments.length === 1) f = d3.ascending;
191 if (f.call(array, a, b = array[i]) > 0) {
197 d3.last = function(array, f) {
202 if (arguments.length === 1) f = d3.ascending;
204 if (f.call(array, a, b = array[i]) <= 0) {
210 d3.nest = function() {
217 function map(array, depth) {
218 if (depth >= keys.length) return rollup
219 ? rollup.call(nest, array) : (sortValues
220 ? array.sort(sortValues)
231 if ((keyValue = key(object = array[i])) in o) {
232 o[keyValue].push(object);
234 o[keyValue] = [object];
238 for (keyValue in o) {
239 o[keyValue] = map(o[keyValue], depth);
245 function entries(map, depth) {
246 if (depth >= keys.length) return map;
249 sortKey = sortKeys[depth++],
253 a.push({key: key, values: entries(map[key], depth)});
256 if (sortKey) a.sort(function(a, b) {
257 return sortKey(a.key, b.key);
263 nest.map = function(array) {
264 return map(array, 0);
267 nest.entries = function(array) {
268 return entries(map(array, 0), 0);
271 nest.key = function(d) {
276 // Specifies the order for the most-recently specified key.
277 // Note: only applies to entries. Map keys are unordered!
278 nest.sortKeys = function(order) {
279 sortKeys[keys.length - 1] = order;
283 // Specifies the order for leaf values.
284 // Applies to both maps and entries array.
285 nest.sortValues = function(order) {
290 nest.rollup = function(f) {
297 d3.keys = function(map) {
299 for (var key in map) keys.push(key);
302 d3.values = function(map) {
304 for (var key in map) values.push(map[key]);
307 d3.entries = function(map) {
309 for (var key in map) entries.push({key: key, value: map[key]});
312 d3.permute = function(array, indexes) {
316 while (++i < n) permutes[i] = array[indexes[i]];
319 d3.merge = function(arrays) {
320 return Array.prototype.concat.apply([], arrays);
322 d3.split = function(array, f) {
328 if (arguments.length < 2) f = d3_splitter;
330 if (f.call(values, value = array[i], i)) {
333 if (!values.length) arrays.push(values);
340 function d3_splitter(d) {
343 function d3_collapse(s) {
344 return s.replace(/(^\s+)|(\s+$)/g, "").replace(/\s+/g, " ");
347 * @param {number} start
348 * @param {number=} stop
349 * @param {number=} step
351 d3.range = function(start, stop, step) {
352 if (arguments.length < 3) {
354 if (arguments.length < 2) {
359 if ((stop - start) / step == Infinity) throw new Error("infinite range");
363 if (step < 0) while ((j = start + step * ++i) > stop) range.push(j);
364 else while ((j = start + step * ++i) < stop) range.push(j);
367 d3.requote = function(s) {
368 return s.replace(d3_requote_re, "\\$&");
371 var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
372 d3.round = function(x, n) {
374 ? Math.round(x * Math.pow(10, n)) * Math.pow(10, -n)
377 d3.xhr = function(url, mime, callback) {
378 var req = new XMLHttpRequest;
379 if (arguments.length < 3) callback = mime;
380 else if (mime && req.overrideMimeType) req.overrideMimeType(mime);
381 req.open("GET", url, true);
382 req.onreadystatechange = function() {
383 if (req.readyState === 4) callback(req.status < 300 ? req : null);
387 d3.text = function(url, mime, callback) {
388 function ready(req) {
389 callback(req && req.responseText);
391 if (arguments.length < 3) {
395 d3.xhr(url, mime, ready);
397 d3.json = function(url, callback) {
398 d3.text(url, "application/json", function(text) {
399 callback(text ? JSON.parse(text) : null);
402 d3.html = function(url, callback) {
403 d3.text(url, "text/html", function(text) {
404 if (text != null) { // Treat empty string as valid HTML.
405 var range = document.createRange();
406 range.selectNode(document.body);
407 text = range.createContextualFragment(text);
412 d3.xml = function(url, mime, callback) {
413 function ready(req) {
414 callback(req && req.responseXML);
416 if (arguments.length < 3) {
420 d3.xhr(url, mime, ready);
425 svg: "http://www.w3.org/2000/svg",
426 xhtml: "http://www.w3.org/1999/xhtml",
427 xlink: "http://www.w3.org/1999/xlink",
428 xml: "http://www.w3.org/XML/1998/namespace",
429 xmlns: "http://www.w3.org/2000/xmlns/"
432 qualify: function(name) {
433 var i = name.indexOf(":");
434 return i < 0 ? name : {
435 space: d3.ns.prefix[name.substring(0, i)],
436 local: name.substring(i + 1)
441 /** @param {...string} types */
442 d3.dispatch = function(types) {
445 for (var i = 0, n = arguments.length; i < n; i++) {
447 dispatch[type] = d3_dispatch(type);
452 function d3_dispatch(type) {
456 dispatch.add = function(listener) {
457 for (var i = 0; i < listeners.length; i++) {
458 if (listeners[i].listener == listener) return dispatch; // already registered
460 listeners.push({listener: listener, on: true});
464 dispatch.remove = function(listener) {
465 for (var i = 0; i < listeners.length; i++) {
466 var l = listeners[i];
467 if (l.listener == listener) {
469 listeners = listeners.slice(0, i).concat(listeners.slice(i + 1));
476 dispatch.dispatch = function() {
477 var ls = listeners; // defensive reference
478 for (var i = 0, n = ls.length; i < n; i++) {
480 if (l.on) l.listener.apply(this, arguments);
487 d3.format = function(specifier) {
488 var match = d3_format_re.exec(specifier),
489 fill = match[1] || " ",
490 sign = match[3] || "",
494 precision = match[8],
500 if (precision) precision = +precision.substring(1);
503 fill = "0"; // TODO align = "=";
504 if (comma) width -= Math.floor((width - 1) / 4);
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;
515 // If no precision is specified for r, fallback to general notation.
516 if (type == "r" && !precision) type = "g";
518 type = d3_format_types[type] || d3_format_typeDefault;
520 return function(value) {
522 // Return the empty string for floats formatted as ints.
523 if (integer && (value % 1)) return "";
525 // Convert negative to positive, and record the sign prefix.
526 var negative = (value < 0) && (value = -value) ? "\u2212" : sign;
528 // Apply the scale, computing it from the value's exponent for si format.
530 var prefix = d3.formatPrefix(value, precision);
531 value *= prefix.scale;
532 suffix = prefix.symbol;
537 // Convert to the desired precision.
538 value = type(value, precision);
540 // If the fill character is 0, the sign and group is applied after the fill.
542 var length = value.length + negative.length;
543 if (length < width) value = new Array(width - length + 1).join(fill) + value;
544 if (comma) value = d3_format_group(value);
545 value = negative + value;
548 // Otherwise (e.g., space-filling), the sign and group is applied before.
550 if (comma) value = d3_format_group(value);
551 value = negative + value;
552 var length = value.length;
553 if (length < width) value = new Array(width - length + 1).join(fill) + value;
556 return value + suffix;
560 // [[fill]align][sign][#][0][width][,][.precision][type]
561 var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
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))); }
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);
574 function d3_format_typeDefault(x) {
578 // Apply comma grouping for thousands.
579 function d3_format_group(value) {
580 var i = value.lastIndexOf("."),
581 f = i >= 0 ? value.substring(i) : (i = value.length, ""),
583 while (i > 0) t.push(value.substring(i -= 3, i + 3));
584 return t.reverse().join(",") + f;
586 var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix);
588 d3.formatPrefix = function(value, precision) {
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));
596 return d3_formatPrefixes[8 + i / 3];
599 function d3_formatPrefix(d, i) {
601 scale: Math.pow(10, (8 - i) * 3),
607 * TERMS OF USE - EASING EQUATIONS
609 * Open source under the BSD License.
611 * Copyright 2001 Robert Penner
612 * All rights reserved.
614 * Redistribution and use in source and binary forms, with or without
615 * modification, are permitted provided that the following conditions are met:
617 * - Redistributions of source code must retain the above copyright notice, this
618 * list of conditions and the following disclaimer.
620 * - Redistributions in binary form must reproduce the above copyright notice,
621 * this list of conditions and the following disclaimer in the documentation
622 * and/or other materials provided with the distribution.
624 * - Neither the name of the author nor the names of contributors may be used to
625 * endorse or promote products derived from this software without specific
626 * prior written permission.
628 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
629 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
630 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
631 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
632 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
633 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
634 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
635 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
636 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
637 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
638 * POSSIBILITY OF SUCH DAMAGE.
641 var d3_ease_quad = d3_ease_poly(2),
642 d3_ease_cubic = d3_ease_poly(3);
645 linear: function() { return d3_ease_linear; },
647 quad: function() { return d3_ease_quad; },
648 cubic: function() { return d3_ease_cubic; },
649 sin: function() { return d3_ease_sin; },
650 exp: function() { return d3_ease_exp; },
651 circle: function() { return d3_ease_circle; },
652 elastic: d3_ease_elastic,
654 bounce: function() { return d3_ease_bounce; }
658 "in": function(f) { return f; },
659 "out": d3_ease_reverse,
660 "in-out": d3_ease_reflect,
661 "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); }
664 d3.ease = function(name) {
665 var i = name.indexOf("-"),
666 t = i >= 0 ? name.substring(0, i) : name,
667 m = i >= 0 ? name.substring(i + 1) : "in";
668 return d3_ease_clamp(d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1))));
671 function d3_ease_clamp(f) {
673 return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
677 function d3_ease_reverse(f) {
683 function d3_ease_reflect(f) {
685 return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
689 function d3_ease_linear(t) {
693 function d3_ease_poly(e) {
695 return Math.pow(t, e);
699 function d3_ease_sin(t) {
700 return 1 - Math.cos(t * Math.PI / 2);
703 function d3_ease_exp(t) {
704 return Math.pow(2, 10 * (t - 1));
707 function d3_ease_circle(t) {
708 return 1 - Math.sqrt(1 - t * t);
711 function d3_ease_elastic(a, p) {
713 if (arguments.length < 2) p = 0.45;
714 if (arguments.length < 1) { a = 1; s = p / 4; }
715 else s = p / (2 * Math.PI) * Math.asin(1 / a);
717 return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * Math.PI / p);
721 function d3_ease_back(s) {
724 return t * t * ((s + 1) * t - s);
728 function d3_ease_bounce(t) {
729 return t < 1 / 2.75 ? 7.5625 * t * t
730 : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
731 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
732 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
735 d3.interpolate = function(a, b) {
736 var i = d3.interpolators.length, f;
737 while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
741 d3.interpolateNumber = function(a, b) {
743 return function(t) { return a + b * t; };
746 d3.interpolateRound = function(a, b) {
748 return function(t) { return Math.round(a + b * t); };
751 d3.interpolateString = function(a, b) {
752 var m, // current match
754 j, // current index (for coallescing)
755 s0 = 0, // start index of current string prefix
756 s1 = 0, // end index of current string prefix
757 s = [], // string constants and placeholders
758 q = [], // number interpolators
762 // Reset our regular expression!
763 d3_interpolate_number.lastIndex = 0;
765 // Find all numbers in b.
766 for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
767 if (m.index) s.push(b.substring(s0, s1 = m.index));
768 q.push({i: s.length, x: m[0]});
770 s0 = d3_interpolate_number.lastIndex;
772 if (s0 < b.length) s.push(b.substring(s0));
774 // Find all numbers in a.
775 for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
777 if (o.x == m[0]) { // The numbers match, so coallesce.
779 if (s[o.i + 1] == null) { // This match is followed by another number.
782 for (j = i + 1; j < n; ++j) q[j].i--;
783 } else { // This match is followed by a string, so coallesce twice.
784 s[o.i - 1] += o.x + s[o.i + 1];
786 for (j = i + 1; j < n; ++j) q[j].i -= 2;
789 if (s[o.i + 1] == null) { // This match is followed by another number.
791 } else { // This match is followed by a string, so coallesce twice.
792 s[o.i] = o.x + s[o.i + 1];
793 s.splice(o.i + 1, 1);
794 for (j = i + 1; j < n; ++j) q[j].i--;
801 o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
805 // Remove any numbers in b not found in a.
808 if (s[o.i + 1] == null) { // This match is followed by another number.
810 } else { // This match is followed by a string, so coallesce twice.
811 s[o.i] = o.x + s[o.i + 1];
812 s.splice(o.i + 1, 1);
817 // Special optimization for only a single match.
818 if (s.length === 1) {
819 return s[0] == null ? q[0].x : function() { return b; };
822 // Otherwise, interpolate each of the numbers and rejoin the string.
824 for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
829 d3.interpolateRgb = function(a, b) {
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));
846 // interpolates HSL space, but outputs RGB string (for compatibility)
847 d3.interpolateHsl = function(a, b) {
857 return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t).toString();
861 d3.interpolateArray = function(a, b) {
866 n0 = Math.min(a.length, b.length),
868 for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));
869 for (; i < na; ++i) c[i] = a[i];
870 for (; i < nb; ++i) c[i] = b[i];
872 for (i = 0; i < n0; ++i) c[i] = x[i](t);
877 d3.interpolateObject = function(a, b) {
883 i[k] = d3_interpolateByName(k)(a[k], b[k]);
894 for (k in i) c[k] = i[k](t);
899 var d3_interpolate_number = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g,
900 d3_interpolate_rgb = {background: 1, fill: 1, stroke: 1};
902 function d3_interpolateByName(n) {
903 return n in d3_interpolate_rgb || /\bcolor\b/.test(n)
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); }
915 function d3_uninterpolateNumber(a, b) {
916 b = b - (a = +a) ? 1 / (b - a) : 0;
917 return function(x) { return (x - a) * b; };
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)); };
924 d3.rgb = function(r, g, b) {
925 return arguments.length === 1
926 ? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b)
927 : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
928 : d3_rgb(~~r, ~~g, ~~b);
931 function d3_rgb(r, g, b) {
932 return new d3_Rgb(r, g, b);
935 function d3_Rgb(r, g, b) {
941 d3_Rgb.prototype.brighter = function(k) {
942 k = Math.pow(0.7, arguments.length ? k : 1);
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;
952 Math.min(255, Math.floor(r / k)),
953 Math.min(255, Math.floor(g / k)),
954 Math.min(255, Math.floor(b / k)));
957 d3_Rgb.prototype.darker = function(k) {
958 k = Math.pow(0.7, arguments.length ? k : 1);
960 Math.floor(k * this.r),
961 Math.floor(k * this.g),
962 Math.floor(k * this.b));
965 d3_Rgb.prototype.hsl = function() {
966 return d3_rgb_hsl(this.r, this.g, this.b);
969 d3_Rgb.prototype.toString = function() {
970 return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
973 function d3_rgb_hex(v) {
975 ? "0" + Math.max(0, v).toString(16)
976 : Math.min(255, v).toString(16);
979 function d3_rgb_parse(format, rgb, hsl) {
980 var r = 0, // red channel; int in [0, 255]
981 g = 0, // green channel; int in [0, 255]
982 b = 0, // blue channel; int in [0, 255]
983 m1, // CSS color specification match
984 m2, // CSS color specification type (e.g., rgb)
987 /* Handle hsl, rgb. */
988 m1 = /([a-z]+)\((.*)\)/i.exec(format);
990 m2 = m1[2].split(",");
994 parseFloat(m2[0]), // degrees
995 parseFloat(m2[1]) / 100, // percentage
996 parseFloat(m2[2]) / 100 // percentage
1001 d3_rgb_parseNumber(m2[0]),
1002 d3_rgb_parseNumber(m2[1]),
1003 d3_rgb_parseNumber(m2[2])
1010 if (name = d3_rgb_names[format]) return rgb(name.r, name.g, name.b);
1012 /* Hexadecimal colors: #rgb and #rrggbb. */
1013 if (format != null && format.charAt(0) === "#") {
1014 if (format.length === 4) {
1015 r = format.charAt(1); r += r;
1016 g = format.charAt(2); g += g;
1017 b = format.charAt(3); b += b;
1018 } else if (format.length === 7) {
1019 r = format.substring(1, 3);
1020 g = format.substring(3, 5);
1021 b = format.substring(5, 7);
1023 r = parseInt(r, 16);
1024 g = parseInt(g, 16);
1025 b = parseInt(b, 16);
1028 return rgb(r, g, b);
1031 function d3_rgb_hsl(r, g, b) {
1032 var min = Math.min(r /= 255, g /= 255, b /= 255),
1033 max = Math.max(r, g, b),
1037 l = (max + min) / 2;
1039 s = l < .5 ? d / (max + min) : d / (2 - max - min);
1040 if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
1041 else if (g == max) h = (b - r) / d + 2;
1042 else h = (r - g) / d + 4;
1047 return d3_hsl(h, s, l);
1050 function d3_rgb_parseNumber(c) { // either integer or percentage
1051 var f = parseFloat(c);
1052 return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
1055 var d3_rgb_names = {
1056 aliceblue: "#f0f8ff",
1057 antiquewhite: "#faebd7",
1059 aquamarine: "#7fffd4",
1064 blanchedalmond: "#ffebcd",
1066 blueviolet: "#8a2be2",
1068 burlywood: "#deb887",
1069 cadetblue: "#5f9ea0",
1070 chartreuse: "#7fff00",
1071 chocolate: "#d2691e",
1073 cornflowerblue: "#6495ed",
1074 cornsilk: "#fff8dc",
1077 darkblue: "#00008b",
1078 darkcyan: "#008b8b",
1079 darkgoldenrod: "#b8860b",
1080 darkgray: "#a9a9a9",
1081 darkgreen: "#006400",
1082 darkgrey: "#a9a9a9",
1083 darkkhaki: "#bdb76b",
1084 darkmagenta: "#8b008b",
1085 darkolivegreen: "#556b2f",
1086 darkorange: "#ff8c00",
1087 darkorchid: "#9932cc",
1089 darksalmon: "#e9967a",
1090 darkseagreen: "#8fbc8f",
1091 darkslateblue: "#483d8b",
1092 darkslategray: "#2f4f4f",
1093 darkslategrey: "#2f4f4f",
1094 darkturquoise: "#00ced1",
1095 darkviolet: "#9400d3",
1096 deeppink: "#ff1493",
1097 deepskyblue: "#00bfff",
1100 dodgerblue: "#1e90ff",
1101 firebrick: "#b22222",
1102 floralwhite: "#fffaf0",
1103 forestgreen: "#228b22",
1105 gainsboro: "#dcdcdc",
1106 ghostwhite: "#f8f8ff",
1108 goldenrod: "#daa520",
1111 greenyellow: "#adff2f",
1113 honeydew: "#f0fff0",
1115 indianred: "#cd5c5c",
1119 lavender: "#e6e6fa",
1120 lavenderblush: "#fff0f5",
1121 lawngreen: "#7cfc00",
1122 lemonchiffon: "#fffacd",
1123 lightblue: "#add8e6",
1124 lightcoral: "#f08080",
1125 lightcyan: "#e0ffff",
1126 lightgoldenrodyellow: "#fafad2",
1127 lightgray: "#d3d3d3",
1128 lightgreen: "#90ee90",
1129 lightgrey: "#d3d3d3",
1130 lightpink: "#ffb6c1",
1131 lightsalmon: "#ffa07a",
1132 lightseagreen: "#20b2aa",
1133 lightskyblue: "#87cefa",
1134 lightslategray: "#778899",
1135 lightslategrey: "#778899",
1136 lightsteelblue: "#b0c4de",
1137 lightyellow: "#ffffe0",
1139 limegreen: "#32cd32",
1143 mediumaquamarine: "#66cdaa",
1144 mediumblue: "#0000cd",
1145 mediumorchid: "#ba55d3",
1146 mediumpurple: "#9370db",
1147 mediumseagreen: "#3cb371",
1148 mediumslateblue: "#7b68ee",
1149 mediumspringgreen: "#00fa9a",
1150 mediumturquoise: "#48d1cc",
1151 mediumvioletred: "#c71585",
1152 midnightblue: "#191970",
1153 mintcream: "#f5fffa",
1154 mistyrose: "#ffe4e1",
1155 moccasin: "#ffe4b5",
1156 navajowhite: "#ffdead",
1160 olivedrab: "#6b8e23",
1162 orangered: "#ff4500",
1164 palegoldenrod: "#eee8aa",
1165 palegreen: "#98fb98",
1166 paleturquoise: "#afeeee",
1167 palevioletred: "#db7093",
1168 papayawhip: "#ffefd5",
1169 peachpuff: "#ffdab9",
1173 powderblue: "#b0e0e6",
1176 rosybrown: "#bc8f8f",
1177 royalblue: "#4169e1",
1178 saddlebrown: "#8b4513",
1180 sandybrown: "#f4a460",
1181 seagreen: "#2e8b57",
1182 seashell: "#fff5ee",
1186 slateblue: "#6a5acd",
1187 slategray: "#708090",
1188 slategrey: "#708090",
1190 springgreen: "#00ff7f",
1191 steelblue: "#4682b4",
1196 turquoise: "#40e0d0",
1200 whitesmoke: "#f5f5f5",
1202 yellowgreen: "#9acd32"
1205 for (var d3_rgb_name in d3_rgb_names) {
1206 d3_rgb_names[d3_rgb_name] = d3_rgb_parse(
1207 d3_rgb_names[d3_rgb_name],
1211 d3.hsl = function(h, s, l) {
1212 return arguments.length === 1
1213 ? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l)
1214 : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
1215 : d3_hsl(+h, +s, +l);
1218 function d3_hsl(h, s, l) {
1219 return new d3_Hsl(h, s, l);
1222 function d3_Hsl(h, s, l) {
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);
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);
1238 d3_Hsl.prototype.rgb = function() {
1239 return d3_hsl_rgb(this.h, this.s, this.l);
1242 d3_Hsl.prototype.toString = function() {
1243 return this.rgb().toString();
1246 function d3_hsl_rgb(h, s, l) {
1250 /* Some simple corrections for h, s and l. */
1251 h = h % 360; if (h < 0) h += 360;
1252 s = s < 0 ? 0 : s > 1 ? 1 : s;
1253 l = l < 0 ? 0 : l > 1 ? 1 : l;
1255 /* From FvD 13.37, CSS Color Module Level 3 */
1256 m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
1260 if (h > 360) h -= 360;
1261 else if (h < 0) h += 360;
1262 if (h < 60) return m1 + (m2 - m1) * h / 60;
1263 if (h < 180) return m2;
1264 if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
1269 return Math.round(v(h) * 255);
1272 return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
1274 function d3_selection(groups) {
1275 d3_arraySubclass(groups, d3_selectionPrototype);
1279 var d3_select = function(s, n) { return n.querySelector(s); },
1280 d3_selectAll = function(s, n) { return n.querySelectorAll(s); };
1282 // Prefer Sizzle, if available.
1283 if (typeof Sizzle === "function") {
1284 d3_select = function(s, n) { return Sizzle(s, n)[0]; };
1285 d3_selectAll = function(s, n) { return Sizzle.uniqueSort(Sizzle(s, n)); };
1288 var d3_selectionPrototype = [];
1290 d3.selection = function() {
1291 return d3_selectionRoot;
1294 d3.selection.prototype = d3_selectionPrototype;
1295 d3_selectionPrototype.select = function(selector) {
1302 if (typeof selector !== "function") selector = d3_selection_selector(selector);
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__;
1312 subgroup.push(null);
1317 return d3_selection(subgroups);
1320 function d3_selection_selector(selector) {
1322 return d3_select(selector, this);
1325 d3_selectionPrototype.selectAll = function(selector) {
1330 if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
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;
1341 return d3_selection(subgroups);
1344 function d3_selection_selectorAll(selector) {
1346 return d3_selectAll(selector, this);
1349 d3_selectionPrototype.attr = function(name, value) {
1350 name = d3.ns.qualify(name);
1352 // If no value is specified, return the first value.
1353 if (arguments.length < 2) {
1354 var node = this.node();
1356 ? node.getAttributeNS(name.space, name.local)
1357 : node.getAttribute(name);
1360 function attrNull() {
1361 this.removeAttribute(name);
1364 function attrNullNS() {
1365 this.removeAttributeNS(name.space, name.local);
1368 function attrConstant() {
1369 this.setAttribute(name, value);
1372 function attrConstantNS() {
1373 this.setAttributeNS(name.space, name.local, value);
1376 function attrFunction() {
1377 var x = value.apply(this, arguments);
1378 if (x == null) this.removeAttribute(name);
1379 else this.setAttribute(name, x);
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);
1388 return this.each(value == null
1389 ? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
1390 ? (name.local ? attrFunctionNS : attrFunction)
1391 : (name.local ? attrConstantNS : attrConstant)));
1393 d3_selectionPrototype.classed = function(name, value) {
1394 var names = name.split(d3_selection_classedWhitespace),
1397 if (arguments.length > 1) {
1398 while (++i < n) d3_selection_classed.call(this, names[i], value);
1401 while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false;
1406 var d3_selection_classedWhitespace = /\s+/g;
1408 function d3_selection_classed(name, value) {
1409 var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
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;
1417 return re.test(c.baseVal != null ? c.baseVal : c);
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;
1427 cv = d3_collapse(cv + " " + name);
1428 if (cb) c.baseVal = cv;
1429 else this.className = cv;
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;
1443 function classedFunction() {
1444 (value.apply(this, arguments)
1446 : classedRemove).call(this);
1449 return this.each(typeof value === "function"
1450 ? classedFunction : value
1454 d3_selectionPrototype.style = function(name, value, priority) {
1455 if (arguments.length < 3) priority = "";
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);
1462 function styleNull() {
1463 this.style.removeProperty(name);
1466 function styleConstant() {
1467 this.style.setProperty(name, value, priority);
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);
1476 return this.each(value == null
1477 ? styleNull : (typeof value === "function"
1478 ? styleFunction : styleConstant));
1480 d3_selectionPrototype.property = function(name, value) {
1482 // If no value is specified, return the first value.
1483 if (arguments.length < 2) return this.node()[name];
1485 function propertyNull() {
1489 function propertyConstant() {
1493 function propertyFunction() {
1494 var x = value.apply(this, arguments);
1495 if (x == null) delete this[name];
1496 else this[name] = x;
1499 return this.each(value == null
1500 ? propertyNull : (typeof value === "function"
1501 ? propertyFunction : propertyConstant));
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; }));
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; }));
1515 // TODO append(node)?
1516 // TODO append(function)?
1517 d3_selectionPrototype.append = function(name) {
1518 name = d3.ns.qualify(name);
1521 return this.appendChild(document.createElement(name));
1524 function appendNS() {
1525 return this.appendChild(document.createElementNS(name.space, name.local));
1528 return this.select(name.local ? appendNS : append);
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);
1537 return this.insertBefore(
1538 document.createElement(name),
1539 d3_select(before, this));
1542 function insertNS() {
1543 return this.insertBefore(
1544 document.createElementNS(name.space, name.local),
1545 d3_select(before, this));
1548 return this.select(name.local ? insertNS : insert);
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);
1559 // TODO data(null) for clearing data?
1560 d3_selectionPrototype.data = function(data, join) {
1565 function bind(group, groupData) {
1568 m = groupData.length,
1569 n0 = Math.min(n, m),
1570 n1 = Math.max(n, m),
1581 j = groupData.length;
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
1588 nodeByKey[key] = node;
1593 for (i = -1; ++i < m;) {
1594 node = nodeByKey[key = join.call(groupData, nodeData = groupData[i], i)];
1596 node.__data__ = nodeData;
1597 updateNodes[i] = node;
1598 enterNodes[i] = exitNodes[i] = null;
1600 enterNodes[i] = d3_selection_dataNode(nodeData);
1601 updateNodes[i] = exitNodes[i] = null;
1603 delete nodeByKey[key];
1606 for (i = -1; ++i < n;) {
1607 if (keys[i] in nodeByKey) {
1608 exitNodes[i] = group[i];
1612 for (i = -1; ++i < n0;) {
1614 nodeData = groupData[i];
1616 node.__data__ = nodeData;
1617 updateNodes[i] = node;
1618 enterNodes[i] = exitNodes[i] = null;
1620 enterNodes[i] = d3_selection_dataNode(nodeData);
1621 updateNodes[i] = exitNodes[i] = null;
1624 for (; i < m; ++i) {
1625 enterNodes[i] = d3_selection_dataNode(groupData[i]);
1626 updateNodes[i] = exitNodes[i] = null;
1628 for (; i < n1; ++i) {
1629 exitNodes[i] = group[i];
1630 enterNodes[i] = updateNodes[i] = null;
1637 enterNodes.parentNode
1638 = updateNodes.parentNode
1639 = exitNodes.parentNode
1642 enter.push(enterNodes);
1643 update.push(updateNodes);
1644 exit.push(exitNodes);
1650 if (typeof data === "function") {
1652 bind(group = this[i], data.call(group, group.parentNode.__data__, i));
1656 bind(group = this[i], data);
1660 var selection = d3_selection(update);
1661 selection.enter = function() { return d3_selection_enter(enter); };
1662 selection.exit = function() { return d3_selection(exit); };
1666 function d3_selection_dataNode(data) {
1667 return {__data__: data};
1669 // TODO preserve null elements to maintain index?
1670 d3_selectionPrototype.filter = function(filter) {
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);
1686 return d3_selection(subgroups);
1688 d3_selectionPrototype.map = function(map) {
1689 return this.each(function() {
1690 this.__data__ = map.apply(this, arguments);
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];
1699 if (prev) prev.parentNode.insertBefore(node, prev.nextSibling);
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__);
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;
1718 // parse the type specifier
1719 var name = "__on" + type, i = type.indexOf(".");
1720 if (i > 0) type = type.substring(0, i);
1722 // if called with only one argument, return the current listener
1723 if (arguments.length < 2) return (i = this.node()[name]) && i._;
1725 // remove the old event listener, and add the new event listener
1726 return this.each(function(d, i) {
1729 if (node[name]) node.removeEventListener(type, node[name], capture);
1730 if (listener) node.addEventListener(type, node[name] = l, capture);
1732 // wrapped event listener that preserves i
1734 var o = d3.event; // Events can be reentrant (e.g., focus).
1737 listener.call(node, node.__data__, i);
1743 // stash the unwrapped listener for retrieval
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);
1757 // Note: assigning to the arguments array simultaneously changes the value of
1758 // the corresponding argument!
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
1765 d3_selectionPrototype.call = function(callback) {
1766 callback.apply(this, (arguments[0] = this, arguments));
1769 d3_selectionPrototype.empty = function() {
1770 return !this.node();
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;
1781 d3_selectionPrototype.transition = function() {
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);
1793 return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId, Date.now());
1795 var d3_selectionRoot = d3_selection([[document]]);
1797 d3_selectionRoot[0].parentNode = document.documentElement;
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
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[]
1813 function d3_selection_enter(selection) {
1814 d3_arraySubclass(selection, d3_selection_enterPrototype);
1818 var d3_selection_enterPrototype = [];
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) {
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__;
1841 subgroup.push(null);
1846 return d3_selection(subgroups);
1848 function d3_transition(groups, id, time) {
1849 d3_arraySubclass(groups, d3_transitionPrototype);
1852 event = d3.dispatch("start", "end"),
1853 ease = d3_transitionEase;
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;
1866 groups.ease = function(value) {
1867 if (!arguments.length) return ease;
1868 ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments);
1872 groups.each = function(type, listener) {
1873 if (arguments.length < 2) return d3_transition_each.call(groups, type);
1874 event[type].add(listener);
1878 d3.timer(function(elapsed) {
1879 groups.each(function(d, i, j) {
1882 delay = groups[j][i].delay,
1883 duration = groups[j][i].duration,
1884 lock = node.__transition__ || (node.__transition__ = {active: 0, count: 0});
1888 delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time);
1890 function start(elapsed) {
1891 if (lock.active > id) return stop();
1894 for (var tween in tweens) {
1895 if (tween = tweens[tween].call(node, d, i)) {
1896 tweened.push(tween);
1900 event.start.dispatch.call(node, d, i);
1901 if (!tick(elapsed)) d3.timer(tick, 0, time);
1905 function tick(elapsed) {
1906 if (lock.active !== id) return stop();
1908 var t = (elapsed - delay) / duration,
1913 tweened[--n].call(node, e);
1918 d3_transitionInheritId = id;
1919 event.end.dispatch.call(node, d, i);
1920 d3_transitionInheritId = 0;
1926 if (!--lock.count) delete node.__transition__;
1936 var d3_transitionRemove = {};
1938 function d3_transitionNull(d, i, a) {
1939 return a != "" && d3_transitionRemove;
1942 function d3_transitionTween(b) {
1944 function transitionFunction(d, i, a) {
1945 var v = b.call(this, d, i);
1947 ? a != "" && d3_transitionRemove
1948 : a != v && d3.interpolate(a, v);
1951 function transitionString(d, i, a) {
1952 return a != b && d3.interpolate(a, b);
1955 return typeof b === "function" ? transitionFunction
1956 : b == null ? d3_transitionNull
1957 : (b += "", transitionString);
1960 var d3_transitionPrototype = [],
1961 d3_transitionId = 0,
1962 d3_transitionInheritId = 0,
1963 d3_transitionEase = d3.ease("cubic-in-out");
1965 d3_transitionPrototype.call = d3_selectionPrototype.call;
1967 d3.transition = function() {
1968 return d3_selectionRoot.transition();
1971 d3.transition.prototype = d3_transitionPrototype;
1972 d3_transitionPrototype.select = function(selector) {
1978 if (typeof selector !== "function") selector = d3_selection_selector(selector);
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});
1987 subgroup.push(null);
1992 return d3_transition(subgroups, this.id, this.time).ease(this.ease());
1994 d3_transitionPrototype.selectAll = function(selector) {
2000 if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
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});
2014 return d3_transition(subgroups, this.id, this.time).ease(this.ease());
2016 d3_transitionPrototype.attr = function(name, value) {
2017 return this.attrTween(name, d3_transitionTween(value));
2020 d3_transitionPrototype.attrTween = function(nameNS, tween) {
2021 var name = d3.ns.qualify(nameNS);
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)); };
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)); };
2037 return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
2039 d3_transitionPrototype.style = function(name, value, priority) {
2040 if (arguments.length < 3) priority = "";
2041 return this.styleTween(name, d3_transitionTween(value), priority);
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); };
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)
2060 d3_transitionPrototype.remove = function() {
2061 return this.each("end", function() {
2063 if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
2066 d3_transitionPrototype.delay = function(value) {
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; }));
2072 d3_transitionPrototype.duration = function(value) {
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; }));
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);
2087 d3_transitionPrototype.transition = function() {
2088 return this.select(d3_this);
2090 var d3_timer_queue = null,
2091 d3_timer_interval, // is an interval (or frame) active?
2092 d3_timer_timeout; // is a timeout active?
2094 // The timer will continue to fire until callback returns true.
2095 d3.timer = function(callback, delay, then) {
2098 t1 = d3_timer_queue;
2100 if (arguments.length < 3) {
2101 if (arguments.length < 2) delay = 0;
2102 else if (!isFinite(delay)) return;
2106 // See if the callback's already in the queue.
2108 if (t1.callback === callback) {
2118 // Otherwise, add the callback to the queue.
2119 if (!found) d3_timer_queue = {
2123 next: d3_timer_queue
2127 if (!d3_timer_interval) {
2128 d3_timer_timeout = clearTimeout(d3_timer_timeout);
2129 d3_timer_interval = 1;
2130 d3_timer_frame(d3_timer_step);
2134 function d3_timer_step() {
2137 t1 = d3_timer_queue;
2140 elapsed = now - t1.then;
2141 if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
2145 var delay = d3_timer_flush() - now;
2147 if (isFinite(delay)) {
2148 clearTimeout(d3_timer_timeout);
2149 d3_timer_timeout = setTimeout(d3_timer_step, delay);
2151 d3_timer_interval = 0;
2153 d3_timer_interval = 1;
2154 d3_timer_frame(d3_timer_step);
2158 d3.timer.flush = function() {
2161 t1 = d3_timer_queue;
2164 elapsed = now - t1.then;
2165 if (!t1.delay) t1.flush = t1.callback(elapsed);
2172 // Flush after callbacks, to avoid concurrent queue modification.
2173 function d3_timer_flush() {
2175 t1 = d3_timer_queue,
2179 t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
2181 then = Math.min(then, t1.then + t1.delay);
2182 t1 = (t0 = t1).next;
2188 var d3_timer_frame = window.requestAnimationFrame
2189 || window.webkitRequestAnimationFrame
2190 || window.mozRequestAnimationFrame
2191 || window.oRequestAnimationFrame
2192 || window.msRequestAnimationFrame
2193 || function(callback) { setTimeout(callback, 17); };
2194 function d3_noop() {}
2197 function d3_scaleExtent(domain) {
2198 var start = domain[0], stop = domain[domain.length - 1];
2199 return start < stop ? [start, stop] : [stop, start];
2201 function d3_scale_nice(domain, nice) {
2203 i1 = domain.length - 1,
2209 dx = i0; i0 = i1; i1 = dx;
2210 dx = x0; x0 = x1; x1 = dx;
2215 domain[i0] = nice.floor(x0);
2216 domain[i1] = nice.ceil(x1);
2222 function d3_scale_niceDefault() {
2225 d3.scale.linear = function() {
2226 return d3_scale_linear([0, 1], [0, 1], d3.interpolate, false);
2229 function d3_scale_linear(domain, range, interpolate, clamp) {
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);
2245 // Note: requires range is coercible to number!
2246 scale.invert = function(y) {
2250 scale.domain = function(x) {
2251 if (!arguments.length) return domain;
2252 domain = x.map(Number);
2256 scale.range = function(x) {
2257 if (!arguments.length) return range;
2262 scale.rangeRound = function(x) {
2263 return scale.range(x).interpolate(d3.interpolateRound);
2266 scale.clamp = function(x) {
2267 if (!arguments.length) return clamp;
2272 scale.interpolate = function(x) {
2273 if (!arguments.length) return interpolate;
2278 scale.ticks = function(m) {
2279 return d3_scale_linearTicks(domain, m);
2282 scale.tickFormat = function(m) {
2283 return d3_scale_linearTickFormat(domain, m);
2286 scale.nice = function() {
2287 d3_scale_nice(domain, d3_scale_linearNice);
2291 scale.copy = function() {
2292 return d3_scale_linear(domain, range, interpolate, clamp);
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);
2306 function d3_scale_linearNice(dx) {
2307 dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
2309 floor: function(x) { return Math.floor(x / dx) * dx; },
2310 ceil: function(x) { return Math.ceil(x / dx) * dx; }
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;
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;
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
2333 function d3_scale_linearTicks(domain, m) {
2334 return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
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");
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) {
2347 function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
2354 u.push(uninterpolate(domain[j - 1], domain[j]));
2355 i.push(interpolate(range[j - 1], range[j]));
2358 return function(x) {
2359 var j = d3.bisect(domain, x, 1, domain.length - 1) - 1;
2360 return i[j](u[j](x));
2363 d3.scale.log = function() {
2364 return d3_scale_log(d3.scale.linear(), d3_scale_logp);
2367 function d3_scale_log(linear, log) {
2371 return linear(log(x));
2374 scale.invert = function(x) {
2375 return pow(linear.invert(x));
2378 scale.domain = function(x) {
2379 if (!arguments.length) return linear.domain().map(pow);
2380 log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;
2382 linear.domain(x.map(log));
2386 scale.nice = function() {
2387 linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
2391 scale.ticks = function() {
2392 var extent = d3_scaleExtent(linear.domain()),
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]));
2399 if (log === d3_scale_logn) {
2401 for (; i++ < j;) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
2403 for (; i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);
2406 for (i = 0; ticks[i] < u; i++) {} // strip small values
2407 for (j = ticks.length; ticks[j - 1] > v; j--) {} // strip big values
2408 ticks = ticks.slice(i, j);
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),
2419 return function(d) {
2420 return d / pow(f(log(d) + e)) < k ? format(d) : "";
2424 scale.copy = function() {
2425 return d3_scale_log(linear.copy(), log);
2428 return d3_scale_linearRebind(scale, linear);
2431 var d3_scale_logFormat = d3.format("e");
2433 function d3_scale_logp(x) {
2434 return Math.log(x) / Math.LN10;
2437 function d3_scale_logn(x) {
2438 return -Math.log(-x) / Math.LN10;
2441 d3_scale_logp.pow = function(x) {
2442 return Math.pow(10, x);
2445 d3_scale_logn.pow = function(x) {
2446 return -Math.pow(10, -x);
2448 d3.scale.pow = function() {
2449 return d3_scale_pow(d3.scale.linear(), 1);
2452 function d3_scale_pow(linear, exponent) {
2453 var powp = d3_scale_powPow(exponent),
2454 powb = d3_scale_powPow(1 / exponent);
2457 return linear(powp(x));
2460 scale.invert = function(x) {
2461 return powb(linear.invert(x));
2464 scale.domain = function(x) {
2465 if (!arguments.length) return linear.domain().map(powb);
2466 linear.domain(x.map(powp));
2470 scale.ticks = function(m) {
2471 return d3_scale_linearTicks(scale.domain(), m);
2474 scale.tickFormat = function(m) {
2475 return d3_scale_linearTickFormat(scale.domain(), m);
2478 scale.nice = function() {
2479 return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
2482 scale.exponent = function(x) {
2483 if (!arguments.length) return exponent;
2484 var domain = scale.domain();
2485 powp = d3_scale_powPow(exponent = x);
2486 powb = d3_scale_powPow(1 / exponent);
2487 return scale.domain(domain);
2490 scale.copy = function() {
2491 return d3_scale_pow(linear.copy(), exponent);
2494 return d3_scale_linearRebind(scale, linear);
2497 function d3_scale_powPow(e) {
2498 return function(x) {
2499 return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
2502 d3.scale.sqrt = function() {
2503 return d3.scale.pow().exponent(.5);
2505 d3.scale.ordinal = function() {
2506 return d3_scale_ordinal([], {t: "range", x: []});
2509 function d3_scale_ordinal(domain, ranger) {
2515 return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length];
2518 scale.domain = function(x) {
2519 if (!arguments.length) return domain;
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);
2527 scale.range = function(x) {
2528 if (!arguments.length) return range;
2531 ranger = {t: "range", x: x};
2535 scale.rangePoints = function(x, padding) {
2536 if (arguments.length < 2) padding = 0;
2539 step = (stop - start) / (domain.length - 1 + padding);
2540 range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step);
2542 ranger = {t: "rangePoints", x: x, p: padding};
2546 scale.rangeBands = function(x, padding) {
2547 if (arguments.length < 2) padding = 0;
2550 step = (stop - start) / (domain.length + padding);
2551 range = d3.range(start + step * padding, stop, step);
2552 rangeBand = step * (1 - padding);
2553 ranger = {t: "rangeBands", x: x, p: padding};
2557 scale.rangeRoundBands = function(x, padding) {
2558 if (arguments.length < 2) padding = 0;
2561 step = Math.floor((stop - start) / (domain.length + padding)),
2562 err = stop - start - (domain.length - padding) * step;
2563 range = d3.range(start + Math.round(err / 2), stop, step);
2564 rangeBand = Math.round(step * (1 - padding));
2565 ranger = {t: "rangeRoundBands", x: x, p: padding};
2569 scale.rangeBand = function() {
2573 scale.copy = function() {
2574 return d3_scale_ordinal(domain, ranger);
2577 return scale.domain(domain);
2580 * This product includes color specifications and designs developed by Cynthia
2581 * Brewer (http://colorbrewer.org/). See lib/colorbrewer for more information.
2584 d3.scale.category10 = function() {
2585 return d3.scale.ordinal().range(d3_category10);
2588 d3.scale.category20 = function() {
2589 return d3.scale.ordinal().range(d3_category20);
2592 d3.scale.category20b = function() {
2593 return d3.scale.ordinal().range(d3_category20b);
2596 d3.scale.category20c = function() {
2597 return d3.scale.ordinal().range(d3_category20c);
2600 var d3_category10 = [
2601 "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
2602 "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"
2605 var d3_category20 = [
2606 "#1f77b4", "#aec7e8",
2607 "#ff7f0e", "#ffbb78",
2608 "#2ca02c", "#98df8a",
2609 "#d62728", "#ff9896",
2610 "#9467bd", "#c5b0d5",
2611 "#8c564b", "#c49c94",
2612 "#e377c2", "#f7b6d2",
2613 "#7f7f7f", "#c7c7c7",
2614 "#bcbd22", "#dbdb8d",
2615 "#17becf", "#9edae5"
2618 var d3_category20b = [
2619 "#393b79", "#5254a3", "#6b6ecf", "#9c9ede",
2620 "#637939", "#8ca252", "#b5cf6b", "#cedb9c",
2621 "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94",
2622 "#843c39", "#ad494a", "#d6616b", "#e7969c",
2623 "#7b4173", "#a55194", "#ce6dbd", "#de9ed6"
2626 var d3_category20c = [
2627 "#3182bd", "#6baed6", "#9ecae1", "#c6dbef",
2628 "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2",
2629 "#31a354", "#74c476", "#a1d99b", "#c7e9c0",
2630 "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb",
2631 "#636363", "#969696", "#bdbdbd", "#d9d9d9"
2633 d3.scale.quantile = function() {
2634 return d3_scale_quantile([], []);
2637 function d3_scale_quantile(domain, range) {
2640 function rescale() {
2645 while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
2650 if (isNaN(x = +x)) return NaN;
2651 return range[d3.bisect(thresholds, x)];
2654 scale.domain = function(x) {
2655 if (!arguments.length) return domain;
2656 domain = x.filter(function(d) { return !isNaN(d); }).sort(d3.ascending);
2660 scale.range = function(x) {
2661 if (!arguments.length) return range;
2666 scale.quantiles = function() {
2670 scale.copy = function() {
2671 return d3_scale_quantile(domain, range); // copy on write!
2676 d3.scale.quantize = function() {
2677 return d3_scale_quantize(0, 1, [0, 1]);
2680 function d3_scale_quantize(x0, x1, range) {
2684 return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
2687 function rescale() {
2688 kx = range.length / (x1 - x0);
2689 i = range.length - 1;
2693 scale.domain = function(x) {
2694 if (!arguments.length) return [x0, x1];
2696 x1 = +x[x.length - 1];
2700 scale.range = function(x) {
2701 if (!arguments.length) return range;
2706 scale.copy = function() {
2707 return d3_scale_quantize(x0, x1, range); // copy on write
2713 d3.svg.arc = function() {
2714 var innerRadius = d3_svg_arcInnerRadius,
2715 outerRadius = d3_svg_arcOuterRadius,
2716 startAngle = d3_svg_arcStartAngle,
2717 endAngle = d3_svg_arcEndAngle;
2720 var r0 = innerRadius.apply(this, arguments),
2721 r1 = outerRadius.apply(this, arguments),
2722 a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset,
2723 a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset,
2724 da = (a1 < a0 && (da = a0, a0 = a1, a1 = da), a1 - a0),
2725 df = da < Math.PI ? "0" : "1",
2730 return da >= d3_svg_arcMax
2733 + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
2734 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
2736 + "A" + r0 + "," + r0 + " 0 1,0 0," + (-r0)
2737 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0
2740 + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
2741 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
2744 ? "M" + r1 * c0 + "," + r1 * s0
2745 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1
2746 + "L" + r0 * c1 + "," + r0 * s1
2747 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0
2749 : "M" + r1 * c0 + "," + r1 * s0
2750 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1
2755 arc.innerRadius = function(v) {
2756 if (!arguments.length) return innerRadius;
2757 innerRadius = d3.functor(v);
2761 arc.outerRadius = function(v) {
2762 if (!arguments.length) return outerRadius;
2763 outerRadius = d3.functor(v);
2767 arc.startAngle = function(v) {
2768 if (!arguments.length) return startAngle;
2769 startAngle = d3.functor(v);
2773 arc.endAngle = function(v) {
2774 if (!arguments.length) return endAngle;
2775 endAngle = d3.functor(v);
2779 arc.centroid = function() {
2780 var r = (innerRadius.apply(this, arguments)
2781 + outerRadius.apply(this, arguments)) / 2,
2782 a = (startAngle.apply(this, arguments)
2783 + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
2784 return [Math.cos(a) * r, Math.sin(a) * r];
2790 var d3_svg_arcOffset = -Math.PI / 2,
2791 d3_svg_arcMax = 2 * Math.PI - 1e-6;
2793 function d3_svg_arcInnerRadius(d) {
2794 return d.innerRadius;
2797 function d3_svg_arcOuterRadius(d) {
2798 return d.outerRadius;
2801 function d3_svg_arcStartAngle(d) {
2802 return d.startAngle;
2805 function d3_svg_arcEndAngle(d) {
2808 function d3_svg_line(projection) {
2809 var x = d3_svg_lineX,
2811 interpolate = "linear",
2812 interpolator = d3_svg_lineInterpolators[interpolate],
2816 return d.length < 1 ? null : "M" + interpolator(projection(d3_svg_linePoints(this, d, x, y)), tension);
2819 line.x = function(v) {
2820 if (!arguments.length) return x;
2825 line.y = function(v) {
2826 if (!arguments.length) return y;
2831 line.interpolate = function(v) {
2832 if (!arguments.length) return interpolate;
2833 interpolator = d3_svg_lineInterpolators[interpolate = v];
2837 line.tension = function(v) {
2838 if (!arguments.length) return tension;
2846 d3.svg.line = function() {
2847 return d3_svg_line(Object);
2850 // Converts the specified array of data into an array of points
2851 // (x-y tuples), by evaluating the specified `x` and `y` functions on each
2852 // data point. The `this` context of the evaluated functions is the specified
2853 // "self" object; each function is passed the current datum and index.
2854 function d3_svg_linePoints(self, d, x, y) {
2858 fx = typeof x === "function",
2859 fy = typeof y === "function",
2862 while (++i < n) points.push([
2863 x.call(self, value = d[i], i),
2864 y.call(self, value, i)
2867 while (++i < n) points.push([x.call(self, d[i], i), y]);
2869 while (++i < n) points.push([x, y.call(self, d[i], i)]);
2871 while (++i < n) points.push([x, y]);
2876 // The default `x` property, which references d[0].
2877 function d3_svg_lineX(d) {
2881 // The default `y` property, which references d[1].
2882 function d3_svg_lineY(d) {
2886 // The various interpolators supported by the `line` class.
2887 var d3_svg_lineInterpolators = {
2888 "linear": d3_svg_lineLinear,
2889 "step-before": d3_svg_lineStepBefore,
2890 "step-after": d3_svg_lineStepAfter,
2891 "basis": d3_svg_lineBasis,
2892 "basis-open": d3_svg_lineBasisOpen,
2893 "basis-closed": d3_svg_lineBasisClosed,
2894 "bundle": d3_svg_lineBundle,
2895 "cardinal": d3_svg_lineCardinal,
2896 "cardinal-open": d3_svg_lineCardinalOpen,
2897 "cardinal-closed": d3_svg_lineCardinalClosed,
2898 "monotone": d3_svg_lineMonotone
2901 // Linear interpolation; generates "L" commands.
2902 function d3_svg_lineLinear(points) {
2906 path = [p[0], ",", p[1]];
2907 while (++i < n) path.push("L", (p = points[i])[0], ",", p[1]);
2908 return path.join("");
2911 // Step interpolation; generates "H" and "V" commands.
2912 function d3_svg_lineStepBefore(points) {
2916 path = [p[0], ",", p[1]];
2917 while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
2918 return path.join("");
2921 // Step interpolation; generates "H" and "V" commands.
2922 function d3_svg_lineStepAfter(points) {
2926 path = [p[0], ",", p[1]];
2927 while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
2928 return path.join("");
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));
2939 // Closed cardinal spline interpolation; generates "C" commands.
2940 function d3_svg_lineCardinalClosed(points, tension) {
2941 return points.length < 3
2942 ? d3_svg_lineLinear(points)
2943 : points[0] + d3_svg_lineHermite((points.push(points[0]), points),
2944 d3_svg_lineCardinalTangents([points[points.length - 2]]
2945 .concat(points, [points[1]]), tension));
2948 // Cardinal spline interpolation; generates "C" commands.
2949 function d3_svg_lineCardinal(points, tension, closed) {
2950 return points.length < 3
2951 ? d3_svg_lineLinear(points)
2952 : points[0] + d3_svg_lineHermite(points,
2953 d3_svg_lineCardinalTangents(points, tension));
2956 // Hermite spline construction; generates "C" commands.
2957 function d3_svg_lineHermite(points, tangents) {
2958 if (tangents.length < 1
2959 || (points.length != tangents.length
2960 && points.length != tangents.length + 2)) {
2961 return d3_svg_lineLinear(points);
2964 var quad = points.length != tangents.length,
2973 path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3)
2974 + "," + p[0] + "," + p[1];
2979 if (tangents.length > 1) {
2983 path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1])
2984 + "," + (p[0] - t[0]) + "," + (p[1] - t[1])
2985 + "," + p[0] + "," + p[1];
2986 for (var i = 2; i < tangents.length; i++, pi++) {
2989 path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1])
2990 + "," + p[0] + "," + p[1];
2995 var lp = points[pi];
2996 path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3)
2997 + "," + lp[0] + "," + lp[1];
3003 // Generates tangents for a cardinal spline.
3004 function d3_svg_lineCardinalTangents(points, tension) {
3006 a = (1 - tension) / 2,
3016 tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
3021 // B-spline interpolation; generates "C" commands.
3022 function d3_svg_lineBasis(points) {
3023 if (points.length < 3) return d3_svg_lineLinear(points);
3029 px = [x0, x0, x0, (pi = points[1])[0]],
3030 py = [y0, y0, y0, pi[1]],
3031 path = [x0, ",", y0];
3032 d3_svg_lineBasisBezier(path, px, py);
3035 px.shift(); px.push(pi[0]);
3036 py.shift(); py.push(pi[1]);
3037 d3_svg_lineBasisBezier(path, px, py);
3041 px.shift(); px.push(pi[0]);
3042 py.shift(); py.push(pi[1]);
3043 d3_svg_lineBasisBezier(path, px, py);
3045 return path.join("");
3048 // Open B-spline interpolation; generates "C" commands.
3049 function d3_svg_lineBasisOpen(points) {
3050 if (points.length < 4) return d3_svg_lineLinear(points);
3062 path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px)
3063 + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
3064 --i; while (++i < n) {
3066 px.shift(); px.push(pi[0]);
3067 py.shift(); py.push(pi[1]);
3068 d3_svg_lineBasisBezier(path, px, py);
3070 return path.join("");
3073 // Closed B-spline interpolation; generates "C" commands.
3074 function d3_svg_lineBasisClosed(points) {
3088 d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",",
3089 d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)
3091 --i; while (++i < m) {
3093 px.shift(); px.push(pi[0]);
3094 py.shift(); py.push(pi[1]);
3095 d3_svg_lineBasisBezier(path, px, py);
3097 return path.join("");
3100 function d3_svg_lineBundle(points, tension) {
3101 var n = points.length - 1,
3104 dx = points[n][0] - x0,
3105 dy = points[n][1] - y0,
3112 p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
3113 p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
3115 return d3_svg_lineBasis(points);
3118 // Returns the dot product of the given four-element vectors.
3119 function d3_svg_lineDot4(a, b) {
3120 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
3123 // Matrix to transform basis (b-spline) control points to bezier
3124 // control points. Derived from FvD 11.2.8.
3125 var d3_svg_lineBasisBezier1 = [0, 2/3, 1/3, 0],
3126 d3_svg_lineBasisBezier2 = [0, 1/3, 2/3, 0],
3127 d3_svg_lineBasisBezier3 = [0, 1/6, 2/3, 1/6];
3129 // Pushes a "C" Bézier curve onto the specified path array, given the
3130 // two specified four-element arrays which define the control points.
3131 function d3_svg_lineBasisBezier(path, x, y) {
3133 "C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x),
3134 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y),
3135 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x),
3136 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y),
3137 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x),
3138 ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
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]);
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) {
3150 j = points.length - 1,
3154 d = m[0] = d3_svg_lineSlope(p0, p1);
3156 m[i] = d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]));
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) {
3171 m = d3_svg_lineFiniteDifferences(points),
3173 j = points.length - 1;
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.
3179 // Then, for each segment…
3181 d = d3_svg_lineSlope(points[i], points[i + 1]);
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.
3187 if (Math.abs(d) < 1e-6) {
3188 m[i] = m[i + 1] = 0;
3190 // 4. Let ak = mk / dk and bk = m{k + 1} / dk.
3194 // 5. Prevent overshoot and ensure monotonicity by restricting the
3195 // magnitude of vector <ak, bk> to a circle of radius 3.
3198 s = d * 3 / Math.sqrt(s);
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]);
3217 function d3_svg_lineMonotone(points) {
3218 return points.length < 3
3219 ? d3_svg_lineLinear(points)
3221 d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
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;
3230 function d3_svg_lineRadial(points) {
3239 a = point[1] + d3_svg_arcOffset;
3240 point[0] = r * Math.cos(a);
3241 point[1] = r * Math.sin(a);
3245 function d3_svg_area(projection) {
3246 var x0 = d3_svg_lineX,
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)
3264 area.x = function(x) {
3265 if (!arguments.length) return x1;
3270 area.x0 = function(x) {
3271 if (!arguments.length) return x0;
3276 area.x1 = function(x) {
3277 if (!arguments.length) return x1;
3282 area.y = function(y) {
3283 if (!arguments.length) return y1;
3288 area.y0 = function(y) {
3289 if (!arguments.length) return y0;
3294 area.y1 = function(y) {
3295 if (!arguments.length) return y1;
3300 area.interpolate = function(x) {
3301 if (!arguments.length) return interpolate;
3302 i0 = d3_svg_lineInterpolators[interpolate = x];
3303 i1 = i0.reverse || i0;
3307 area.tension = function(x) {
3308 if (!arguments.length) return tension;
3313 return area.interpolate("linear");
3316 d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
3317 d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
3319 d3.svg.area = function() {
3320 return d3_svg_area(Object);
3323 function d3_svg_areaX(points) {
3324 return function(d, i) {
3325 return points[i][0];
3329 function d3_svg_areaY(points) {
3330 return function(d, i) {
3331 return points[i][1];
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;
3344 d3.svg.chord = function() {
3345 var source = d3_svg_chordSource,
3346 target = d3_svg_chordTarget,
3347 radius = d3_svg_chordRadius,
3348 startAngle = d3_svg_arcStartAngle,
3349 endAngle = d3_svg_arcEndAngle;
3351 // TODO Allow control point to be customized.
3353 function chord(d, i) {
3354 var s = subgroup(this, source, d, i),
3355 t = subgroup(this, target, d, i);
3357 + arc(s.r, s.p1) + (equals(s, t)
3358 ? curve(s.r, s.p1, s.r, s.p0)
3359 : curve(s.r, s.p1, t.r, t.p0)
3361 + curve(t.r, t.p1, s.r, s.p0))
3365 function subgroup(self, f, d, i) {
3366 var subgroup = f.call(self, d, i),
3367 r = radius.call(self, subgroup, i),
3368 a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset,
3369 a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
3374 p0: [r * Math.cos(a0), r * Math.sin(a0)],
3375 p1: [r * Math.cos(a1), r * Math.sin(a1)]
3379 function equals(a, b) {
3380 return a.a0 == b.a0 && a.a1 == b.a1;
3383 function arc(r, p) {
3384 return "A" + r + "," + r + " 0 0,1 " + p;
3387 function curve(r0, p0, r1, p1) {
3388 return "Q 0,0 " + p1;
3391 chord.radius = function(v) {
3392 if (!arguments.length) return radius;
3393 radius = d3.functor(v);
3397 chord.source = function(v) {
3398 if (!arguments.length) return source;
3399 source = d3.functor(v);
3403 chord.target = function(v) {
3404 if (!arguments.length) return target;
3405 target = d3.functor(v);
3409 chord.startAngle = function(v) {
3410 if (!arguments.length) return startAngle;
3411 startAngle = d3.functor(v);
3415 chord.endAngle = function(v) {
3416 if (!arguments.length) return endAngle;
3417 endAngle = d3.functor(v);
3424 function d3_svg_chordSource(d) {
3428 function d3_svg_chordTarget(d) {
3432 function d3_svg_chordRadius(d) {
3436 function d3_svg_chordStartAngle(d) {
3437 return d.startAngle;
3440 function d3_svg_chordEndAngle(d) {
3443 d3.svg.diagonal = function() {
3444 var source = d3_svg_chordSource,
3445 target = d3_svg_chordTarget,
3446 projection = d3_svg_diagonalProjection;
3448 function diagonal(d, i) {
3449 var p0 = source.call(this, d, i),
3450 p3 = target.call(this, d, i),
3451 m = (p0.y + p3.y) / 2,
3452 p = [p0, {x: p0.x, y: m}, {x: p3.x, y: m}, p3];
3453 p = p.map(projection);
3454 return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
3457 diagonal.source = function(x) {
3458 if (!arguments.length) return source;
3459 source = d3.functor(x);
3463 diagonal.target = function(x) {
3464 if (!arguments.length) return target;
3465 target = d3.functor(x);
3469 diagonal.projection = function(x) {
3470 if (!arguments.length) return projection;
3478 function d3_svg_diagonalProjection(d) {
3481 d3.svg.diagonal.radial = function() {
3482 var diagonal = d3.svg.diagonal(),
3483 projection = d3_svg_diagonalProjection,
3484 projection_ = diagonal.projection;
3486 diagonal.projection = function(x) {
3487 return arguments.length
3488 ? projection_(d3_svg_diagonalRadialProjection(projection = x))
3495 function d3_svg_diagonalRadialProjection(projection) {
3497 var d = projection.apply(this, arguments),
3499 a = d[1] + d3_svg_arcOffset;
3500 return [r * Math.cos(a), r * Math.sin(a)];
3503 d3.svg.mouse = function(container) {
3504 return d3_svg_mousePoint(container, d3.event);
3507 // https://bugs.webkit.org/show_bug.cgi?id=44083
3508 var d3_mouse_bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0;
3510 function d3_svg_mousePoint(container, e) {
3511 var point = (container.ownerSVGElement || container).createSVGPoint();
3512 if ((d3_mouse_bug44083 < 0) && (window.scrollX || window.scrollY)) {
3513 var svg = d3.select(document.body)
3515 .style("position", "absolute")
3518 var ctm = svg[0][0].getScreenCTM();
3519 d3_mouse_bug44083 = !(ctm.f || ctm.e);
3522 if (d3_mouse_bug44083) {
3526 point.x = e.clientX;
3527 point.y = e.clientY;
3529 point = point.matrixTransform(container.getScreenCTM().inverse());
3530 return [point.x, point.y];
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;
3540 d3.svg.symbol = function() {
3541 var type = d3_svg_symbolType,
3542 size = d3_svg_symbolSize;
3544 function symbol(d, i) {
3545 return (d3_svg_symbols[type.call(this, d, i)]
3546 || d3_svg_symbols.circle)
3547 (size.call(this, d, i));
3550 symbol.type = function(x) {
3551 if (!arguments.length) return type;
3552 type = d3.functor(x);
3556 // size of symbol in square pixels
3557 symbol.size = function(x) {
3558 if (!arguments.length) return size;
3559 size = d3.functor(x);
3566 function d3_svg_symbolSize() {
3570 function d3_svg_symbolType() {
3574 // TODO cross-diagonal?
3575 var d3_svg_symbols = {
3576 "circle": function(size) {
3577 var r = Math.sqrt(size / Math.PI);
3579 + "A" + r + "," + r + " 0 1,1 0," + (-r)
3580 + "A" + r + "," + r + " 0 1,1 0," + r
3583 "cross": function(size) {
3584 var r = Math.sqrt(size / 5) / 2;
3585 return "M" + -3 * r + "," + -r
3599 "diamond": function(size) {
3600 var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)),
3601 rx = ry * d3_svg_symbolTan30;
3608 "square": function(size) {
3609 var r = Math.sqrt(size) / 2;
3610 return "M" + -r + "," + -r
3611 + "L" + r + "," + -r
3613 + " " + -r + "," + r
3616 "triangle-down": function(size) {
3617 var rx = Math.sqrt(size / d3_svg_symbolSqrt3),
3618 ry = rx * d3_svg_symbolSqrt3 / 2;
3620 + "L" + rx +"," + -ry
3621 + " " + -rx + "," + -ry
3624 "triangle-up": function(size) {
3625 var rx = Math.sqrt(size / d3_svg_symbolSqrt3),
3626 ry = rx * d3_svg_symbolSqrt3 / 2;
3628 + "L" + rx +"," + ry
3629 + " " + -rx + "," + ry
3634 d3.svg.symbolTypes = d3.keys(d3_svg_symbols);
3636 var d3_svg_symbolSqrt3 = Math.sqrt(3),
3637 d3_svg_symbolTan30 = Math.tan(30 * Math.PI / 180);
3638 d3.svg.axis = function() {
3639 var scale = d3.scale.linear(),
3645 tickArguments_ = [10],
3649 function axis(selection) {
3650 selection.each(function(d, i, j) {
3651 var g = d3.select(this);
3653 // If selection is a transition, create subtransitions.
3654 var transition = selection.delay ? function(o) {
3655 var id = d3_transitionInheritId;
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());
3663 d3_transitionInheritId = id;
3668 var ticks = scale.ticks.apply(scale, tickArguments_),
3669 tickFormat = tickFormat_ == null ? scale.tickFormat.apply(scale, tickArguments_) : tickFormat_;
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);
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),
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);
3691 // Stash the new scale and grab the old scale.
3692 var scale0 = this.__chart__ || scale;
3693 this.__chart__ = scale.copy();
3695 tickEnter.append("svg:line").attr("class", "tick");
3696 tickEnter.append("svg:text");
3697 tickUpdate.select("text").text(tickFormat);
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);
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);
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);
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);
3734 tickEnter.call(tickTransform, scale0);
3735 tickUpdate.call(tickTransform, scale);
3736 tickExit.call(tickTransform, scale);
3738 subtickEnter.call(tickTransform, scale0);
3739 subtickUpdate.call(tickTransform, scale);
3740 subtickExit.call(tickTransform, scale);
3744 axis.scale = function(x) {
3745 if (!arguments.length) return scale;
3750 axis.orient = function(x) {
3751 if (!arguments.length) return orient;
3756 axis.ticks = function() {
3757 if (!arguments.length) return tickArguments_;
3758 tickArguments_ = arguments;
3762 axis.tickFormat = function(x) {
3763 if (!arguments.length) return tickFormat_;
3768 axis.tickSize = function(x, y, z) {
3769 if (!arguments.length) return tickMajorSize;
3770 var n = arguments.length - 1;
3772 tickMinorSize = n > 1 ? +y : tickMajorSize;
3773 tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
3777 axis.tickPadding = function(x) {
3778 if (!arguments.length) return tickPadding;
3783 axis.tickSubdivide = function(x) {
3784 if (!arguments.length) return tickSubdivide;
3792 function d3_svg_axisX(selection, x) {
3793 selection.attr("transform", function(d) { return "translate(" + x(d) + ",0)"; });
3796 function d3_svg_axisY(selection, y) {
3797 selection.attr("transform", function(d) { return "translate(0," + y(d) + ")"; });
3800 function d3_svg_axisSubdivide(scale, ticks, m) {
3802 if (m && ticks.length > 1) {
3803 var extent = d3_scaleExtent(scale.domain()),
3807 d = (ticks[1] - ticks[0]) / ++m,
3811 for (j = m; --j > 0;) {
3812 if ((v = +ticks[i] - j * d) >= extent[0]) {
3817 for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1];) {
3824 d3.behavior.drag = function() {
3825 var event = d3.dispatch("drag", "dragstart", "dragend");
3829 .on("mousedown.drag", mousedown)
3830 .on("touchstart.drag", mousedown);
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);
3840 // snapshot the local context for subsequent dispatch
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;
3849 function mousedown() {
3850 start.apply(this, arguments);
3851 d3_behavior_dragDispatch("dragstart");
3854 drag.on = function(type, listener) {
3855 event[type].add(listener);
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;
3870 function d3_behavior_dragDispatch(type) {
3871 var o = d3.event, p = d3_behavior_dragTarget.parentNode, dx = 0, dy = 0;
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;
3882 d3.event = {dx: dx, dy: dy};
3883 d3_behavior_dragEvent[type].dispatch.apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
3891 function d3_behavior_dragPoint(container) {
3892 return d3.event.touches
3893 ? d3.svg.touches(container)[0]
3894 : d3.svg.mouse(container);
3897 function d3_behavior_dragMove() {
3898 if (!d3_behavior_dragTarget) return;
3899 var parent = d3_behavior_dragTarget.parentNode;
3901 // O NOES! The drag element was removed from the DOM.
3902 if (!parent) return d3_behavior_dragUp();
3904 d3_behavior_dragDispatch("drag");
3905 d3_behavior_dragCancel();
3908 function d3_behavior_dragUp() {
3909 if (!d3_behavior_dragTarget) return;
3910 d3_behavior_dragDispatch("dragend");
3911 d3_behavior_dragTarget = null;
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();
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;
3929 function d3_behavior_dragCancel() {
3930 d3.event.stopPropagation();
3931 d3.event.preventDefault();
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");
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);
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);
3955 // snapshot the local context for subsequent dispatch
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;
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();
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);
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));
3985 // doubletap detection
3986 function touchstart() {
3987 start.apply(this, arguments);
3988 var touches = d3_behavior_zoomTouchup(),
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]);
3994 d3_behavior_zoomLast = now;
3997 zoom.on = function(type, listener) {
3998 event[type].add(listener);
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;
4018 function d3_behavior_zoomLocation(point) {
4020 point[0] - d3_behavior_zoomXyz[0],
4021 point[1] - d3_behavior_zoomXyz[1],
4022 d3_behavior_zoomXyz[2]
4026 // detect the pixels that would be scrolled by this wheel event
4027 function d3_behavior_zoomDelta() {
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")
4038 .style("overflow-y", "scroll")
4040 .style("height", "2000px")
4044 var e = d3.event, delta;
4046 d3_behavior_zoomDiv.scrollTop = 1000;
4047 d3_behavior_zoomDiv.dispatchEvent(e);
4048 delta = 1000 - d3_behavior_zoomDiv.scrollTop;
4050 delta = e.wheelDelta || (-e.detail * 5);
4053 return delta * .005;
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),
4064 while (++i < n) d3_behavior_zoomLocations[(touch = touches[i]).identifier] = d3_behavior_zoomLocation(touch);
4068 function d3_behavior_zoomTouchmove() {
4069 var touches = d3.svg.touches(d3_behavior_zoomTarget);
4070 switch (touches.length) {
4074 var touch = touches[0];
4075 d3_behavior_zoomTo(d3_behavior_zoomXyz[2], touch, d3_behavior_zoomLocations[touch.identifier]);
4079 // double-touch pan + zoom
4081 var p0 = touches[0],
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);
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);
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;
4106 d3_behavior_zoomMousemove();
4107 d3_behavior_zoomPanning = null;
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;
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).
4130 transform: function(sx, sy) {
4131 if (sx) transform(sx, x);
4132 if (sy) transform(sy, y);
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));
4143 d3_behavior_zoomDispatch.apply(d3_behavior_zoomTarget, d3_behavior_zoomArguments);