d3-jsnext
Version:
d3, but futuristic
1,599 lines (1,365 loc) • 91 kB
JavaScript
(function () { 'use strict';
var width = 960,
height = 500;
var d3$select;
var d3$selection;
var d3_document = window.document;
d3$selection = function() {
return d3$select(d3_document.documentElement);
};
var d3_selectionPrototype = d3$selection.prototype = [];
var d3_vendorPrefixes = ["webkit", "ms", "moz", "Moz", "o", "O"];
function d3_vendorSymbol(object, name) {
if (name in object) return name;
name = name.charAt(0).toUpperCase() + name.slice(1);
for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
var prefixName = d3_vendorPrefixes[i] + name;
if (prefixName in object) return prefixName;
}
}
var d3_select = function(s, n) { return n.querySelector(s); },
d3_selectAll = function(s, n) { return n.querySelectorAll(s); },
d3_selectMatches = function(n, s) {
var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
d3_selectMatches = function(n, s) {
return d3_selectMatcher.call(n, s);
};
return d3_selectMatches(n, s);
};// Prefer Sizzle, if available.
if (typeof Sizzle === "function") {
d3_select = function(s, n) { return Sizzle(s, n)[0] || null; };
d3_selectAll = Sizzle;
d3_selectMatches = Sizzle.matchesSelector;
}
function d3_selection_selector(selector) {
return typeof selector === "function" ? selector : function() {
return d3_select(selector, this);
};
}
d3_selectionPrototype.select = function(selector) {
var subgroups = [],
subgroup,
subnode,
group,
node;
selector = d3_selection_selector(selector);
for (var j = -1, m = this.length; ++j < m;) {
subgroups.push(subgroup = []);
subgroup.parentNode = (group = this[j]).parentNode;
for (var i = -1, n = group.length; ++i < n;) {
if (node = group[i]) {
subgroup.push(subnode = selector.call(node, node.__data__, i, j));
if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
} else {
subgroup.push(null);
}
}
}
return d3_selection(subgroups);
};
var d3_arraySlice = [].slice,
d3_array = function(list) { return d3_arraySlice.call(list); }; // conversion for NodeLists
function d3_selection_selectorAll(selector) {
return typeof selector === "function" ? selector : function() {
return d3_selectAll(selector, this);
};
}
d3_selectionPrototype.selectAll = function(selector) {
var subgroups = [],
subgroup,
node;
selector = d3_selection_selectorAll(selector);
for (var j = -1, m = this.length; ++j < m;) {
for (var group = this[j], i = -1, n = group.length; ++i < n;) {
if (node = group[i]) {
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
subgroup.parentNode = node;
}
}
}
return d3_selection(subgroups);
};
var d3$ns;
var d3_nsPrefix = {
svg: "http://www.w3.org/2000/svg",
xhtml: "http://www.w3.org/1999/xhtml",
xlink: "http://www.w3.org/1999/xlink",
xml: "http://www.w3.org/XML/1998/namespace",
xmlns: "http://www.w3.org/2000/xmlns/"
};
d3$ns = {
prefix: d3_nsPrefix,
qualify: function(name) {
var i = name.indexOf(":"),
prefix = name;
if (i >= 0) {
prefix = name.slice(0, i);
name = name.slice(i + 1);
}
return d3_nsPrefix.hasOwnProperty(prefix)
? {space: d3_nsPrefix[prefix], local: name}
: name;
}
};
function d3_selection_attr(name, value) {
name = d3$ns.qualify(name);
// For attr(string, null), remove the attribute with the specified name.
function attrNull() {
this.removeAttribute(name);
}
function attrNullNS() {
this.removeAttributeNS(name.space, name.local);
}
// For attr(string, string), set the attribute with the specified name.
function attrConstant() {
this.setAttribute(name, value);
}
function attrConstantNS() {
this.setAttributeNS(name.space, name.local, value);
}
// For attr(string, function), evaluate the function for each element, and set
// or remove the attribute as appropriate.
function attrFunction() {
var x = value.apply(this, arguments);
if (x == null) this.removeAttribute(name);
else this.setAttribute(name, x);
}
function attrFunctionNS() {
var x = value.apply(this, arguments);
if (x == null) this.removeAttributeNS(name.space, name.local);
else this.setAttributeNS(name.space, name.local, x);
}
return value == null
? (name.local ? attrNullNS : attrNull) : (typeof value === "function"
? (name.local ? attrFunctionNS : attrFunction)
: (name.local ? attrConstantNS : attrConstant));
}
d3_selectionPrototype.attr = function(name, value) {
if (arguments.length < 2) {
// For attr(string), return the attribute value for the first node.
if (typeof name === "string") {
var node = this.node();
name = d3$ns.qualify(name);
return name.local
? node.getAttributeNS(name.space, name.local)
: node.getAttribute(name);
}
// For attr(object), the object specifies the names and values of the
// attributes to set or remove. The values may be functions that are
// evaluated for each element.
for (value in name) this.each(d3_selection_attr(value, name[value]));
return this;
}
return this.each(d3_selection_attr(name, value));
};
function d3_collapse(s) {
return s.trim().replace(/\s+/g, " ");
}
var d3$requote;
var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
d3$requote = function(s) {
return s.replace(d3_requote_re, "\\$&");
};
function d3_selection_classedRe(name) {
return new RegExp("(?:^|\\s+)" + d3$requote(name) + "(?:\\s+|$)", "g");
}
function d3_selection_classedName(name) {
var re = d3_selection_classedRe(name);
return function(node, value) {
if (c = node.classList) return value ? c.add(name) : c.remove(name);
var c = node.getAttribute("class") || "";
if (value) {
re.lastIndex = 0;
if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
} else {
node.setAttribute("class", d3_collapse(c.replace(re, " ")));
}
};
}
function d3_selection_classes(name) {
return (name + "").trim().split(/^|\s+/);
}// Multiple class names are allowed (e.g., "foo bar").
function d3_selection_classed(name, value) {
name = d3_selection_classes(name).map(d3_selection_classedName);
var n = name.length;
function classedConstant() {
var i = -1;
while (++i < n) name[i](this, value);
}
// When the value is a function, the function is still evaluated only once per
// element even if there are multiple class names.
function classedFunction() {
var i = -1, x = value.apply(this, arguments);
while (++i < n) name[i](this, x);
}
return typeof value === "function"
? classedFunction
: classedConstant;
}
d3_selectionPrototype.classed = function(name, value) {
if (arguments.length < 2) {
// For classed(string), return true only if the first node has the specified
// class or classes. Note that even if the browser supports DOMTokenList, it
// probably doesn't support it on SVG elements (which can be animated).
if (typeof name === "string") {
var node = this.node(),
n = (name = d3_selection_classes(name)).length,
i = -1;
if (value = node.classList) {
while (++i < n) if (!value.contains(name[i])) return false;
} else {
value = node.getAttribute("class");
while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
}
return true;
}
// For classed(object), the object specifies the names of classes to add or
// remove. The values may be functions that are evaluated for each element.
for (value in name) this.each(d3_selection_classed(value, name[value]));
return this;
}
// Otherwise, both a name and a value are specified, and are handled as below.
return this.each(d3_selection_classed(name, value));
};
function d3_selection_style(name, value, priority) {
// For style(name, null) or style(name, null, priority), remove the style
// property with the specified name. The priority is ignored.
function styleNull() {
this.style.removeProperty(name);
}
// For style(name, string) or style(name, string, priority), set the style
// property with the specified name, using the specified priority.
function styleConstant() {
this.style.setProperty(name, value, priority);
}
// For style(name, function) or style(name, function, priority), evaluate the
// function for each element, and set or remove the style property as
// appropriate. When setting, use the specified priority.
function styleFunction() {
var x = value.apply(this, arguments);
if (x == null) this.style.removeProperty(name);
else this.style.setProperty(name, x, priority);
}
return value == null
? styleNull : (typeof value === "function"
? styleFunction : styleConstant);
}
function d3_window(node) {
return node
&& ((node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
|| (node.document && node) // node is a Window
|| node.defaultView); // node is a Document
}
d3_selectionPrototype.style = function(name, value, priority) {
var n = arguments.length;
if (n < 3) {
// For style(object) or style(object, string), the object specifies the
// names and values of the attributes to set or remove. The values may be
// functions that are evaluated for each element. The optional string
// specifies the priority.
if (typeof name !== "string") {
if (n < 2) value = "";
for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
return this;
}
// For style(string), return the computed style value for the first node.
if (n < 2) {
var node = this.node();
return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
}
// For style(string, string) or style(string, function), use the default
// priority. The priority is ignored for style(string, null).
priority = "";
}
// Otherwise, a name, value and priority are specified, and handled as below.
return this.each(d3_selection_style(name, value, priority));
};
function d3_selection_property(name, value) {
// For property(name, null), remove the property with the specified name.
function propertyNull() {
delete this[name];
}
// For property(name, string), set the property with the specified name.
function propertyConstant() {
this[name] = value;
}
// For property(name, function), evaluate the function for each element, and
// set or remove the property as appropriate.
function propertyFunction() {
var x = value.apply(this, arguments);
if (x == null) delete this[name];
else this[name] = x;
}
return value == null
? propertyNull : (typeof value === "function"
? propertyFunction : propertyConstant);
}
d3_selectionPrototype.property = function(name, value) {
if (arguments.length < 2) {
// For property(string), return the property value for the first node.
if (typeof name === "string") return this.node()[name];
// For property(object), the object specifies the names and values of the
// properties to set or remove. The values may be functions that are
// evaluated for each element.
for (value in name) this.each(d3_selection_property(value, name[value]));
return this;
}
// Otherwise, both a name and a value are specified, and are handled as below.
return this.each(d3_selection_property(name, value));
};
d3_selectionPrototype.text = function(value) {
return arguments.length
? this.each(typeof value === "function"
? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null
? function() { this.textContent = ""; }
: function() { this.textContent = value; })
: this.node().textContent;
};
d3_selectionPrototype.html = function(value) {
return arguments.length
? this.each(typeof value === "function"
? function() { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; } : value == null
? function() { this.innerHTML = ""; }
: function() { this.innerHTML = value; })
: this.node().innerHTML;
};
function d3_selection_creator(name) {
function create() {
var document = this.ownerDocument,
namespace = this.namespaceURI;
return namespace
? document.createElementNS(namespace, name)
: document.createElement(name);
}
function createNS() {
return this.ownerDocument.createElementNS(name.space, name.local);
}
return typeof name === "function" ? name
: (name = d3$ns.qualify(name)).local ? createNS
: create;
}
d3_selectionPrototype.append = function(name) {
name = d3_selection_creator(name);
return this.select(function() {
return this.appendChild(name.apply(this, arguments));
});
};
d3_selectionPrototype.insert = function(name, before) {
name = d3_selection_creator(name);
before = d3_selection_selector(before);
return this.select(function() {
return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
});
};
function d3_selectionRemove() {
var parent = this.parentNode;
if (parent) parent.removeChild(this);
}// TODO remove(selector)?
// TODO remove(node)?
// TODO remove(function)?
d3_selectionPrototype.remove = function() {
return this.each(d3_selectionRemove);
};
var d3_selection_enterPrototype = [];
d3_selection_enterPrototype.append = d3_selectionPrototype.append;
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
d3_selection_enterPrototype.node = d3_selectionPrototype.node;
d3_selection_enterPrototype.call = d3_selectionPrototype.call;
d3_selection_enterPrototype.size = d3_selectionPrototype.size;
d3_selection_enterPrototype.select = function(selector) {
var subgroups = [],
subgroup,
subnode,
upgroup,
group,
node;
for (var j = -1, m = this.length; ++j < m;) {
upgroup = (group = this[j]).update;
subgroups.push(subgroup = []);
subgroup.parentNode = group.parentNode;
for (var i = -1, n = group.length; ++i < n;) {
if (node = group[i]) {
subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
subnode.__data__ = node.__data__;
} else {
subgroup.push(null);
}
}
}
return d3_selection(subgroups);
};
function d3_selection_enterInsertBefore(enter) {
var i0, j0;
return function(d, i, j) {
var group = enter[j].update,
n = group.length,
node;
if (j != j0) j0 = j, i0 = 0;
if (i >= i0) i0 = i + 1;
while (!(node = group[i0]) && ++i0 < n);
return node;
};
}
d3_selection_enterPrototype.insert = function(name, before) {
if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
return d3_selectionPrototype.insert.call(this, name, before);
};
var d3_subclass = {}.__proto__?
// Until ECMAScript supports array subclassing, prototype injection works well.
function(object, prototype) {
object.__proto__ = prototype;
}:
// And if your browser doesn't support __proto__, we'll use direct extension.
function(object, prototype) {
for (var property in prototype) object[property] = prototype[property];
};
function d3_selection_enter(selection) {
d3_subclass(selection, d3_selection_enterPrototype);
return selection;
}
function d3_selection_dataNode(data) {
return {__data__: data};
}
function d3_Map() {
this._ = Object.create(null);
}
var d3_map_proto = "__proto__",
d3_map_zero = "\0";
function d3_map_unescape(key) {
return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
}
function d3_map_empty() {
for (var key in this._) return false;
return true;
}
function d3_map_size() {
var size = 0;
for (var key in this._) ++size;
return size;
}
function d3_map_keys() {
var keys = [];
for (var key in this._) keys.push(d3_map_unescape(key));
return keys;
}
function d3_map_escape(key) {
return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
}
function d3_map_remove(key) {
return (key = d3_map_escape(key)) in this._ && delete this._[key];
}
function d3_map_has(key) {
return d3_map_escape(key) in this._;
}
function d3_class(ctor, properties) {
for (var key in properties) {
Object.defineProperty(ctor.prototype, key, {
value: properties[key],
enumerable: false
});
}
}
d3_class(d3_Map, {
has: d3_map_has,
get: function(key) {
return this._[d3_map_escape(key)];
},
set: function(key, value) {
return this._[d3_map_escape(key)] = value;
},
remove: d3_map_remove,
keys: d3_map_keys,
values: function() {
var values = [];
for (var key in this._) values.push(this._[key]);
return values;
},
entries: function() {
var entries = [];
for (var key in this._) entries.push({key: d3_map_unescape(key), value: this._[key]});
return entries;
},
size: d3_map_size,
empty: d3_map_empty,
forEach: function(f) {
for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
}
});
d3_selectionPrototype.data = function(value, key) {
var i = -1,
n = this.length,
group,
node;
// If no value is specified, return the first value.
if (!arguments.length) {
value = new Array(n = (group = this[0]).length);
while (++i < n) {
if (node = group[i]) {
value[i] = node.__data__;
}
}
return value;
}
function bind(group, groupData) {
var i,
n = group.length,
m = groupData.length,
n0 = Math.min(n, m),
updateNodes = new Array(m),
enterNodes = new Array(m),
exitNodes = new Array(n),
node,
nodeData;
if (key) {
var nodeByKeyValue = new d3_Map,
keyValues = new Array(n),
keyValue;
for (i = -1; ++i < n;) {
if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
exitNodes[i] = node; // duplicate selection key
} else {
nodeByKeyValue.set(keyValue, node);
}
keyValues[i] = keyValue;
}
for (i = -1; ++i < m;) {
if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
enterNodes[i] = d3_selection_dataNode(nodeData);
} else if (node !== true) { // no duplicate data key
updateNodes[i] = node;
node.__data__ = nodeData;
}
nodeByKeyValue.set(keyValue, true);
}
for (i = -1; ++i < n;) {
if (nodeByKeyValue.get(keyValues[i]) !== true) {
exitNodes[i] = group[i];
}
}
} else {
for (i = -1; ++i < n0;) {
node = group[i];
nodeData = groupData[i];
if (node) {
node.__data__ = nodeData;
updateNodes[i] = node;
} else {
enterNodes[i] = d3_selection_dataNode(nodeData);
}
}
for (; i < m; ++i) {
enterNodes[i] = d3_selection_dataNode(groupData[i]);
}
for (; i < n; ++i) {
exitNodes[i] = group[i];
}
}
enterNodes.update
= updateNodes;
enterNodes.parentNode
= updateNodes.parentNode
= exitNodes.parentNode
= group.parentNode;
enter.push(enterNodes);
update.push(updateNodes);
exit.push(exitNodes);
}
var enter = d3_selection_enter([]),
update = d3_selection([]),
exit = d3_selection([]);
if (typeof value === "function") {
while (++i < n) {
bind(group = this[i], value.call(group, group.parentNode.__data__, i));
}
} else {
while (++i < n) {
bind(group = this[i], value);
}
}
update.enter = function() { return enter; };
update.exit = function() { return exit; };
return update;
};
d3_selectionPrototype.datum = function(value) {
return arguments.length
? this.property("__data__", value)
: this.property("__data__");
};
function d3_selection_filter(selector) {
return function() {
return d3_selectMatches(this, selector);
};
}
d3_selectionPrototype.filter = function(filter) {
var subgroups = [],
subgroup,
group,
node;
if (typeof filter !== "function") filter = d3_selection_filter(filter);
for (var j = 0, m = this.length; j < m; j++) {
subgroups.push(subgroup = []);
subgroup.parentNode = (group = this[j]).parentNode;
for (var i = 0, n = group.length; i < n; i++) {
if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
subgroup.push(node);
}
}
}
return d3_selection(subgroups);
};
d3_selectionPrototype.order = function() {
for (var j = -1, m = this.length; ++j < m;) {
for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
if (node = group[i]) {
if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
next = node;
}
}
}
return this;
};
function d3_ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
function d3_selection_sortComparator(comparator) {
if (!arguments.length) comparator = d3_ascending;
return function(a, b) {
return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
};
}
d3_selectionPrototype.sort = function(comparator) {
comparator = d3_selection_sortComparator.apply(this, arguments);
for (var j = -1, m = this.length; ++j < m;) this[j].sort(comparator);
return this.order();
};
function d3_noop() {}
function d3_selection_onListener(listener, argumentz) {
return function(e) {
var o = window.d3_event; // Events can be reentrant (e.g., focus).
window.d3_event = e;
argumentz[0] = this.__data__;
try {
listener.apply(this, argumentz);
} finally {
window.d3_event = o;
}
};
}
function d3_selection_onFilter(listener, argumentz) {
var l = d3_selection_onListener(listener, argumentz);
return function(e) {
var target = this, related = e.relatedTarget;
if (!related || (related !== target && !(related.compareDocumentPosition(target) & 8))) {
l.call(target, e);
}
};
}
var d3$map;
d3$map = function(object, f) {
var map = new d3_Map;
if (object instanceof d3_Map) {
object.forEach(function(key, value) { map.set(key, value); });
} else if (Array.isArray(object)) {
var i = -1,
n = object.length,
o;
if (arguments.length === 1) while (++i < n) map.set(i, object[i]);
else while (++i < n) map.set(f.call(object, o = object[i], i), o);
} else {
for (var key in object) map.set(key, object[key]);
}
return map;
};
var d3_selection_onFilters = d3$map({
mouseenter: "mouseover",
mouseleave: "mouseout"
});
function d3_selection_on(type, listener, capture) {
var name = "__on" + type,
i = type.indexOf("."),
wrap = d3_selection_onListener;
if (i > 0) type = type.slice(0, i);
var filter = d3_selection_onFilters.get(type);
if (filter) type = filter, wrap = d3_selection_onFilter;
function onRemove() {
var l = this[name];
if (l) {
this.removeEventListener(type, l, l.$);
delete this[name];
}
}
function onAdd() {
var l = wrap(listener, d3_array(arguments));
onRemove.call(this);
this.addEventListener(type, this[name] = l, l.$ = capture);
l._ = listener;
}
function removeAll() {
var re = new RegExp("^__on([^.]+)" + d3$requote(type) + "$"),
match;
for (var name in this) {
if (match = name.match(re)) {
var l = this[name];
this.removeEventListener(match[1], l, l.$);
delete this[name];
}
}
}
return i
? listener ? onAdd : onRemove
: listener ? d3_noop : removeAll;
}
d3_selectionPrototype.on = function(type, listener, capture) {
var n = arguments.length;
if (n < 3) {
// For on(object) or on(object, boolean), the object specifies the event
// types and listeners to add or remove. The optional boolean specifies
// whether the listener captures events.
if (typeof type !== "string") {
if (n < 2) listener = false;
for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
return this;
}
// For on(string), return the listener for the first node.
if (n < 2) return (n = this.node()["__on" + type]) && n._;
// For on(string, function), use the default capture.
capture = false;
}
// Otherwise, a type, listener and capture are specified, and handled as below.
return this.each(d3_selection_on(type, listener, capture));
};
function d3_selection_each(groups, callback) {
for (var j = 0, m = groups.length; j < m; j++) {
for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
if (node = group[i]) callback(node, i, j);
}
}
return groups;
}
d3_selectionPrototype.each = function(callback) {
return d3_selection_each(this, function(node, i, j) {
callback.call(node, node.__data__, i, j);
});
};
d3_selectionPrototype.call = function(callback) {
var args = d3_array(arguments);
callback.apply(args[0] = this, args);
return this;
};
d3_selectionPrototype.empty = function() {
return !this.node();
};
d3_selectionPrototype.node = function() {
for (var j = 0, m = this.length; j < m; j++) {
for (var group = this[j], i = 0, n = group.length; i < n; i++) {
var node = group[i];
if (node) return node;
}
}
return null;
};
d3_selectionPrototype.size = function() {
var n = 0;
d3_selection_each(this, function() { ++n; });
return n;
};
function d3_selection(groups) {
d3_subclass(groups, d3_selectionPrototype);
return groups;
}
function d3_documentElement(node) {
return node
&& (node.ownerDocument // node is a Node
|| node.document // node is a Window
|| node).documentElement; // node is a Document
}// TODO fast singleton implementation?
d3$select = function(node) {
var group;
if (typeof node === "string") {
group = [d3_select(node, d3_document)];
group.parentNode = d3_document.documentElement;
} else {
group = [node];
group.parentNode = d3_documentElement(node);
}
return d3_selection([group]);
};
var d3$scale$category20;
function d3_hsl_rgb(h, s, l) {
var m1,
m2;
/* Some simple corrections for h, s and l. */
h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
l = l < 0 ? 0 : l > 1 ? 1 : l;
/* From FvD 13.37, CSS Color Module Level 3 */
m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
m1 = 2 * l - m2;
function v(h) {
if (h > 360) h -= 360;
else if (h < 0) h += 360;
if (h < 60) return m1 + (m2 - m1) * h / 60;
if (h < 180) return m2;
if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
return m1;
}
function vv(h) {
return Math.round(v(h) * 255);
}
return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
}
var d3_rgb_names = d3$map({
aliceblue: 0xf0f8ff,
antiquewhite: 0xfaebd7,
aqua: 0x00ffff,
aquamarine: 0x7fffd4,
azure: 0xf0ffff,
beige: 0xf5f5dc,
bisque: 0xffe4c4,
black: 0x000000,
blanchedalmond: 0xffebcd,
blue: 0x0000ff,
blueviolet: 0x8a2be2,
brown: 0xa52a2a,
burlywood: 0xdeb887,
cadetblue: 0x5f9ea0,
chartreuse: 0x7fff00,
chocolate: 0xd2691e,
coral: 0xff7f50,
cornflowerblue: 0x6495ed,
cornsilk: 0xfff8dc,
crimson: 0xdc143c,
cyan: 0x00ffff,
darkblue: 0x00008b,
darkcyan: 0x008b8b,
darkgoldenrod: 0xb8860b,
darkgray: 0xa9a9a9,
darkgreen: 0x006400,
darkgrey: 0xa9a9a9,
darkkhaki: 0xbdb76b,
darkmagenta: 0x8b008b,
darkolivegreen: 0x556b2f,
darkorange: 0xff8c00,
darkorchid: 0x9932cc,
darkred: 0x8b0000,
darksalmon: 0xe9967a,
darkseagreen: 0x8fbc8f,
darkslateblue: 0x483d8b,
darkslategray: 0x2f4f4f,
darkslategrey: 0x2f4f4f,
darkturquoise: 0x00ced1,
darkviolet: 0x9400d3,
deeppink: 0xff1493,
deepskyblue: 0x00bfff,
dimgray: 0x696969,
dimgrey: 0x696969,
dodgerblue: 0x1e90ff,
firebrick: 0xb22222,
floralwhite: 0xfffaf0,
forestgreen: 0x228b22,
fuchsia: 0xff00ff,
gainsboro: 0xdcdcdc,
ghostwhite: 0xf8f8ff,
gold: 0xffd700,
goldenrod: 0xdaa520,
gray: 0x808080,
green: 0x008000,
greenyellow: 0xadff2f,
grey: 0x808080,
honeydew: 0xf0fff0,
hotpink: 0xff69b4,
indianred: 0xcd5c5c,
indigo: 0x4b0082,
ivory: 0xfffff0,
khaki: 0xf0e68c,
lavender: 0xe6e6fa,
lavenderblush: 0xfff0f5,
lawngreen: 0x7cfc00,
lemonchiffon: 0xfffacd,
lightblue: 0xadd8e6,
lightcoral: 0xf08080,
lightcyan: 0xe0ffff,
lightgoldenrodyellow: 0xfafad2,
lightgray: 0xd3d3d3,
lightgreen: 0x90ee90,
lightgrey: 0xd3d3d3,
lightpink: 0xffb6c1,
lightsalmon: 0xffa07a,
lightseagreen: 0x20b2aa,
lightskyblue: 0x87cefa,
lightslategray: 0x778899,
lightslategrey: 0x778899,
lightsteelblue: 0xb0c4de,
lightyellow: 0xffffe0,
lime: 0x00ff00,
limegreen: 0x32cd32,
linen: 0xfaf0e6,
magenta: 0xff00ff,
maroon: 0x800000,
mediumaquamarine: 0x66cdaa,
mediumblue: 0x0000cd,
mediumorchid: 0xba55d3,
mediumpurple: 0x9370db,
mediumseagreen: 0x3cb371,
mediumslateblue: 0x7b68ee,
mediumspringgreen: 0x00fa9a,
mediumturquoise: 0x48d1cc,
mediumvioletred: 0xc71585,
midnightblue: 0x191970,
mintcream: 0xf5fffa,
mistyrose: 0xffe4e1,
moccasin: 0xffe4b5,
navajowhite: 0xffdead,
navy: 0x000080,
oldlace: 0xfdf5e6,
olive: 0x808000,
olivedrab: 0x6b8e23,
orange: 0xffa500,
orangered: 0xff4500,
orchid: 0xda70d6,
palegoldenrod: 0xeee8aa,
palegreen: 0x98fb98,
paleturquoise: 0xafeeee,
palevioletred: 0xdb7093,
papayawhip: 0xffefd5,
peachpuff: 0xffdab9,
peru: 0xcd853f,
pink: 0xffc0cb,
plum: 0xdda0dd,
powderblue: 0xb0e0e6,
purple: 0x800080,
rebeccapurple: 0x663399,
red: 0xff0000,
rosybrown: 0xbc8f8f,
royalblue: 0x4169e1,
saddlebrown: 0x8b4513,
salmon: 0xfa8072,
sandybrown: 0xf4a460,
seagreen: 0x2e8b57,
seashell: 0xfff5ee,
sienna: 0xa0522d,
silver: 0xc0c0c0,
skyblue: 0x87ceeb,
slateblue: 0x6a5acd,
slategray: 0x708090,
slategrey: 0x708090,
snow: 0xfffafa,
springgreen: 0x00ff7f,
steelblue: 0x4682b4,
tan: 0xd2b48c,
teal: 0x008080,
thistle: 0xd8bfd8,
tomato: 0xff6347,
turquoise: 0x40e0d0,
violet: 0xee82ee,
wheat: 0xf5deb3,
white: 0xffffff,
whitesmoke: 0xf5f5f5,
yellow: 0xffff00,
yellowgreen: 0x9acd32
});
function d3_rgb_parseNumber(c) { // either integer or percentage
var f = parseFloat(c);
return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
}
function d3_rgb_parse(format, rgb, hsl) {
var r = 0, // red channel; int in [0, 255]
g = 0, // green channel; int in [0, 255]
b = 0, // blue channel; int in [0, 255]
m1, // CSS color specification match
m2, // CSS color specification type (e.g., rgb)
color;
/* Handle hsl, rgb. */
m1 = /([a-z]+)\((.*)\)/i.exec(format);
if (m1) {
m2 = m1[2].split(",");
switch (m1[1]) {
case "hsl": {
return hsl(
parseFloat(m2[0]), // degrees
parseFloat(m2[1]) / 100, // percentage
parseFloat(m2[2]) / 100 // percentage
);
}
case "rgb": {
return rgb(
d3_rgb_parseNumber(m2[0]),
d3_rgb_parseNumber(m2[1]),
d3_rgb_parseNumber(m2[2])
);
}
}
}
/* Named colors. */
if (color = d3_rgb_names.get(format.toLowerCase())) {
return rgb(color.r, color.g, color.b);
}
/* Hexadecimal colors: #rgb and #rrggbb. */
if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
if (format.length === 4) {
r = (color & 0xf00) >> 4; r = (r >> 4) | r;
g = (color & 0xf0); g = (g >> 4) | g;
b = (color & 0xf); b = (b << 4) | b;
} else if (format.length === 7) {
r = (color & 0xff0000) >> 16;
g = (color & 0xff00) >> 8;
b = (color & 0xff);
}
}
return rgb(r, g, b);
}
function d3_rgb(r, g, b) {
return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b)
: arguments.length < 2 ? (r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b)
: d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
: new d3_rgb(r, g, b);
}
function d3_color() {}
d3_color.prototype.toString = function() {
return this.rgb() + "";
};
var d3_rgbPrototype = d3_rgb.prototype = new d3_color;
d3_rgbPrototype.brighter = function(k) {
k = Math.pow(0.7, arguments.length ? k : 1);
var r = this.r,
g = this.g,
b = this.b,
i = 30;
if (!r && !g && !b) return new d3_rgb(i, i, i);
if (r && r < i) r = i;
if (g && g < i) g = i;
if (b && b < i) b = i;
return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
};
d3_rgbPrototype.darker = function(k) {
k = Math.pow(0.7, arguments.length ? k : 1);
return new d3_rgb(k * this.r, k * this.g, k * this.b);
};
function d3_hsl(h, s, l) {
return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l)
: arguments.length < 2 ? (h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l)
: d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
: new d3_hsl(h, s, l);
}
var d3_hslPrototype = d3_hsl.prototype = new d3_color;
d3_hslPrototype.brighter = function(k) {
k = Math.pow(0.7, arguments.length ? k : 1);
return new d3_hsl(this.h, this.s, this.l / k);
};
d3_hslPrototype.darker = function(k) {
k = Math.pow(0.7, arguments.length ? k : 1);
return new d3_hsl(this.h, this.s, k * this.l);
};
d3_hslPrototype.rgb = function() {
return d3_hsl_rgb(this.h, this.s, this.l);
};
function d3_rgb_hsl(r, g, b) {
var min = Math.min(r /= 255, g /= 255, b /= 255),
max = Math.max(r, g, b),
d = max - min,
h,
s,
l = (max + min) / 2;
if (d) {
s = l < .5 ? d / (max + min) : d / (2 - max - min);
if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
else if (g == max) h = (b - r) / d + 2;
else h = (r - g) / d + 4;
h *= 60;
} else {
h = NaN;
s = l > 0 && l < 1 ? 0 : h;
}
return new d3_hsl(h, s, l);
}
d3_rgbPrototype.hsl = function() {
return d3_rgb_hsl(this.r, this.g, this.b);
};
function d3_rgb_hex(v) {
return v < 0x10
? "0" + Math.max(0, v).toString(16)
: Math.min(255, v).toString(16);
}
d3_rgbPrototype.toString = function() {
return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
};
function d3_rgbNumber(value) {
return new d3_rgb(value >> 16, value >> 8 & 0xff, value & 0xff);
}
function d3_rgbString(value) {
return d3_rgbNumber(value) + "";
}
var d3_category20 = [
0x1f77b4, 0xaec7e8,
0xff7f0e, 0xffbb78,
0x2ca02c, 0x98df8a,
0xd62728, 0xff9896,
0x9467bd, 0xc5b0d5,
0x8c564b, 0xc49c94,
0xe377c2, 0xf7b6d2,
0x7f7f7f, 0xc7c7c7,
0xbcbd22, 0xdbdb8d,
0x17becf, 0x9edae5
].map(d3_rgbString);
var d3$scale$ordinal;
function d3_scaleExtent(domain) {
var start = domain[0], stop = domain[domain.length - 1];
return start < stop ? [start, stop] : [stop, start];
}
var d3$range;
var abs = Math.abs;
function d3_range_integerScale(x) {
var k = 1;
while (x * k % 1) k *= 10;
return k;
}
d3$range = function(start, stop, step) {
if (arguments.length < 3) {
step = 1;
if (arguments.length < 2) {
stop = start;
start = 0;
}
}
if ((stop - start) / step === Infinity) throw new Error("infinite range");
var range = [],
k = d3_range_integerScale(abs(step)),
i = -1,
j;
start *= k, stop *= k, step *= k;
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k);
else while ((j = start + step * ++i) < stop) range.push(j / k);
return range;
};
function d3_scale_ordinal(domain, ranger) {
var index,
range,
rangeBand;
function scale(x) {
return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
}
function steps(start, step) {
return d3$range(domain.length).map(function(i) { return start + step * i; });
}
scale.domain = function(x) {
if (!arguments.length) return domain;
domain = [];
index = new d3_Map;
var i = -1, n = x.length, xi;
while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
return scale[ranger.t].apply(scale, ranger.a);
};
scale.range = function(x) {
if (!arguments.length) return range;
range = x;
rangeBand = 0;
ranger = {t: "range", a: arguments};
return scale;
};
scale.rangePoints = function(x, padding) {
if (arguments.length < 2) padding = 0;
var start = x[0],
stop = x[1],
step = domain.length < 2 ? (start = (start + stop) / 2, 0) : (stop - start) / (domain.length - 1 + padding);
range = steps(start + step * padding / 2, step);
rangeBand = 0;
ranger = {t: "rangePoints", a: arguments};
return scale;
};
scale.rangeRoundPoints = function(x, padding) {
if (arguments.length < 2) padding = 0;
var start = x[0],
stop = x[1],
step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), 0) : (stop - start) / (domain.length - 1 + padding) | 0; // bitwise floor for symmetry
range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
rangeBand = 0;
ranger = {t: "rangeRoundPoints", a: arguments};
return scale;
};
scale.rangeBands = function(x, padding, outerPadding) {
if (arguments.length < 2) padding = 0;
if (arguments.length < 3) outerPadding = padding;
var reverse = x[1] < x[0],
start = x[reverse - 0],
stop = x[1 - reverse],
step = (stop - start) / (domain.length - padding + 2 * outerPadding);
range = steps(start + step * outerPadding, step);
if (reverse) range.reverse();
rangeBand = step * (1 - padding);
ranger = {t: "rangeBands", a: arguments};
return scale;
};
scale.rangeRoundBands = function(x, padding, outerPadding) {
if (arguments.length < 2) padding = 0;
if (arguments.length < 3) outerPadding = padding;
var reverse = x[1] < x[0],
start = x[reverse - 0],
stop = x[1 - reverse],
step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
if (reverse) range.reverse();
rangeBand = Math.round(step * (1 - padding));
ranger = {t: "rangeRoundBands", a: arguments};
return scale;
};
scale.rangeBand = function() {
return rangeBand;
};
scale.rangeExtent = function() {
return d3_scaleExtent(ranger.a[0]);
};
scale.copy = function() {
return d3_scale_ordinal(domain, ranger);
};
return scale.domain(domain);
}
d3$scale$ordinal = function() {
return d3_scale_ordinal([], {t: "range", a: [[]]});
};
d3$scale$category20 = function() {
return d3$scale$ordinal().range(d3_category20);
};
var color = d3$scale$category20();
var d3$layout$force;
var d3$rebind;// Method is assumed to be a standard D3 getter-setter:
// If passed with no arguments, gets the value.
// If passed with arguments, sets the value and returns the target.
function d3_rebind(target, source, method) {
return function() {
var value = method.apply(source, arguments);
return value === source ? target : value;
};
}// Copies a variable number of methods from source to target.
d3$rebind = function(target, source) {
var i = 1, n = arguments.length, method;
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
return target;
};
function d3_layout_forceMouseout(d) {
d.fixed &= ~4; // unset bit 3
}
function d3_layout_forceMouseover(d) {
d.fixed |= 4; // set bit 3
d.px = d.x, d.py = d.y; // set velocity to zero
}
function d3_layout_forceDragend(d) {
d.fixed &= ~6; // unset bits 2 and 3
}// The fixed property has three bits:
// Bit 1 can be set externally (e.g., d.fixed = true) and show persist.
// Bit 2 stores the dragging state, from mousedown to mouseup.
// Bit 3 stores the hover state, from mouseover to mouseout.
// Dragend is a special case: it also clears the hover state.
function d3_layout_forceDragstart(d) {
d.fixed |= 2; // set bit 2
}
function d3_identity(d) {
return d;
}
var d3$behavior$drag;
function d3_eventPreventDefault() {
window.d3_event.preventDefault();
}
var d3_event_dragSelect,
d3_event_dragId = 0;
function d3_event_dragSuppress(node) {
var name = ".dragsuppress-" + ++d3_event_dragId,
click = "click" + name,
w = d3$select(d3_window(node))
.on("touchmove" + name, d3_eventPreventDefault)
.on("dragstart" + name, d3_eventPreventDefault)
.on("selectstart" + name, d3_eventPreventDefault);
if (d3_event_dragSelect == null) {
d3_event_dragSelect = "onselectstart" in node ? false
: d3_vendorSymbol(node.style, "userSelect");
}
if (d3_event_dragSelect) {
var style = d3_documentElement(node).style,
select = style[d3_event_dragSelect];
style[d3_event_dragSelect] = "none";
}
return function(suppressClick) {
w.on(name, null);
if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
if (suppressClick) { // suppress the next click, but only if it’s immediate
var off = function() { w.on(click, null); };
w.on(click, function() { d3_eventPreventDefault(); off(); }, true);
setTimeout(off, 0);
}
};
}
var d3$touch;// https://bugs.webkit.org/show_bug.cgi?id=44083
var d3_mouse_bug44083 = window.navigator && /WebKit/.test(window.navigator.userAgent) ? -1 : 0;
function d3_mousePoint(container, e) {
if (e.changedTouches) e = e.changedTouches[0];
var svg = container.ownerSVGElement || container;
if (svg.createSVGPoint) {
var point = svg.createSVGPoint();
if (d3_mouse_bug44083 < 0) {
var window = d3_window(container);
if (window.scrollX || window.scrollY) {
svg = d3$select("body").append("svg").style({
position: "absolute",
top: 0,
left: 0,
margin: 0,
padding: 0,
border: "none"
}, "important");
var ctm = svg[0][0].getScreenCTM();
d3_mouse_bug44083 = !(ctm.f || ctm.e);
svg.remove();
}
}
if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY;
else point.x = e.clientX, point.y = e.clientY;
point = point.matrixTransform(container.getScreenCTM().inverse());
return [point.x, point.y];
}
var rect = container.getBoundingClientRect();
return [e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop];
}
function d3_eventSource() {
var e = window.d3_event, s;
while (s = e.sourceEvent) e = s;
return e;
}
d3$touch = function(container, touches, identifier) {
if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
if ((touch = touches[i]).identifier === identifier) {
return d3_mousePoint(container, touch);
}
}
};// While it is possible to receive a touchstart event with more than one changed
// touch, the event is only shared by touches on the same target; for new
// touches targetting different elements, multiple touchstart events are
// received even when the touches start simultaneously. Since multiple touches
// cannot move the same target to different locations concurrently without
// tearing the fabric of spacetime, we allow the first touch to win.
function d3_behavior_dragTouchId() {
return window.d3_event.changedTouches[0].identifier;
}
var d3$mouse;
d3$mouse = function(container) {
return d3_mousePoint(container, d3_eventSource());
};
function d3_dispatch_event(dispatch) {
var listeners = [],
listenerByName = new d3_Map;
function event() {
var z = listeners, // defensive reference
i = -1,
n = z.length,
l;
while (++i < n) if (l = z[i].on) l.apply(this, arguments);
return dispatch;
}
event.on = function(name, listener) {
var l = listenerByName.get(name),
i;
// return the current listener, if any
if (arguments.length < 2) return l && l.on;
// remove the old listener, if any (with copy-on-write)
if (l) {
l.on = null;
listeners = listeners.slice(0, i =