1 | (function (global, factory) {
|
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
3 | typeof define === 'function' && define.amd ? define(factory) :
|
4 | (global = global || self, global.controls = factory());
|
5 | }(this, (function () { 'use strict';
|
6 |
|
7 | var xhtml = "http://www.w3.org/1999/xhtml";
|
8 |
|
9 | var namespaces = {
|
10 | svg: "http://www.w3.org/2000/svg",
|
11 | xhtml: xhtml,
|
12 | xlink: "http://www.w3.org/1999/xlink",
|
13 | xml: "http://www.w3.org/XML/1998/namespace",
|
14 | xmlns: "http://www.w3.org/2000/xmlns/"
|
15 | };
|
16 |
|
17 | function namespace(name) {
|
18 | var prefix = name += "", i = prefix.indexOf(":");
|
19 | if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
|
20 | return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
|
21 | }
|
22 |
|
23 | function creatorInherit(name) {
|
24 | return function() {
|
25 | var document = this.ownerDocument,
|
26 | uri = this.namespaceURI;
|
27 | return uri === xhtml && document.documentElement.namespaceURI === xhtml
|
28 | ? document.createElement(name)
|
29 | : document.createElementNS(uri, name);
|
30 | };
|
31 | }
|
32 |
|
33 | function creatorFixed(fullname) {
|
34 | return function() {
|
35 | return this.ownerDocument.createElementNS(fullname.space, fullname.local);
|
36 | };
|
37 | }
|
38 |
|
39 | function creator(name) {
|
40 | var fullname = namespace(name);
|
41 | return (fullname.local
|
42 | ? creatorFixed
|
43 | : creatorInherit)(fullname);
|
44 | }
|
45 |
|
46 | function none() {}
|
47 |
|
48 | function selector(selector) {
|
49 | return selector == null ? none : function() {
|
50 | return this.querySelector(selector);
|
51 | };
|
52 | }
|
53 |
|
54 | function selection_select(select) {
|
55 | if (typeof select !== "function") select = selector(select);
|
56 |
|
57 | for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
|
58 | for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
|
59 | if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
|
60 | if ("__data__" in node) subnode.__data__ = node.__data__;
|
61 | subgroup[i] = subnode;
|
62 | }
|
63 | }
|
64 | }
|
65 |
|
66 | return new Selection(subgroups, this._parents);
|
67 | }
|
68 |
|
69 | function empty() {
|
70 | return [];
|
71 | }
|
72 |
|
73 | function selectorAll(selector) {
|
74 | return selector == null ? empty : function() {
|
75 | return this.querySelectorAll(selector);
|
76 | };
|
77 | }
|
78 |
|
79 | function selection_selectAll(select) {
|
80 | if (typeof select !== "function") select = selectorAll(select);
|
81 |
|
82 | for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
|
83 | for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
|
84 | if (node = group[i]) {
|
85 | subgroups.push(select.call(node, node.__data__, i, group));
|
86 | parents.push(node);
|
87 | }
|
88 | }
|
89 | }
|
90 |
|
91 | return new Selection(subgroups, parents);
|
92 | }
|
93 |
|
94 | function matcher(selector) {
|
95 | return function() {
|
96 | return this.matches(selector);
|
97 | };
|
98 | }
|
99 |
|
100 | function selection_filter(match) {
|
101 | if (typeof match !== "function") match = matcher(match);
|
102 |
|
103 | for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
|
104 | for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
|
105 | if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
|
106 | subgroup.push(node);
|
107 | }
|
108 | }
|
109 | }
|
110 |
|
111 | return new Selection(subgroups, this._parents);
|
112 | }
|
113 |
|
114 | function sparse(update) {
|
115 | return new Array(update.length);
|
116 | }
|
117 |
|
118 | function selection_enter() {
|
119 | return new Selection(this._enter || this._groups.map(sparse), this._parents);
|
120 | }
|
121 |
|
122 | function EnterNode(parent, datum) {
|
123 | this.ownerDocument = parent.ownerDocument;
|
124 | this.namespaceURI = parent.namespaceURI;
|
125 | this._next = null;
|
126 | this._parent = parent;
|
127 | this.__data__ = datum;
|
128 | }
|
129 |
|
130 | EnterNode.prototype = {
|
131 | constructor: EnterNode,
|
132 | appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
|
133 | insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
|
134 | querySelector: function(selector) { return this._parent.querySelector(selector); },
|
135 | querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
|
136 | };
|
137 |
|
138 | function constant(x) {
|
139 | return function() {
|
140 | return x;
|
141 | };
|
142 | }
|
143 |
|
144 | var keyPrefix = "$";
|
145 |
|
146 | function bindIndex(parent, group, enter, update, exit, data) {
|
147 | var i = 0,
|
148 | node,
|
149 | groupLength = group.length,
|
150 | dataLength = data.length;
|
151 |
|
152 |
|
153 |
|
154 |
|
155 | for (; i < dataLength; ++i) {
|
156 | if (node = group[i]) {
|
157 | node.__data__ = data[i];
|
158 | update[i] = node;
|
159 | } else {
|
160 | enter[i] = new EnterNode(parent, data[i]);
|
161 | }
|
162 | }
|
163 |
|
164 |
|
165 | for (; i < groupLength; ++i) {
|
166 | if (node = group[i]) {
|
167 | exit[i] = node;
|
168 | }
|
169 | }
|
170 | }
|
171 |
|
172 | function bindKey(parent, group, enter, update, exit, data, key) {
|
173 | var i,
|
174 | node,
|
175 | nodeByKeyValue = {},
|
176 | groupLength = group.length,
|
177 | dataLength = data.length,
|
178 | keyValues = new Array(groupLength),
|
179 | keyValue;
|
180 |
|
181 |
|
182 |
|
183 | for (i = 0; i < groupLength; ++i) {
|
184 | if (node = group[i]) {
|
185 | keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
|
186 | if (keyValue in nodeByKeyValue) {
|
187 | exit[i] = node;
|
188 | } else {
|
189 | nodeByKeyValue[keyValue] = node;
|
190 | }
|
191 | }
|
192 | }
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | for (i = 0; i < dataLength; ++i) {
|
198 | keyValue = keyPrefix + key.call(parent, data[i], i, data);
|
199 | if (node = nodeByKeyValue[keyValue]) {
|
200 | update[i] = node;
|
201 | node.__data__ = data[i];
|
202 | nodeByKeyValue[keyValue] = null;
|
203 | } else {
|
204 | enter[i] = new EnterNode(parent, data[i]);
|
205 | }
|
206 | }
|
207 |
|
208 |
|
209 | for (i = 0; i < groupLength; ++i) {
|
210 | if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
|
211 | exit[i] = node;
|
212 | }
|
213 | }
|
214 | }
|
215 |
|
216 | function selection_data(value, key) {
|
217 | if (!value) {
|
218 | data = new Array(this.size()), j = -1;
|
219 | this.each(function(d) { data[++j] = d; });
|
220 | return data;
|
221 | }
|
222 |
|
223 | var bind = key ? bindKey : bindIndex,
|
224 | parents = this._parents,
|
225 | groups = this._groups;
|
226 |
|
227 | if (typeof value !== "function") value = constant(value);
|
228 |
|
229 | for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
|
230 | var parent = parents[j],
|
231 | group = groups[j],
|
232 | groupLength = group.length,
|
233 | data = value.call(parent, parent && parent.__data__, j, parents),
|
234 | dataLength = data.length,
|
235 | enterGroup = enter[j] = new Array(dataLength),
|
236 | updateGroup = update[j] = new Array(dataLength),
|
237 | exitGroup = exit[j] = new Array(groupLength);
|
238 |
|
239 | bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
|
240 |
|
241 |
|
242 |
|
243 |
|
244 | for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
|
245 | if (previous = enterGroup[i0]) {
|
246 | if (i0 >= i1) i1 = i0 + 1;
|
247 | while (!(next = updateGroup[i1]) && ++i1 < dataLength);
|
248 | previous._next = next || null;
|
249 | }
|
250 | }
|
251 | }
|
252 |
|
253 | update = new Selection(update, parents);
|
254 | update._enter = enter;
|
255 | update._exit = exit;
|
256 | return update;
|
257 | }
|
258 |
|
259 | function selection_exit() {
|
260 | return new Selection(this._exit || this._groups.map(sparse), this._parents);
|
261 | }
|
262 |
|
263 | function selection_join(onenter, onupdate, onexit) {
|
264 | var enter = this.enter(), update = this, exit = this.exit();
|
265 | enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
|
266 | if (onupdate != null) update = onupdate(update);
|
267 | if (onexit == null) exit.remove(); else onexit(exit);
|
268 | return enter && update ? enter.merge(update).order() : update;
|
269 | }
|
270 |
|
271 | function selection_merge(selection) {
|
272 |
|
273 | for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
|
274 | for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
|
275 | if (node = group0[i] || group1[i]) {
|
276 | merge[i] = node;
|
277 | }
|
278 | }
|
279 | }
|
280 |
|
281 | for (; j < m0; ++j) {
|
282 | merges[j] = groups0[j];
|
283 | }
|
284 |
|
285 | return new Selection(merges, this._parents);
|
286 | }
|
287 |
|
288 | function selection_order() {
|
289 |
|
290 | for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
|
291 | for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
|
292 | if (node = group[i]) {
|
293 | if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
|
294 | next = node;
|
295 | }
|
296 | }
|
297 | }
|
298 |
|
299 | return this;
|
300 | }
|
301 |
|
302 | function selection_sort(compare) {
|
303 | if (!compare) compare = ascending;
|
304 |
|
305 | function compareNode(a, b) {
|
306 | return a && b ? compare(a.__data__, b.__data__) : !a - !b;
|
307 | }
|
308 |
|
309 | for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
|
310 | for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
|
311 | if (node = group[i]) {
|
312 | sortgroup[i] = node;
|
313 | }
|
314 | }
|
315 | sortgroup.sort(compareNode);
|
316 | }
|
317 |
|
318 | return new Selection(sortgroups, this._parents).order();
|
319 | }
|
320 |
|
321 | function ascending(a, b) {
|
322 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
323 | }
|
324 |
|
325 | function selection_call() {
|
326 | var callback = arguments[0];
|
327 | arguments[0] = this;
|
328 | callback.apply(null, arguments);
|
329 | return this;
|
330 | }
|
331 |
|
332 | function selection_nodes() {
|
333 | var nodes = new Array(this.size()), i = -1;
|
334 | this.each(function() { nodes[++i] = this; });
|
335 | return nodes;
|
336 | }
|
337 |
|
338 | function selection_node() {
|
339 |
|
340 | for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
|
341 | for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
|
342 | var node = group[i];
|
343 | if (node) return node;
|
344 | }
|
345 | }
|
346 |
|
347 | return null;
|
348 | }
|
349 |
|
350 | function selection_size() {
|
351 | var size = 0;
|
352 | this.each(function() { ++size; });
|
353 | return size;
|
354 | }
|
355 |
|
356 | function selection_empty() {
|
357 | return !this.node();
|
358 | }
|
359 |
|
360 | function selection_each(callback) {
|
361 |
|
362 | for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
|
363 | for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
|
364 | if (node = group[i]) callback.call(node, node.__data__, i, group);
|
365 | }
|
366 | }
|
367 |
|
368 | return this;
|
369 | }
|
370 |
|
371 | function attrRemove(name) {
|
372 | return function() {
|
373 | this.removeAttribute(name);
|
374 | };
|
375 | }
|
376 |
|
377 | function attrRemoveNS(fullname) {
|
378 | return function() {
|
379 | this.removeAttributeNS(fullname.space, fullname.local);
|
380 | };
|
381 | }
|
382 |
|
383 | function attrConstant(name, value) {
|
384 | return function() {
|
385 | this.setAttribute(name, value);
|
386 | };
|
387 | }
|
388 |
|
389 | function attrConstantNS(fullname, value) {
|
390 | return function() {
|
391 | this.setAttributeNS(fullname.space, fullname.local, value);
|
392 | };
|
393 | }
|
394 |
|
395 | function attrFunction(name, value) {
|
396 | return function() {
|
397 | var v = value.apply(this, arguments);
|
398 | if (v == null) this.removeAttribute(name);
|
399 | else this.setAttribute(name, v);
|
400 | };
|
401 | }
|
402 |
|
403 | function attrFunctionNS(fullname, value) {
|
404 | return function() {
|
405 | var v = value.apply(this, arguments);
|
406 | if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
|
407 | else this.setAttributeNS(fullname.space, fullname.local, v);
|
408 | };
|
409 | }
|
410 |
|
411 | function selection_attr(name, value) {
|
412 | var fullname = namespace(name);
|
413 |
|
414 | if (arguments.length < 2) {
|
415 | var node = this.node();
|
416 | return fullname.local
|
417 | ? node.getAttributeNS(fullname.space, fullname.local)
|
418 | : node.getAttribute(fullname);
|
419 | }
|
420 |
|
421 | return this.each((value == null
|
422 | ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
|
423 | ? (fullname.local ? attrFunctionNS : attrFunction)
|
424 | : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
|
425 | }
|
426 |
|
427 | function defaultView(node) {
|
428 | return (node.ownerDocument && node.ownerDocument.defaultView)
|
429 | || (node.document && node)
|
430 | || node.defaultView;
|
431 | }
|
432 |
|
433 | function styleRemove(name) {
|
434 | return function() {
|
435 | this.style.removeProperty(name);
|
436 | };
|
437 | }
|
438 |
|
439 | function styleConstant(name, value, priority) {
|
440 | return function() {
|
441 | this.style.setProperty(name, value, priority);
|
442 | };
|
443 | }
|
444 |
|
445 | function styleFunction(name, value, priority) {
|
446 | return function() {
|
447 | var v = value.apply(this, arguments);
|
448 | if (v == null) this.style.removeProperty(name);
|
449 | else this.style.setProperty(name, v, priority);
|
450 | };
|
451 | }
|
452 |
|
453 | function selection_style(name, value, priority) {
|
454 | return arguments.length > 1
|
455 | ? this.each((value == null
|
456 | ? styleRemove : typeof value === "function"
|
457 | ? styleFunction
|
458 | : styleConstant)(name, value, priority == null ? "" : priority))
|
459 | : styleValue(this.node(), name);
|
460 | }
|
461 |
|
462 | function styleValue(node, name) {
|
463 | return node.style.getPropertyValue(name)
|
464 | || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
|
465 | }
|
466 |
|
467 | function propertyRemove(name) {
|
468 | return function() {
|
469 | delete this[name];
|
470 | };
|
471 | }
|
472 |
|
473 | function propertyConstant(name, value) {
|
474 | return function() {
|
475 | this[name] = value;
|
476 | };
|
477 | }
|
478 |
|
479 | function propertyFunction(name, value) {
|
480 | return function() {
|
481 | var v = value.apply(this, arguments);
|
482 | if (v == null) delete this[name];
|
483 | else this[name] = v;
|
484 | };
|
485 | }
|
486 |
|
487 | function selection_property(name, value) {
|
488 | return arguments.length > 1
|
489 | ? this.each((value == null
|
490 | ? propertyRemove : typeof value === "function"
|
491 | ? propertyFunction
|
492 | : propertyConstant)(name, value))
|
493 | : this.node()[name];
|
494 | }
|
495 |
|
496 | function classArray(string) {
|
497 | return string.trim().split(/^|\s+/);
|
498 | }
|
499 |
|
500 | function classList(node) {
|
501 | return node.classList || new ClassList(node);
|
502 | }
|
503 |
|
504 | function ClassList(node) {
|
505 | this._node = node;
|
506 | this._names = classArray(node.getAttribute("class") || "");
|
507 | }
|
508 |
|
509 | ClassList.prototype = {
|
510 | add: function(name) {
|
511 | var i = this._names.indexOf(name);
|
512 | if (i < 0) {
|
513 | this._names.push(name);
|
514 | this._node.setAttribute("class", this._names.join(" "));
|
515 | }
|
516 | },
|
517 | remove: function(name) {
|
518 | var i = this._names.indexOf(name);
|
519 | if (i >= 0) {
|
520 | this._names.splice(i, 1);
|
521 | this._node.setAttribute("class", this._names.join(" "));
|
522 | }
|
523 | },
|
524 | contains: function(name) {
|
525 | return this._names.indexOf(name) >= 0;
|
526 | }
|
527 | };
|
528 |
|
529 | function classedAdd(node, names) {
|
530 | var list = classList(node), i = -1, n = names.length;
|
531 | while (++i < n) list.add(names[i]);
|
532 | }
|
533 |
|
534 | function classedRemove(node, names) {
|
535 | var list = classList(node), i = -1, n = names.length;
|
536 | while (++i < n) list.remove(names[i]);
|
537 | }
|
538 |
|
539 | function classedTrue(names) {
|
540 | return function() {
|
541 | classedAdd(this, names);
|
542 | };
|
543 | }
|
544 |
|
545 | function classedFalse(names) {
|
546 | return function() {
|
547 | classedRemove(this, names);
|
548 | };
|
549 | }
|
550 |
|
551 | function classedFunction(names, value) {
|
552 | return function() {
|
553 | (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
|
554 | };
|
555 | }
|
556 |
|
557 | function selection_classed(name, value) {
|
558 | var names = classArray(name + "");
|
559 |
|
560 | if (arguments.length < 2) {
|
561 | var list = classList(this.node()), i = -1, n = names.length;
|
562 | while (++i < n) if (!list.contains(names[i])) return false;
|
563 | return true;
|
564 | }
|
565 |
|
566 | return this.each((typeof value === "function"
|
567 | ? classedFunction : value
|
568 | ? classedTrue
|
569 | : classedFalse)(names, value));
|
570 | }
|
571 |
|
572 | function textRemove() {
|
573 | this.textContent = "";
|
574 | }
|
575 |
|
576 | function textConstant(value) {
|
577 | return function() {
|
578 | this.textContent = value;
|
579 | };
|
580 | }
|
581 |
|
582 | function textFunction(value) {
|
583 | return function() {
|
584 | var v = value.apply(this, arguments);
|
585 | this.textContent = v == null ? "" : v;
|
586 | };
|
587 | }
|
588 |
|
589 | function selection_text(value) {
|
590 | return arguments.length
|
591 | ? this.each(value == null
|
592 | ? textRemove : (typeof value === "function"
|
593 | ? textFunction
|
594 | : textConstant)(value))
|
595 | : this.node().textContent;
|
596 | }
|
597 |
|
598 | function htmlRemove() {
|
599 | this.innerHTML = "";
|
600 | }
|
601 |
|
602 | function htmlConstant(value) {
|
603 | return function() {
|
604 | this.innerHTML = value;
|
605 | };
|
606 | }
|
607 |
|
608 | function htmlFunction(value) {
|
609 | return function() {
|
610 | var v = value.apply(this, arguments);
|
611 | this.innerHTML = v == null ? "" : v;
|
612 | };
|
613 | }
|
614 |
|
615 | function selection_html(value) {
|
616 | return arguments.length
|
617 | ? this.each(value == null
|
618 | ? htmlRemove : (typeof value === "function"
|
619 | ? htmlFunction
|
620 | : htmlConstant)(value))
|
621 | : this.node().innerHTML;
|
622 | }
|
623 |
|
624 | function raise() {
|
625 | if (this.nextSibling) this.parentNode.appendChild(this);
|
626 | }
|
627 |
|
628 | function selection_raise() {
|
629 | return this.each(raise);
|
630 | }
|
631 |
|
632 | function lower() {
|
633 | if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
|
634 | }
|
635 |
|
636 | function selection_lower() {
|
637 | return this.each(lower);
|
638 | }
|
639 |
|
640 | function selection_append(name) {
|
641 | var create = typeof name === "function" ? name : creator(name);
|
642 | return this.select(function() {
|
643 | return this.appendChild(create.apply(this, arguments));
|
644 | });
|
645 | }
|
646 |
|
647 | function constantNull() {
|
648 | return null;
|
649 | }
|
650 |
|
651 | function selection_insert(name, before) {
|
652 | var create = typeof name === "function" ? name : creator(name),
|
653 | select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
|
654 | return this.select(function() {
|
655 | return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
|
656 | });
|
657 | }
|
658 |
|
659 | function remove() {
|
660 | var parent = this.parentNode;
|
661 | if (parent) parent.removeChild(this);
|
662 | }
|
663 |
|
664 | function selection_remove() {
|
665 | return this.each(remove);
|
666 | }
|
667 |
|
668 | function selection_cloneShallow() {
|
669 | return this.parentNode.insertBefore(this.cloneNode(false), this.nextSibling);
|
670 | }
|
671 |
|
672 | function selection_cloneDeep() {
|
673 | return this.parentNode.insertBefore(this.cloneNode(true), this.nextSibling);
|
674 | }
|
675 |
|
676 | function selection_clone(deep) {
|
677 | return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
|
678 | }
|
679 |
|
680 | function selection_datum(value) {
|
681 | return arguments.length
|
682 | ? this.property("__data__", value)
|
683 | : this.node().__data__;
|
684 | }
|
685 |
|
686 | var filterEvents = {};
|
687 |
|
688 | var event$1 = null;
|
689 |
|
690 | if (typeof document !== "undefined") {
|
691 | var element = document.documentElement;
|
692 | if (!("onmouseenter" in element)) {
|
693 | filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
|
694 | }
|
695 | }
|
696 |
|
697 | function filterContextListener(listener, index, group) {
|
698 | listener = contextListener(listener, index, group);
|
699 | return function(event) {
|
700 | var related = event.relatedTarget;
|
701 | if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
|
702 | listener.call(this, event);
|
703 | }
|
704 | };
|
705 | }
|
706 |
|
707 | function contextListener(listener, index, group) {
|
708 | return function(event1) {
|
709 | var event0 = event$1;
|
710 | event$1 = event1;
|
711 | try {
|
712 | listener.call(this, this.__data__, index, group);
|
713 | } finally {
|
714 | event$1 = event0;
|
715 | }
|
716 | };
|
717 | }
|
718 |
|
719 | function parseTypenames(typenames) {
|
720 | return typenames.trim().split(/^|\s+/).map(function(t) {
|
721 | var name = "", i = t.indexOf(".");
|
722 | if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
|
723 | return {type: t, name: name};
|
724 | });
|
725 | }
|
726 |
|
727 | function onRemove(typename) {
|
728 | return function() {
|
729 | var on = this.__on;
|
730 | if (!on) return;
|
731 | for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
|
732 | if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
|
733 | this.removeEventListener(o.type, o.listener, o.capture);
|
734 | } else {
|
735 | on[++i] = o;
|
736 | }
|
737 | }
|
738 | if (++i) on.length = i;
|
739 | else delete this.__on;
|
740 | };
|
741 | }
|
742 |
|
743 | function onAdd(typename, value, capture) {
|
744 | var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
|
745 | return function(d, i, group) {
|
746 | var on = this.__on, o, listener = wrap(value, i, group);
|
747 | if (on) for (var j = 0, m = on.length; j < m; ++j) {
|
748 | if ((o = on[j]).type === typename.type && o.name === typename.name) {
|
749 | this.removeEventListener(o.type, o.listener, o.capture);
|
750 | this.addEventListener(o.type, o.listener = listener, o.capture = capture);
|
751 | o.value = value;
|
752 | return;
|
753 | }
|
754 | }
|
755 | this.addEventListener(typename.type, listener, capture);
|
756 | o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
|
757 | if (!on) this.__on = [o];
|
758 | else on.push(o);
|
759 | };
|
760 | }
|
761 |
|
762 | function selection_on(typename, value, capture) {
|
763 | var typenames = parseTypenames(typename + ""), i, n = typenames.length, t;
|
764 |
|
765 | if (arguments.length < 2) {
|
766 | var on = this.node().__on;
|
767 | if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
|
768 | for (i = 0, o = on[j]; i < n; ++i) {
|
769 | if ((t = typenames[i]).type === o.type && t.name === o.name) {
|
770 | return o.value;
|
771 | }
|
772 | }
|
773 | }
|
774 | return;
|
775 | }
|
776 |
|
777 | on = value ? onAdd : onRemove;
|
778 | if (capture == null) capture = false;
|
779 | for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
|
780 | return this;
|
781 | }
|
782 |
|
783 | function dispatchEvent(node, type, params) {
|
784 | var window = defaultView(node),
|
785 | event = window.CustomEvent;
|
786 |
|
787 | if (typeof event === "function") {
|
788 | event = new event(type, params);
|
789 | } else {
|
790 | event = window.document.createEvent("Event");
|
791 | if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
|
792 | else event.initEvent(type, false, false);
|
793 | }
|
794 |
|
795 | node.dispatchEvent(event);
|
796 | }
|
797 |
|
798 | function dispatchConstant(type, params) {
|
799 | return function() {
|
800 | return dispatchEvent(this, type, params);
|
801 | };
|
802 | }
|
803 |
|
804 | function dispatchFunction(type, params) {
|
805 | return function() {
|
806 | return dispatchEvent(this, type, params.apply(this, arguments));
|
807 | };
|
808 | }
|
809 |
|
810 | function selection_dispatch(type, params) {
|
811 | return this.each((typeof params === "function"
|
812 | ? dispatchFunction
|
813 | : dispatchConstant)(type, params));
|
814 | }
|
815 |
|
816 | var root = [null];
|
817 |
|
818 | function Selection(groups, parents) {
|
819 | this._groups = groups;
|
820 | this._parents = parents;
|
821 | }
|
822 |
|
823 | function selection() {
|
824 | return new Selection([[document.documentElement]], root);
|
825 | }
|
826 |
|
827 | Selection.prototype = selection.prototype = {
|
828 | constructor: Selection,
|
829 | select: selection_select,
|
830 | selectAll: selection_selectAll,
|
831 | filter: selection_filter,
|
832 | data: selection_data,
|
833 | enter: selection_enter,
|
834 | exit: selection_exit,
|
835 | join: selection_join,
|
836 | merge: selection_merge,
|
837 | order: selection_order,
|
838 | sort: selection_sort,
|
839 | call: selection_call,
|
840 | nodes: selection_nodes,
|
841 | node: selection_node,
|
842 | size: selection_size,
|
843 | empty: selection_empty,
|
844 | each: selection_each,
|
845 | attr: selection_attr,
|
846 | style: selection_style,
|
847 | property: selection_property,
|
848 | classed: selection_classed,
|
849 | text: selection_text,
|
850 | html: selection_html,
|
851 | raise: selection_raise,
|
852 | lower: selection_lower,
|
853 | append: selection_append,
|
854 | insert: selection_insert,
|
855 | remove: selection_remove,
|
856 | clone: selection_clone,
|
857 | datum: selection_datum,
|
858 | on: selection_on,
|
859 | dispatch: selection_dispatch
|
860 | };
|
861 |
|
862 | function select(selector) {
|
863 | return typeof selector === "string"
|
864 | ? new Selection([[document.querySelector(selector)]], [document.documentElement])
|
865 | : new Selection([[selector]], root);
|
866 | }
|
867 |
|
868 | function sourceEvent() {
|
869 | var current = event$1, source;
|
870 | while (source = current.sourceEvent) current = source;
|
871 | return current;
|
872 | }
|
873 |
|
874 | function point(node, event) {
|
875 | var svg = node.ownerSVGElement || node;
|
876 |
|
877 | if (svg.createSVGPoint) {
|
878 | var point = svg.createSVGPoint();
|
879 | point.x = event.clientX, point.y = event.clientY;
|
880 | point = point.matrixTransform(node.getScreenCTM().inverse());
|
881 | return [point.x, point.y];
|
882 | }
|
883 |
|
884 | var rect = node.getBoundingClientRect();
|
885 | return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
|
886 | }
|
887 |
|
888 | function d3_mouse(node) {
|
889 | var event = sourceEvent();
|
890 | if (event.changedTouches) event = event.changedTouches[0];
|
891 | return point(node, event);
|
892 | }
|
893 |
|
894 | function ascending$1(a, b) {
|
895 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
896 | }
|
897 |
|
898 | function sortArray(uarr, sort, parser, formatter) {
|
899 | var sarr = uarr.map(function(d, i) {
|
900 | var parsed_value = parser(d);
|
901 | return {
|
902 | value: d,
|
903 | options_index: i,
|
904 | parsed: parsed_value,
|
905 | display: formatter(d)
|
906 | };
|
907 | });
|
908 |
|
909 | if (!sort) return sarr;
|
910 | return sarr.sort(function(a, b) { return ascending$1(a.parsed, b.parsed); });
|
911 | }
|
912 |
|
913 | function Stylesheet() {
|
914 | this.declarations = [];
|
915 | return this;
|
916 | }
|
917 |
|
918 | Stylesheet.prototype.select = function(selector) {
|
919 | if (!selector) return this;
|
920 | var declaration = new Declaration(selector, this);
|
921 | declaration.parent = this;
|
922 | this.addDeclaration(declaration);
|
923 |
|
924 | return declaration;
|
925 | };
|
926 |
|
927 | Stylesheet.prototype.addDeclaration = function(declaration) {
|
928 | this.declarations.push(declaration);
|
929 | return this;
|
930 | };
|
931 |
|
932 | Stylesheet.prototype.print = function() {
|
933 | var text = "";
|
934 | this.declarations.forEach(function(declaration) {
|
935 | text += declaration.selector + " {\n";
|
936 | declaration.styles.forEach(function(style) {
|
937 | text += "\t" + style[0] + ": " + style[1] + ";\n";
|
938 | });
|
939 | text += "}\n\n";
|
940 | });
|
941 | return text;
|
942 | };
|
943 |
|
944 | Stylesheet.prototype.clear = function() {
|
945 | this.declarations = [];
|
946 | return this;
|
947 | };
|
948 |
|
949 | function Declaration(selector) {
|
950 | this.selector = selector;
|
951 | this.styles = [];
|
952 | return this;
|
953 | }
|
954 |
|
955 | Declaration.prototype.style = function(property, _value) {
|
956 | var value = typeof value_ == "function" ? _value() : _value;
|
957 | if (value !== "" && value !== null && value !== undefined) this.styles.push([property, value]);
|
958 | return this;
|
959 | };
|
960 |
|
961 | Declaration.prototype.select = function(selector) {
|
962 | return this.parent.select(this.selector + " " + selector);
|
963 | };
|
964 |
|
965 | function createCssString() {
|
966 | var s = new Stylesheet();
|
967 |
|
968 | s.select(".fl-controls-container")
|
969 | .style("display", "inline-block")
|
970 | .style("line-height", "1em");
|
971 |
|
972 | s.select(".fl-controls-title")
|
973 | .style("display", "inline-block")
|
974 | .style("margin", "0px 0.5em 0px 0px");
|
975 |
|
976 | s.select(".fl-controls-container, .fl-controls-container *")
|
977 | .style("box-sizing", "border-box");
|
978 |
|
979 | s.select(".slider-holder")
|
980 | .style("margin-bottom", "20px");
|
981 |
|
982 | s.select(".fl-controls-slider, .slider-play")
|
983 | .style("pointer-events", "all")
|
984 | .style("display", "inline-block")
|
985 | .style("vertical-align", "middle");
|
986 |
|
987 | s.select(".slider-play svg")
|
988 | .style("height", "100%")
|
989 | .style("width", "100%")
|
990 | .style("cursor", " pointer", "");
|
991 |
|
992 | s.select(".slider-play:hover")
|
993 | .style("opacity", "0.6");
|
994 |
|
995 | s.select(".fl-control-slider")
|
996 | .style("width", "100%")
|
997 | .style("bottom", "0");
|
998 |
|
999 | s.select(".fl-control")
|
1000 | .style("position", "relative");
|
1001 |
|
1002 | s.select(".fl-control.hidden")
|
1003 | .style("display", "none");
|
1004 |
|
1005 | s.select(".fl-control .button")
|
1006 | .style("display", "inline-block")
|
1007 | .style("background", "#eee")
|
1008 | .style("padding", "0.5em")
|
1009 | .style("margin-right", "0.25em")
|
1010 | .style("margin-bottom", "0.25em")
|
1011 | .style("line-height", "1em");
|
1012 |
|
1013 | s.select(".fl-control.grouped:not(.hidden)")
|
1014 | .style("display", "inline-table")
|
1015 | .style("table-layout", "fixed")
|
1016 | .select(".button")
|
1017 | .style("display", "table-cell")
|
1018 | .style("margin", "0")
|
1019 | .style("text-align", "center");
|
1020 |
|
1021 | s.select(".fl-control .button.selected")
|
1022 | .style("background", "#ddd");
|
1023 |
|
1024 | s.select(".fl-control-dropdown")
|
1025 | .style("line-height", "1em")
|
1026 | .select(".list")
|
1027 | .style("display", "none")
|
1028 | .style("position", "absolute")
|
1029 | .style("background-color", "white")
|
1030 | .style("z-index", "100")
|
1031 | .style("border", "1px solid #eee")
|
1032 | .select(".list-item")
|
1033 | .style("text-align", "start")
|
1034 | .style("cursor", "pointer")
|
1035 | .style("padding", "0.5rem");
|
1036 |
|
1037 | s.select(".fl-control-dropdown.open .list")
|
1038 | .style("display", "block");
|
1039 |
|
1040 | s.select(".fl-control-dropdown .main")
|
1041 | .style("position", "relative")
|
1042 | .style("text-align", "start")
|
1043 | .style("display", "flex")
|
1044 | .style("justify-content", "space-between");
|
1045 |
|
1046 | s.select(".fl-control-dropdown .symbol")
|
1047 | .style("float", "right")
|
1048 | .select("div")
|
1049 | .style("border-top-color", "#333333");
|
1050 |
|
1051 | return s.print();
|
1052 | }
|
1053 |
|
1054 | var css_injected = false;
|
1055 |
|
1056 | function injectCSS() {
|
1057 | if (css_injected || typeof document === "undefined") return;
|
1058 |
|
1059 | var css_string = createCssString();
|
1060 |
|
1061 | var head = document.head || document.getElementsByTagName("head")[0];
|
1062 | var style = document.createElement("style");
|
1063 | style.type = "text/css";
|
1064 | style.className = "flourish-controls";
|
1065 | head.appendChild(style);
|
1066 | if (style.styleSheet) {
|
1067 | style.styleSheet.cssText = css_string;
|
1068 | }
|
1069 | else {
|
1070 | style.appendChild(document.createTextNode(css_string));
|
1071 | }
|
1072 | css_injected = true;
|
1073 | }
|
1074 |
|
1075 | var getTextWidth = (function() {
|
1076 | var context = document.createElement("canvas").getContext("2d");
|
1077 | return function(text, font) {
|
1078 | context.font = font || "10px sans-serif";
|
1079 | var metrics = context.measureText(text);
|
1080 | return metrics.width;
|
1081 | };
|
1082 | })();
|
1083 |
|
1084 | var remToPx;
|
1085 |
|
1086 | function getRemToPx() {
|
1087 | var font_size = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
1088 | remToPx = function (rem) { return rem * font_size; };
|
1089 | }
|
1090 |
|
1091 | var MIN_HEIGHT = 90;
|
1092 | function createDropdown(control_obj, state, container) {
|
1093 | var dropdown_obj = {};
|
1094 | var bounding_container = document.body;
|
1095 |
|
1096 |
|
1097 | var dropdown = select(container).append("div").attr("class", "fl-control fl-control-dropdown");
|
1098 | var dropdown_node = dropdown.node();
|
1099 | var dropdown_main = dropdown.append("div").attr("class", "main");
|
1100 | var dropdown_current = dropdown_main.append("span").attr("class", "current");
|
1101 | dropdown_main.append("span").attr("class", "symbol").style("width", "10px")
|
1102 | .append("div")
|
1103 | .style("border-left", "5px solid transparent")
|
1104 | .style("border-right", "5px solid transparent")
|
1105 | .style("border-bottom", "5px solid transparent")
|
1106 | .style("border-top-style", "solid")
|
1107 | .style("border-top-width", "5px")
|
1108 | .style("top", "50%")
|
1109 | .style("position", "absolute")
|
1110 | .style("margin-top", "-2.5px");
|
1111 | var dropdown_list = dropdown.append("div").attr("class", "list");
|
1112 |
|
1113 | var showDropdownList = function() {
|
1114 | dropdown.classed("open", true);
|
1115 | dropdown_list.style("top", "100%");
|
1116 | dropdown_list.style("bottom", null);
|
1117 | dropdown_list.style("display", null);
|
1118 | dropdown_list.style("overflow", "auto");
|
1119 | var bounding_bb = bounding_container.getBoundingClientRect();
|
1120 | var list_bb = dropdown_list.node().getBoundingClientRect();
|
1121 | var overspill = list_bb.bottom - bounding_bb.bottom;
|
1122 | if (overspill > 0) {
|
1123 | var new_height = bounding_bb.bottom - list_bb.top - 30;
|
1124 | if (new_height > MIN_HEIGHT) dropdown_list.style("max-height", new_height + "px");
|
1125 | else dropdown_list
|
1126 | .style("top", "auto")
|
1127 | .style("bottom", "100%");
|
1128 | }
|
1129 | if (list_bb.right > window.innerWidth) {
|
1130 | dropdown_list.style("right", 0);
|
1131 | }
|
1132 | };
|
1133 |
|
1134 | var hideDropdownList = function() {
|
1135 | dropdown.classed("open", false);
|
1136 | dropdown_list.style("right", null);
|
1137 | dropdown_list.style("max-height", null);
|
1138 | dropdown_list.style("display", "none");
|
1139 | };
|
1140 |
|
1141 | var toggleDropdownList = function() {
|
1142 | if (dropdown.classed("open")) hideDropdownList();
|
1143 | else showDropdownList();
|
1144 | };
|
1145 |
|
1146 | dropdown_main.on("click", function() { toggleDropdownList(); });
|
1147 |
|
1148 | var clickHandler = function() {
|
1149 | if (!dropdown.classed("open")) return;
|
1150 | var el = event.target;
|
1151 | var parent = el.parentElement;
|
1152 | while (parent) {
|
1153 | if (el === dropdown_node) return;
|
1154 | el = parent;
|
1155 | parent = el.parentElement;
|
1156 | }
|
1157 | hideDropdownList();
|
1158 | };
|
1159 |
|
1160 | var showControl = function(longest_text_width) {
|
1161 | var dropdown_width = "100%";
|
1162 | if (state.dropdown_width_mode == "auto") {
|
1163 | dropdown_width = Math.min(longest_text_width + 40, remToPx(20)) + "px";
|
1164 | }
|
1165 | else if (state.dropdown_width_mode == "fixed") {
|
1166 | dropdown_width = remToPx(state.dropdown_width_fixed) + "px";
|
1167 | }
|
1168 | container.style.width = state.dropdown_width_mode == "full" ? dropdown_width : "";
|
1169 | dropdown.style("width", dropdown_width).style("display", state.dropdown_width_mode !== "full" ? "inline-table" : null);
|
1170 | dropdown.select(".main").style("width", dropdown_width);
|
1171 | };
|
1172 |
|
1173 | var hideControl = function() {
|
1174 | hideDropdownList();
|
1175 | dropdown.style("display", "none");
|
1176 | };
|
1177 |
|
1178 |
|
1179 | dropdown_obj.appendedToDOM = function(_bounding_container) {
|
1180 | if (_bounding_container) bounding_container = _bounding_container;
|
1181 | document.querySelector("body").addEventListener("click", clickHandler, false);
|
1182 | return dropdown_obj;
|
1183 | };
|
1184 |
|
1185 |
|
1186 | dropdown_obj.removedFromDOM = function() {
|
1187 | document.querySelector("body").removeEventListener("click", clickHandler);
|
1188 | return dropdown_obj;
|
1189 | };
|
1190 |
|
1191 | dropdown_obj.show = showControl;
|
1192 | dropdown_obj.hide = hideControl;
|
1193 |
|
1194 |
|
1195 | dropdown_obj.update = function(sorted_options) {
|
1196 | dropdown_list.text("");
|
1197 | var dropdown_font_size = window.getComputedStyle(dropdown.node()).fontSize;
|
1198 | if (!control_obj.n_options || state.control_type !== "dropdown") {
|
1199 | hideControl();
|
1200 | return dropdown_obj;
|
1201 | }
|
1202 |
|
1203 | var longest_text = "";
|
1204 | dropdown_list.text("")
|
1205 | .selectAll(".list-item")
|
1206 | .data(sorted_options)
|
1207 | .enter()
|
1208 | .append("div")
|
1209 | .attr("class", "list-item")
|
1210 | .text(function(d) {
|
1211 | if (d.display.length > longest_text.length) longest_text = d.display;
|
1212 | return d.display;
|
1213 | })
|
1214 | .on("click", function(d) {
|
1215 | hideDropdownList();
|
1216 | var i = d.options_index;
|
1217 | if (i === control_obj.index()) return;
|
1218 | control_obj.index(i);
|
1219 | dropdown_current.text(d.display).attr("title", d.display);
|
1220 | control_obj.trigger("change");
|
1221 | });
|
1222 | var longest_text_width = getTextWidth(longest_text, dropdown_font_size + " sans-serif");
|
1223 | var sorted_index = control_obj.getSortedIndex();
|
1224 | var value = sorted_options[sorted_index].display;
|
1225 | dropdown_current.text(value).attr("title", value);
|
1226 |
|
1227 | showControl(longest_text_width);
|
1228 |
|
1229 | return dropdown_obj;
|
1230 | };
|
1231 |
|
1232 |
|
1233 | return dropdown_obj;
|
1234 | }
|
1235 |
|
1236 | function createButtons(control_obj, state, container) {
|
1237 | var button_obj = {};
|
1238 | var button_container = select(container).append("div").attr("class", "fl-control fl-control-buttons");
|
1239 |
|
1240 | var showControl = function() {
|
1241 | button_container.classed("hidden", false);
|
1242 | };
|
1243 |
|
1244 | var hideControl = function() {
|
1245 | button_container.classed("hidden", true);
|
1246 | };
|
1247 |
|
1248 | button_obj.show = showControl;
|
1249 | button_obj.hide = hideControl;
|
1250 |
|
1251 | button_obj.update = function(sorted_options) {
|
1252 | if (!control_obj.n_options || state.control_type !== "buttons") {
|
1253 | hideControl();
|
1254 | return button_obj;
|
1255 | }
|
1256 |
|
1257 | var index = control_obj.index();
|
1258 |
|
1259 | button_container.classed("grouped", state.button_group);
|
1260 | button_container.classed("fixed-width", state.button_group_width_mode == "fixed" || state.button_group_width_mode == "full");
|
1261 | button_container.style("width", state.button_group && state.button_group_width_mode == "fixed" ? remToPx(state.button_group_width_fixed) + "px" : state.button_group_width_mode == "full" ? "100%" : null);
|
1262 |
|
1263 | var clickHandler = function(d) {
|
1264 | var i = d.options_index;
|
1265 | if (i === control_obj.index()) return;
|
1266 | control_obj.index(i);
|
1267 | control_obj.trigger("change");
|
1268 | };
|
1269 |
|
1270 | var buttons = button_container.selectAll(".button")
|
1271 | .data(sorted_options, function(d) { return d.display; });
|
1272 |
|
1273 | var buttons_enter = buttons.enter()
|
1274 | .append("div")
|
1275 | .attr("class", "button")
|
1276 | .style("cursor", "pointer")
|
1277 | .attr("role", "button")
|
1278 | .attr("tabindex", 0)
|
1279 | .on("click", function(d) { clickHandler(d); })
|
1280 | .on("keyup", function(d) {
|
1281 | if (event$1.code === "Space" || event$1.code === "Enter") {
|
1282 | event$1.preventDefault();
|
1283 | clickHandler(d);
|
1284 | }
|
1285 | });
|
1286 |
|
1287 | buttons_enter.append("span")
|
1288 | .text(function(d) { return d.display; });
|
1289 |
|
1290 | showControl();
|
1291 |
|
1292 | buttons.merge(buttons_enter)
|
1293 | .classed("selected", function(d) { return d.options_index === index; })
|
1294 | .attr("aria-pressed", function(d) { return d.options_index === index; });
|
1295 |
|
1296 | buttons.exit().remove();
|
1297 |
|
1298 | showControl();
|
1299 | };
|
1300 |
|
1301 | return button_obj;
|
1302 | }
|
1303 |
|
1304 | var slice = Array.prototype.slice;
|
1305 |
|
1306 | function identity(x) {
|
1307 | return x;
|
1308 | }
|
1309 |
|
1310 | var top = 1,
|
1311 | right = 2,
|
1312 | bottom = 3,
|
1313 | left = 4,
|
1314 | epsilon = 1e-6;
|
1315 |
|
1316 | function translateX(x) {
|
1317 | return "translate(" + (x + 0.5) + ",0)";
|
1318 | }
|
1319 |
|
1320 | function translateY(y) {
|
1321 | return "translate(0," + (y + 0.5) + ")";
|
1322 | }
|
1323 |
|
1324 | function number(scale) {
|
1325 | return function(d) {
|
1326 | return +scale(d);
|
1327 | };
|
1328 | }
|
1329 |
|
1330 | function center(scale) {
|
1331 | var offset = Math.max(0, scale.bandwidth() - 1) / 2;
|
1332 | if (scale.round()) offset = Math.round(offset);
|
1333 | return function(d) {
|
1334 | return +scale(d) + offset;
|
1335 | };
|
1336 | }
|
1337 |
|
1338 | function entering() {
|
1339 | return !this.__axis;
|
1340 | }
|
1341 |
|
1342 | function axis(orient, scale) {
|
1343 | var tickArguments = [],
|
1344 | tickValues = null,
|
1345 | tickFormat = null,
|
1346 | tickSizeInner = 6,
|
1347 | tickSizeOuter = 6,
|
1348 | tickPadding = 3,
|
1349 | k = orient === top || orient === left ? -1 : 1,
|
1350 | x = orient === left || orient === right ? "x" : "y",
|
1351 | transform = orient === top || orient === bottom ? translateX : translateY;
|
1352 |
|
1353 | function axis(context) {
|
1354 | var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
|
1355 | format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity) : tickFormat,
|
1356 | spacing = Math.max(tickSizeInner, 0) + tickPadding,
|
1357 | range = scale.range(),
|
1358 | range0 = +range[0] + 0.5,
|
1359 | range1 = +range[range.length - 1] + 0.5,
|
1360 | position = (scale.bandwidth ? center : number)(scale.copy()),
|
1361 | selection = context.selection ? context.selection() : context,
|
1362 | path = selection.selectAll(".domain").data([null]),
|
1363 | tick = selection.selectAll(".tick").data(values, scale).order(),
|
1364 | tickExit = tick.exit(),
|
1365 | tickEnter = tick.enter().append("g").attr("class", "tick"),
|
1366 | line = tick.select("line"),
|
1367 | text = tick.select("text");
|
1368 |
|
1369 | path = path.merge(path.enter().insert("path", ".tick")
|
1370 | .attr("class", "domain")
|
1371 | .attr("stroke", "currentColor"));
|
1372 |
|
1373 | tick = tick.merge(tickEnter);
|
1374 |
|
1375 | line = line.merge(tickEnter.append("line")
|
1376 | .attr("stroke", "currentColor")
|
1377 | .attr(x + "2", k * tickSizeInner));
|
1378 |
|
1379 | text = text.merge(tickEnter.append("text")
|
1380 | .attr("fill", "currentColor")
|
1381 | .attr(x, k * spacing)
|
1382 | .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
|
1383 |
|
1384 | if (context !== selection) {
|
1385 | path = path.transition(context);
|
1386 | tick = tick.transition(context);
|
1387 | line = line.transition(context);
|
1388 | text = text.transition(context);
|
1389 |
|
1390 | tickExit = tickExit.transition(context)
|
1391 | .attr("opacity", epsilon)
|
1392 | .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); });
|
1393 |
|
1394 | tickEnter
|
1395 | .attr("opacity", epsilon)
|
1396 | .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); });
|
1397 | }
|
1398 |
|
1399 | tickExit.remove();
|
1400 |
|
1401 | path
|
1402 | .attr("d", orient === left || orient == right
|
1403 | ? (tickSizeOuter ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter : "M0.5," + range0 + "V" + range1)
|
1404 | : (tickSizeOuter ? "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter : "M" + range0 + ",0.5H" + range1));
|
1405 |
|
1406 | tick
|
1407 | .attr("opacity", 1)
|
1408 | .attr("transform", function(d) { return transform(position(d)); });
|
1409 |
|
1410 | line
|
1411 | .attr(x + "2", k * tickSizeInner);
|
1412 |
|
1413 | text
|
1414 | .attr(x, k * spacing)
|
1415 | .text(format);
|
1416 |
|
1417 | selection.filter(entering)
|
1418 | .attr("fill", "none")
|
1419 | .attr("font-size", 10)
|
1420 | .attr("font-family", "sans-serif")
|
1421 | .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
|
1422 |
|
1423 | selection
|
1424 | .each(function() { this.__axis = position; });
|
1425 | }
|
1426 |
|
1427 | axis.scale = function(_) {
|
1428 | return arguments.length ? (scale = _, axis) : scale;
|
1429 | };
|
1430 |
|
1431 | axis.ticks = function() {
|
1432 | return tickArguments = slice.call(arguments), axis;
|
1433 | };
|
1434 |
|
1435 | axis.tickArguments = function(_) {
|
1436 | return arguments.length ? (tickArguments = _ == null ? [] : slice.call(_), axis) : tickArguments.slice();
|
1437 | };
|
1438 |
|
1439 | axis.tickValues = function(_) {
|
1440 | return arguments.length ? (tickValues = _ == null ? null : slice.call(_), axis) : tickValues && tickValues.slice();
|
1441 | };
|
1442 |
|
1443 | axis.tickFormat = function(_) {
|
1444 | return arguments.length ? (tickFormat = _, axis) : tickFormat;
|
1445 | };
|
1446 |
|
1447 | axis.tickSize = function(_) {
|
1448 | return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
|
1449 | };
|
1450 |
|
1451 | axis.tickSizeInner = function(_) {
|
1452 | return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
|
1453 | };
|
1454 |
|
1455 | axis.tickSizeOuter = function(_) {
|
1456 | return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
|
1457 | };
|
1458 |
|
1459 | axis.tickPadding = function(_) {
|
1460 | return arguments.length ? (tickPadding = +_, axis) : tickPadding;
|
1461 | };
|
1462 |
|
1463 | return axis;
|
1464 | }
|
1465 |
|
1466 | function axisBottom(scale) {
|
1467 | return axis(bottom, scale);
|
1468 | }
|
1469 |
|
1470 | function ascending$2(a, b) {
|
1471 | return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
|
1472 | }
|
1473 |
|
1474 | function bisector(compare) {
|
1475 | if (compare.length === 1) compare = ascendingComparator(compare);
|
1476 | return {
|
1477 | left: function(a, x, lo, hi) {
|
1478 | if (lo == null) lo = 0;
|
1479 | if (hi == null) hi = a.length;
|
1480 | while (lo < hi) {
|
1481 | var mid = lo + hi >>> 1;
|
1482 | if (compare(a[mid], x) < 0) lo = mid + 1;
|
1483 | else hi = mid;
|
1484 | }
|
1485 | return lo;
|
1486 | },
|
1487 | right: function(a, x, lo, hi) {
|
1488 | if (lo == null) lo = 0;
|
1489 | if (hi == null) hi = a.length;
|
1490 | while (lo < hi) {
|
1491 | var mid = lo + hi >>> 1;
|
1492 | if (compare(a[mid], x) > 0) hi = mid;
|
1493 | else lo = mid + 1;
|
1494 | }
|
1495 | return lo;
|
1496 | }
|
1497 | };
|
1498 | }
|
1499 |
|
1500 | function ascendingComparator(f) {
|
1501 | return function(d, x) {
|
1502 | return ascending$2(f(d), x);
|
1503 | };
|
1504 | }
|
1505 |
|
1506 | var ascendingBisect = bisector(ascending$2);
|
1507 | var bisectRight = ascendingBisect.right;
|
1508 |
|
1509 | var e10 = Math.sqrt(50),
|
1510 | e5 = Math.sqrt(10),
|
1511 | e2 = Math.sqrt(2);
|
1512 |
|
1513 | function ticks(start, stop, count) {
|
1514 | var reverse,
|
1515 | i = -1,
|
1516 | n,
|
1517 | ticks,
|
1518 | step;
|
1519 |
|
1520 | stop = +stop, start = +start, count = +count;
|
1521 | if (start === stop && count > 0) return [start];
|
1522 | if (reverse = stop < start) n = start, start = stop, stop = n;
|
1523 | if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
|
1524 |
|
1525 | if (step > 0) {
|
1526 | start = Math.ceil(start / step);
|
1527 | stop = Math.floor(stop / step);
|
1528 | ticks = new Array(n = Math.ceil(stop - start + 1));
|
1529 | while (++i < n) ticks[i] = (start + i) * step;
|
1530 | } else {
|
1531 | start = Math.floor(start * step);
|
1532 | stop = Math.ceil(stop * step);
|
1533 | ticks = new Array(n = Math.ceil(start - stop + 1));
|
1534 | while (++i < n) ticks[i] = (start - i) / step;
|
1535 | }
|
1536 |
|
1537 | if (reverse) ticks.reverse();
|
1538 |
|
1539 | return ticks;
|
1540 | }
|
1541 |
|
1542 | function tickIncrement(start, stop, count) {
|
1543 | var step = (stop - start) / Math.max(0, count),
|
1544 | power = Math.floor(Math.log(step) / Math.LN10),
|
1545 | error = step / Math.pow(10, power);
|
1546 | return power >= 0
|
1547 | ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
|
1548 | : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
|
1549 | }
|
1550 |
|
1551 | function tickStep(start, stop, count) {
|
1552 | var step0 = Math.abs(stop - start) / Math.max(0, count),
|
1553 | step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
|
1554 | error = step0 / step1;
|
1555 | if (error >= e10) step1 *= 10;
|
1556 | else if (error >= e5) step1 *= 5;
|
1557 | else if (error >= e2) step1 *= 2;
|
1558 | return stop < start ? -step1 : step1;
|
1559 | }
|
1560 |
|
1561 | function define(constructor, factory, prototype) {
|
1562 | constructor.prototype = factory.prototype = prototype;
|
1563 | prototype.constructor = constructor;
|
1564 | }
|
1565 |
|
1566 | function extend(parent, definition) {
|
1567 | var prototype = Object.create(parent.prototype);
|
1568 | for (var key in definition) prototype[key] = definition[key];
|
1569 | return prototype;
|
1570 | }
|
1571 |
|
1572 | function Color() {}
|
1573 |
|
1574 | var darker = 0.7;
|
1575 | var brighter = 1 / darker;
|
1576 |
|
1577 | var reI = "\\s*([+-]?\\d+)\\s*",
|
1578 | reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
|
1579 | reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
|
1580 | reHex3 = /^#([0-9a-f]{3})$/,
|
1581 | reHex6 = /^#([0-9a-f]{6})$/,
|
1582 | reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
|
1583 | reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
|
1584 | reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
|
1585 | reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
|
1586 | reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
|
1587 | reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
|
1588 |
|
1589 | var named = {
|
1590 | aliceblue: 0xf0f8ff,
|
1591 | antiquewhite: 0xfaebd7,
|
1592 | aqua: 0x00ffff,
|
1593 | aquamarine: 0x7fffd4,
|
1594 | azure: 0xf0ffff,
|
1595 | beige: 0xf5f5dc,
|
1596 | bisque: 0xffe4c4,
|
1597 | black: 0x000000,
|
1598 | blanchedalmond: 0xffebcd,
|
1599 | blue: 0x0000ff,
|
1600 | blueviolet: 0x8a2be2,
|
1601 | brown: 0xa52a2a,
|
1602 | burlywood: 0xdeb887,
|
1603 | cadetblue: 0x5f9ea0,
|
1604 | chartreuse: 0x7fff00,
|
1605 | chocolate: 0xd2691e,
|
1606 | coral: 0xff7f50,
|
1607 | cornflowerblue: 0x6495ed,
|
1608 | cornsilk: 0xfff8dc,
|
1609 | crimson: 0xdc143c,
|
1610 | cyan: 0x00ffff,
|
1611 | darkblue: 0x00008b,
|
1612 | darkcyan: 0x008b8b,
|
1613 | darkgoldenrod: 0xb8860b,
|
1614 | darkgray: 0xa9a9a9,
|
1615 | darkgreen: 0x006400,
|
1616 | darkgrey: 0xa9a9a9,
|
1617 | darkkhaki: 0xbdb76b,
|
1618 | darkmagenta: 0x8b008b,
|
1619 | darkolivegreen: 0x556b2f,
|
1620 | darkorange: 0xff8c00,
|
1621 | darkorchid: 0x9932cc,
|
1622 | darkred: 0x8b0000,
|
1623 | darksalmon: 0xe9967a,
|
1624 | darkseagreen: 0x8fbc8f,
|
1625 | darkslateblue: 0x483d8b,
|
1626 | darkslategray: 0x2f4f4f,
|
1627 | darkslategrey: 0x2f4f4f,
|
1628 | darkturquoise: 0x00ced1,
|
1629 | darkviolet: 0x9400d3,
|
1630 | deeppink: 0xff1493,
|
1631 | deepskyblue: 0x00bfff,
|
1632 | dimgray: 0x696969,
|
1633 | dimgrey: 0x696969,
|
1634 | dodgerblue: 0x1e90ff,
|
1635 | firebrick: 0xb22222,
|
1636 | floralwhite: 0xfffaf0,
|
1637 | forestgreen: 0x228b22,
|
1638 | fuchsia: 0xff00ff,
|
1639 | gainsboro: 0xdcdcdc,
|
1640 | ghostwhite: 0xf8f8ff,
|
1641 | gold: 0xffd700,
|
1642 | goldenrod: 0xdaa520,
|
1643 | gray: 0x808080,
|
1644 | green: 0x008000,
|
1645 | greenyellow: 0xadff2f,
|
1646 | grey: 0x808080,
|
1647 | honeydew: 0xf0fff0,
|
1648 | hotpink: 0xff69b4,
|
1649 | indianred: 0xcd5c5c,
|
1650 | indigo: 0x4b0082,
|
1651 | ivory: 0xfffff0,
|
1652 | khaki: 0xf0e68c,
|
1653 | lavender: 0xe6e6fa,
|
1654 | lavenderblush: 0xfff0f5,
|
1655 | lawngreen: 0x7cfc00,
|
1656 | lemonchiffon: 0xfffacd,
|
1657 | lightblue: 0xadd8e6,
|
1658 | lightcoral: 0xf08080,
|
1659 | lightcyan: 0xe0ffff,
|
1660 | lightgoldenrodyellow: 0xfafad2,
|
1661 | lightgray: 0xd3d3d3,
|
1662 | lightgreen: 0x90ee90,
|
1663 | lightgrey: 0xd3d3d3,
|
1664 | lightpink: 0xffb6c1,
|
1665 | lightsalmon: 0xffa07a,
|
1666 | lightseagreen: 0x20b2aa,
|
1667 | lightskyblue: 0x87cefa,
|
1668 | lightslategray: 0x778899,
|
1669 | lightslategrey: 0x778899,
|
1670 | lightsteelblue: 0xb0c4de,
|
1671 | lightyellow: 0xffffe0,
|
1672 | lime: 0x00ff00,
|
1673 | limegreen: 0x32cd32,
|
1674 | linen: 0xfaf0e6,
|
1675 | magenta: 0xff00ff,
|
1676 | maroon: 0x800000,
|
1677 | mediumaquamarine: 0x66cdaa,
|
1678 | mediumblue: 0x0000cd,
|
1679 | mediumorchid: 0xba55d3,
|
1680 | mediumpurple: 0x9370db,
|
1681 | mediumseagreen: 0x3cb371,
|
1682 | mediumslateblue: 0x7b68ee,
|
1683 | mediumspringgreen: 0x00fa9a,
|
1684 | mediumturquoise: 0x48d1cc,
|
1685 | mediumvioletred: 0xc71585,
|
1686 | midnightblue: 0x191970,
|
1687 | mintcream: 0xf5fffa,
|
1688 | mistyrose: 0xffe4e1,
|
1689 | moccasin: 0xffe4b5,
|
1690 | navajowhite: 0xffdead,
|
1691 | navy: 0x000080,
|
1692 | oldlace: 0xfdf5e6,
|
1693 | olive: 0x808000,
|
1694 | olivedrab: 0x6b8e23,
|
1695 | orange: 0xffa500,
|
1696 | orangered: 0xff4500,
|
1697 | orchid: 0xda70d6,
|
1698 | palegoldenrod: 0xeee8aa,
|
1699 | palegreen: 0x98fb98,
|
1700 | paleturquoise: 0xafeeee,
|
1701 | palevioletred: 0xdb7093,
|
1702 | papayawhip: 0xffefd5,
|
1703 | peachpuff: 0xffdab9,
|
1704 | peru: 0xcd853f,
|
1705 | pink: 0xffc0cb,
|
1706 | plum: 0xdda0dd,
|
1707 | powderblue: 0xb0e0e6,
|
1708 | purple: 0x800080,
|
1709 | rebeccapurple: 0x663399,
|
1710 | red: 0xff0000,
|
1711 | rosybrown: 0xbc8f8f,
|
1712 | royalblue: 0x4169e1,
|
1713 | saddlebrown: 0x8b4513,
|
1714 | salmon: 0xfa8072,
|
1715 | sandybrown: 0xf4a460,
|
1716 | seagreen: 0x2e8b57,
|
1717 | seashell: 0xfff5ee,
|
1718 | sienna: 0xa0522d,
|
1719 | silver: 0xc0c0c0,
|
1720 | skyblue: 0x87ceeb,
|
1721 | slateblue: 0x6a5acd,
|
1722 | slategray: 0x708090,
|
1723 | slategrey: 0x708090,
|
1724 | snow: 0xfffafa,
|
1725 | springgreen: 0x00ff7f,
|
1726 | steelblue: 0x4682b4,
|
1727 | tan: 0xd2b48c,
|
1728 | teal: 0x008080,
|
1729 | thistle: 0xd8bfd8,
|
1730 | tomato: 0xff6347,
|
1731 | turquoise: 0x40e0d0,
|
1732 | violet: 0xee82ee,
|
1733 | wheat: 0xf5deb3,
|
1734 | white: 0xffffff,
|
1735 | whitesmoke: 0xf5f5f5,
|
1736 | yellow: 0xffff00,
|
1737 | yellowgreen: 0x9acd32
|
1738 | };
|
1739 |
|
1740 | define(Color, color, {
|
1741 | displayable: function() {
|
1742 | return this.rgb().displayable();
|
1743 | },
|
1744 | hex: function() {
|
1745 | return this.rgb().hex();
|
1746 | },
|
1747 | toString: function() {
|
1748 | return this.rgb() + "";
|
1749 | }
|
1750 | });
|
1751 |
|
1752 | function color(format) {
|
1753 | var m;
|
1754 | format = (format + "").trim().toLowerCase();
|
1755 | return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1))
|
1756 | : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16))
|
1757 | : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1)
|
1758 | : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1)
|
1759 | : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4])
|
1760 | : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4])
|
1761 | : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1)
|
1762 | : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4])
|
1763 | : named.hasOwnProperty(format) ? rgbn(named[format])
|
1764 | : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
|
1765 | : null;
|
1766 | }
|
1767 |
|
1768 | function rgbn(n) {
|
1769 | return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
|
1770 | }
|
1771 |
|
1772 | function rgba(r, g, b, a) {
|
1773 | if (a <= 0) r = g = b = NaN;
|
1774 | return new Rgb(r, g, b, a);
|
1775 | }
|
1776 |
|
1777 | function rgbConvert(o) {
|
1778 | if (!(o instanceof Color)) o = color(o);
|
1779 | if (!o) return new Rgb;
|
1780 | o = o.rgb();
|
1781 | return new Rgb(o.r, o.g, o.b, o.opacity);
|
1782 | }
|
1783 |
|
1784 | function rgb(r, g, b, opacity) {
|
1785 | return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
|
1786 | }
|
1787 |
|
1788 | function Rgb(r, g, b, opacity) {
|
1789 | this.r = +r;
|
1790 | this.g = +g;
|
1791 | this.b = +b;
|
1792 | this.opacity = +opacity;
|
1793 | }
|
1794 |
|
1795 | define(Rgb, rgb, extend(Color, {
|
1796 | brighter: function(k) {
|
1797 | k = k == null ? brighter : Math.pow(brighter, k);
|
1798 | return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
|
1799 | },
|
1800 | darker: function(k) {
|
1801 | k = k == null ? darker : Math.pow(darker, k);
|
1802 | return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
|
1803 | },
|
1804 | rgb: function() {
|
1805 | return this;
|
1806 | },
|
1807 | displayable: function() {
|
1808 | return (0 <= this.r && this.r <= 255)
|
1809 | && (0 <= this.g && this.g <= 255)
|
1810 | && (0 <= this.b && this.b <= 255)
|
1811 | && (0 <= this.opacity && this.opacity <= 1);
|
1812 | },
|
1813 | hex: function() {
|
1814 | return "#" + hex(this.r) + hex(this.g) + hex(this.b);
|
1815 | },
|
1816 | toString: function() {
|
1817 | var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
|
1818 | return (a === 1 ? "rgb(" : "rgba(")
|
1819 | + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
|
1820 | + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
|
1821 | + Math.max(0, Math.min(255, Math.round(this.b) || 0))
|
1822 | + (a === 1 ? ")" : ", " + a + ")");
|
1823 | }
|
1824 | }));
|
1825 |
|
1826 | function hex(value) {
|
1827 | value = Math.max(0, Math.min(255, Math.round(value) || 0));
|
1828 | return (value < 16 ? "0" : "") + value.toString(16);
|
1829 | }
|
1830 |
|
1831 | function hsla(h, s, l, a) {
|
1832 | if (a <= 0) h = s = l = NaN;
|
1833 | else if (l <= 0 || l >= 1) h = s = NaN;
|
1834 | else if (s <= 0) h = NaN;
|
1835 | return new Hsl(h, s, l, a);
|
1836 | }
|
1837 |
|
1838 | function hslConvert(o) {
|
1839 | if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
|
1840 | if (!(o instanceof Color)) o = color(o);
|
1841 | if (!o) return new Hsl;
|
1842 | if (o instanceof Hsl) return o;
|
1843 | o = o.rgb();
|
1844 | var r = o.r / 255,
|
1845 | g = o.g / 255,
|
1846 | b = o.b / 255,
|
1847 | min = Math.min(r, g, b),
|
1848 | max = Math.max(r, g, b),
|
1849 | h = NaN,
|
1850 | s = max - min,
|
1851 | l = (max + min) / 2;
|
1852 | if (s) {
|
1853 | if (r === max) h = (g - b) / s + (g < b) * 6;
|
1854 | else if (g === max) h = (b - r) / s + 2;
|
1855 | else h = (r - g) / s + 4;
|
1856 | s /= l < 0.5 ? max + min : 2 - max - min;
|
1857 | h *= 60;
|
1858 | } else {
|
1859 | s = l > 0 && l < 1 ? 0 : h;
|
1860 | }
|
1861 | return new Hsl(h, s, l, o.opacity);
|
1862 | }
|
1863 |
|
1864 | function hsl(h, s, l, opacity) {
|
1865 | return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
|
1866 | }
|
1867 |
|
1868 | function Hsl(h, s, l, opacity) {
|
1869 | this.h = +h;
|
1870 | this.s = +s;
|
1871 | this.l = +l;
|
1872 | this.opacity = +opacity;
|
1873 | }
|
1874 |
|
1875 | define(Hsl, hsl, extend(Color, {
|
1876 | brighter: function(k) {
|
1877 | k = k == null ? brighter : Math.pow(brighter, k);
|
1878 | return new Hsl(this.h, this.s, this.l * k, this.opacity);
|
1879 | },
|
1880 | darker: function(k) {
|
1881 | k = k == null ? darker : Math.pow(darker, k);
|
1882 | return new Hsl(this.h, this.s, this.l * k, this.opacity);
|
1883 | },
|
1884 | rgb: function() {
|
1885 | var h = this.h % 360 + (this.h < 0) * 360,
|
1886 | s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
|
1887 | l = this.l,
|
1888 | m2 = l + (l < 0.5 ? l : 1 - l) * s,
|
1889 | m1 = 2 * l - m2;
|
1890 | return new Rgb(
|
1891 | hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
|
1892 | hsl2rgb(h, m1, m2),
|
1893 | hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
|
1894 | this.opacity
|
1895 | );
|
1896 | },
|
1897 | displayable: function() {
|
1898 | return (0 <= this.s && this.s <= 1 || isNaN(this.s))
|
1899 | && (0 <= this.l && this.l <= 1)
|
1900 | && (0 <= this.opacity && this.opacity <= 1);
|
1901 | }
|
1902 | }));
|
1903 |
|
1904 |
|
1905 | function hsl2rgb(h, m1, m2) {
|
1906 | return (h < 60 ? m1 + (m2 - m1) * h / 60
|
1907 | : h < 180 ? m2
|
1908 | : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
|
1909 | : m1) * 255;
|
1910 | }
|
1911 |
|
1912 | var deg2rad = Math.PI / 180;
|
1913 | var rad2deg = 180 / Math.PI;
|
1914 |
|
1915 |
|
1916 | var K = 18,
|
1917 | Xn = 0.96422,
|
1918 | Yn = 1,
|
1919 | Zn = 0.82521,
|
1920 | t0 = 4 / 29,
|
1921 | t1 = 6 / 29,
|
1922 | t2 = 3 * t1 * t1,
|
1923 | t3 = t1 * t1 * t1;
|
1924 |
|
1925 | function labConvert(o) {
|
1926 | if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
|
1927 | if (o instanceof Hcl) {
|
1928 | if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);
|
1929 | var h = o.h * deg2rad;
|
1930 | return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
|
1931 | }
|
1932 | if (!(o instanceof Rgb)) o = rgbConvert(o);
|
1933 | var r = rgb2lrgb(o.r),
|
1934 | g = rgb2lrgb(o.g),
|
1935 | b = rgb2lrgb(o.b),
|
1936 | y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z;
|
1937 | if (r === g && g === b) x = z = y; else {
|
1938 | x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);
|
1939 | z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);
|
1940 | }
|
1941 | return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
|
1942 | }
|
1943 |
|
1944 | function lab(l, a, b, opacity) {
|
1945 | return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
|
1946 | }
|
1947 |
|
1948 | function Lab(l, a, b, opacity) {
|
1949 | this.l = +l;
|
1950 | this.a = +a;
|
1951 | this.b = +b;
|
1952 | this.opacity = +opacity;
|
1953 | }
|
1954 |
|
1955 | define(Lab, lab, extend(Color, {
|
1956 | brighter: function(k) {
|
1957 | return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
|
1958 | },
|
1959 | darker: function(k) {
|
1960 | return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
|
1961 | },
|
1962 | rgb: function() {
|
1963 | var y = (this.l + 16) / 116,
|
1964 | x = isNaN(this.a) ? y : y + this.a / 500,
|
1965 | z = isNaN(this.b) ? y : y - this.b / 200;
|
1966 | x = Xn * lab2xyz(x);
|
1967 | y = Yn * lab2xyz(y);
|
1968 | z = Zn * lab2xyz(z);
|
1969 | return new Rgb(
|
1970 | lrgb2rgb( 3.1338561 * x - 1.6168667 * y - 0.4906146 * z),
|
1971 | lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z),
|
1972 | lrgb2rgb( 0.0719453 * x - 0.2289914 * y + 1.4052427 * z),
|
1973 | this.opacity
|
1974 | );
|
1975 | }
|
1976 | }));
|
1977 |
|
1978 | function xyz2lab(t) {
|
1979 | return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
|
1980 | }
|
1981 |
|
1982 | function lab2xyz(t) {
|
1983 | return t > t1 ? t * t * t : t2 * (t - t0);
|
1984 | }
|
1985 |
|
1986 | function lrgb2rgb(x) {
|
1987 | return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
|
1988 | }
|
1989 |
|
1990 | function rgb2lrgb(x) {
|
1991 | return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
|
1992 | }
|
1993 |
|
1994 | function hclConvert(o) {
|
1995 | if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
|
1996 | if (!(o instanceof Lab)) o = labConvert(o);
|
1997 | if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0, o.l, o.opacity);
|
1998 | var h = Math.atan2(o.b, o.a) * rad2deg;
|
1999 | return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
|
2000 | }
|
2001 |
|
2002 | function hcl(h, c, l, opacity) {
|
2003 | return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
|
2004 | }
|
2005 |
|
2006 | function Hcl(h, c, l, opacity) {
|
2007 | this.h = +h;
|
2008 | this.c = +c;
|
2009 | this.l = +l;
|
2010 | this.opacity = +opacity;
|
2011 | }
|
2012 |
|
2013 | define(Hcl, hcl, extend(Color, {
|
2014 | brighter: function(k) {
|
2015 | return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
|
2016 | },
|
2017 | darker: function(k) {
|
2018 | return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
|
2019 | },
|
2020 | rgb: function() {
|
2021 | return labConvert(this).rgb();
|
2022 | }
|
2023 | }));
|
2024 |
|
2025 | var A = -0.14861,
|
2026 | B = +1.78277,
|
2027 | C = -0.29227,
|
2028 | D = -0.90649,
|
2029 | E = +1.97294,
|
2030 | ED = E * D,
|
2031 | EB = E * B,
|
2032 | BC_DA = B * C - D * A;
|
2033 |
|
2034 | function cubehelixConvert(o) {
|
2035 | if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
|
2036 | if (!(o instanceof Rgb)) o = rgbConvert(o);
|
2037 | var r = o.r / 255,
|
2038 | g = o.g / 255,
|
2039 | b = o.b / 255,
|
2040 | l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
|
2041 | bl = b - l,
|
2042 | k = (E * (g - l) - C * bl) / D,
|
2043 | s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)),
|
2044 | h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
|
2045 | return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
|
2046 | }
|
2047 |
|
2048 | function cubehelix(h, s, l, opacity) {
|
2049 | return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
|
2050 | }
|
2051 |
|
2052 | function Cubehelix(h, s, l, opacity) {
|
2053 | this.h = +h;
|
2054 | this.s = +s;
|
2055 | this.l = +l;
|
2056 | this.opacity = +opacity;
|
2057 | }
|
2058 |
|
2059 | define(Cubehelix, cubehelix, extend(Color, {
|
2060 | brighter: function(k) {
|
2061 | k = k == null ? brighter : Math.pow(brighter, k);
|
2062 | return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
|
2063 | },
|
2064 | darker: function(k) {
|
2065 | k = k == null ? darker : Math.pow(darker, k);
|
2066 | return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
|
2067 | },
|
2068 | rgb: function() {
|
2069 | var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
|
2070 | l = +this.l,
|
2071 | a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
|
2072 | cosh = Math.cos(h),
|
2073 | sinh = Math.sin(h);
|
2074 | return new Rgb(
|
2075 | 255 * (l + a * (A * cosh + B * sinh)),
|
2076 | 255 * (l + a * (C * cosh + D * sinh)),
|
2077 | 255 * (l + a * (E * cosh)),
|
2078 | this.opacity
|
2079 | );
|
2080 | }
|
2081 | }));
|
2082 |
|
2083 | function constant$1(x) {
|
2084 | return function() {
|
2085 | return x;
|
2086 | };
|
2087 | }
|
2088 |
|
2089 | function linear(a, d) {
|
2090 | return function(t) {
|
2091 | return a + t * d;
|
2092 | };
|
2093 | }
|
2094 |
|
2095 | function exponential(a, b, y) {
|
2096 | return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
|
2097 | return Math.pow(a + t * b, y);
|
2098 | };
|
2099 | }
|
2100 |
|
2101 | function gamma(y) {
|
2102 | return (y = +y) === 1 ? nogamma : function(a, b) {
|
2103 | return b - a ? exponential(a, b, y) : constant$1(isNaN(a) ? b : a);
|
2104 | };
|
2105 | }
|
2106 |
|
2107 | function nogamma(a, b) {
|
2108 | var d = b - a;
|
2109 | return d ? linear(a, d) : constant$1(isNaN(a) ? b : a);
|
2110 | }
|
2111 |
|
2112 | var rgb$1 = (function rgbGamma(y) {
|
2113 | var color = gamma(y);
|
2114 |
|
2115 | function rgb$1(start, end) {
|
2116 | var r = color((start = rgb(start)).r, (end = rgb(end)).r),
|
2117 | g = color(start.g, end.g),
|
2118 | b = color(start.b, end.b),
|
2119 | opacity = nogamma(start.opacity, end.opacity);
|
2120 | return function(t) {
|
2121 | start.r = r(t);
|
2122 | start.g = g(t);
|
2123 | start.b = b(t);
|
2124 | start.opacity = opacity(t);
|
2125 | return start + "";
|
2126 | };
|
2127 | }
|
2128 |
|
2129 | rgb$1.gamma = rgbGamma;
|
2130 |
|
2131 | return rgb$1;
|
2132 | })(1);
|
2133 |
|
2134 | function array(a, b) {
|
2135 | var nb = b ? b.length : 0,
|
2136 | na = a ? Math.min(nb, a.length) : 0,
|
2137 | x = new Array(na),
|
2138 | c = new Array(nb),
|
2139 | i;
|
2140 |
|
2141 | for (i = 0; i < na; ++i) x[i] = interpolateValue(a[i], b[i]);
|
2142 | for (; i < nb; ++i) c[i] = b[i];
|
2143 |
|
2144 | return function(t) {
|
2145 | for (i = 0; i < na; ++i) c[i] = x[i](t);
|
2146 | return c;
|
2147 | };
|
2148 | }
|
2149 |
|
2150 | function date(a, b) {
|
2151 | var d = new Date;
|
2152 | return a = +a, b -= a, function(t) {
|
2153 | return d.setTime(a + b * t), d;
|
2154 | };
|
2155 | }
|
2156 |
|
2157 | function reinterpolate(a, b) {
|
2158 | return a = +a, b -= a, function(t) {
|
2159 | return a + b * t;
|
2160 | };
|
2161 | }
|
2162 |
|
2163 | function object(a, b) {
|
2164 | var i = {},
|
2165 | c = {},
|
2166 | k;
|
2167 |
|
2168 | if (a === null || typeof a !== "object") a = {};
|
2169 | if (b === null || typeof b !== "object") b = {};
|
2170 |
|
2171 | for (k in b) {
|
2172 | if (k in a) {
|
2173 | i[k] = interpolateValue(a[k], b[k]);
|
2174 | } else {
|
2175 | c[k] = b[k];
|
2176 | }
|
2177 | }
|
2178 |
|
2179 | return function(t) {
|
2180 | for (k in i) c[k] = i[k](t);
|
2181 | return c;
|
2182 | };
|
2183 | }
|
2184 |
|
2185 | var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
|
2186 | reB = new RegExp(reA.source, "g");
|
2187 |
|
2188 | function zero(b) {
|
2189 | return function() {
|
2190 | return b;
|
2191 | };
|
2192 | }
|
2193 |
|
2194 | function one(b) {
|
2195 | return function(t) {
|
2196 | return b(t) + "";
|
2197 | };
|
2198 | }
|
2199 |
|
2200 | function string(a, b) {
|
2201 | var bi = reA.lastIndex = reB.lastIndex = 0,
|
2202 | am,
|
2203 | bm,
|
2204 | bs,
|
2205 | i = -1,
|
2206 | s = [],
|
2207 | q = [];
|
2208 |
|
2209 |
|
2210 | a = a + "", b = b + "";
|
2211 |
|
2212 |
|
2213 | while ((am = reA.exec(a))
|
2214 | && (bm = reB.exec(b))) {
|
2215 | if ((bs = bm.index) > bi) {
|
2216 | bs = b.slice(bi, bs);
|
2217 | if (s[i]) s[i] += bs;
|
2218 | else s[++i] = bs;
|
2219 | }
|
2220 | if ((am = am[0]) === (bm = bm[0])) {
|
2221 | if (s[i]) s[i] += bm;
|
2222 | else s[++i] = bm;
|
2223 | } else {
|
2224 | s[++i] = null;
|
2225 | q.push({i: i, x: reinterpolate(am, bm)});
|
2226 | }
|
2227 | bi = reB.lastIndex;
|
2228 | }
|
2229 |
|
2230 |
|
2231 | if (bi < b.length) {
|
2232 | bs = b.slice(bi);
|
2233 | if (s[i]) s[i] += bs;
|
2234 | else s[++i] = bs;
|
2235 | }
|
2236 |
|
2237 |
|
2238 |
|
2239 | return s.length < 2 ? (q[0]
|
2240 | ? one(q[0].x)
|
2241 | : zero(b))
|
2242 | : (b = q.length, function(t) {
|
2243 | for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
|
2244 | return s.join("");
|
2245 | });
|
2246 | }
|
2247 |
|
2248 | function interpolateValue(a, b) {
|
2249 | var t = typeof b, c;
|
2250 | return b == null || t === "boolean" ? constant$1(b)
|
2251 | : (t === "number" ? reinterpolate
|
2252 | : t === "string" ? ((c = color(b)) ? (b = c, rgb$1) : string)
|
2253 | : b instanceof color ? rgb$1
|
2254 | : b instanceof Date ? date
|
2255 | : Array.isArray(b) ? array
|
2256 | : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object
|
2257 | : reinterpolate)(a, b);
|
2258 | }
|
2259 |
|
2260 | function interpolateRound(a, b) {
|
2261 | return a = +a, b -= a, function(t) {
|
2262 | return Math.round(a + b * t);
|
2263 | };
|
2264 | }
|
2265 |
|
2266 | var array$1 = Array.prototype;
|
2267 |
|
2268 | var map = array$1.map;
|
2269 | var slice$1 = array$1.slice;
|
2270 |
|
2271 | function constant$2(x) {
|
2272 | return function() {
|
2273 | return x;
|
2274 | };
|
2275 | }
|
2276 |
|
2277 | function number$1(x) {
|
2278 | return +x;
|
2279 | }
|
2280 |
|
2281 | var unit = [0, 1];
|
2282 |
|
2283 | function deinterpolateLinear(a, b) {
|
2284 | return (b -= (a = +a))
|
2285 | ? function(x) { return (x - a) / b; }
|
2286 | : constant$2(b);
|
2287 | }
|
2288 |
|
2289 | function deinterpolateClamp(deinterpolate) {
|
2290 | return function(a, b) {
|
2291 | var d = deinterpolate(a = +a, b = +b);
|
2292 | return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
|
2293 | };
|
2294 | }
|
2295 |
|
2296 | function reinterpolateClamp(reinterpolate) {
|
2297 | return function(a, b) {
|
2298 | var r = reinterpolate(a = +a, b = +b);
|
2299 | return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
|
2300 | };
|
2301 | }
|
2302 |
|
2303 | function bimap(domain, range, deinterpolate, reinterpolate) {
|
2304 | var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
|
2305 | if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
|
2306 | else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
|
2307 | return function(x) { return r0(d0(x)); };
|
2308 | }
|
2309 |
|
2310 | function polymap(domain, range, deinterpolate, reinterpolate) {
|
2311 | var j = Math.min(domain.length, range.length) - 1,
|
2312 | d = new Array(j),
|
2313 | r = new Array(j),
|
2314 | i = -1;
|
2315 |
|
2316 |
|
2317 | if (domain[j] < domain[0]) {
|
2318 | domain = domain.slice().reverse();
|
2319 | range = range.slice().reverse();
|
2320 | }
|
2321 |
|
2322 | while (++i < j) {
|
2323 | d[i] = deinterpolate(domain[i], domain[i + 1]);
|
2324 | r[i] = reinterpolate(range[i], range[i + 1]);
|
2325 | }
|
2326 |
|
2327 | return function(x) {
|
2328 | var i = bisectRight(domain, x, 1, j) - 1;
|
2329 | return r[i](d[i](x));
|
2330 | };
|
2331 | }
|
2332 |
|
2333 | function copy(source, target) {
|
2334 | return target
|
2335 | .domain(source.domain())
|
2336 | .range(source.range())
|
2337 | .interpolate(source.interpolate())
|
2338 | .clamp(source.clamp());
|
2339 | }
|
2340 |
|
2341 |
|
2342 |
|
2343 | function continuous(deinterpolate, reinterpolate) {
|
2344 | var domain = unit,
|
2345 | range = unit,
|
2346 | interpolate = interpolateValue,
|
2347 | clamp = false,
|
2348 | piecewise,
|
2349 | output,
|
2350 | input;
|
2351 |
|
2352 | function rescale() {
|
2353 | piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap;
|
2354 | output = input = null;
|
2355 | return scale;
|
2356 | }
|
2357 |
|
2358 | function scale(x) {
|
2359 | return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate)))(+x);
|
2360 | }
|
2361 |
|
2362 | scale.invert = function(y) {
|
2363 | return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
|
2364 | };
|
2365 |
|
2366 | scale.domain = function(_) {
|
2367 | return arguments.length ? (domain = map.call(_, number$1), rescale()) : domain.slice();
|
2368 | };
|
2369 |
|
2370 | scale.range = function(_) {
|
2371 | return arguments.length ? (range = slice$1.call(_), rescale()) : range.slice();
|
2372 | };
|
2373 |
|
2374 | scale.rangeRound = function(_) {
|
2375 | return range = slice$1.call(_), interpolate = interpolateRound, rescale();
|
2376 | };
|
2377 |
|
2378 | scale.clamp = function(_) {
|
2379 | return arguments.length ? (clamp = !!_, rescale()) : clamp;
|
2380 | };
|
2381 |
|
2382 | scale.interpolate = function(_) {
|
2383 | return arguments.length ? (interpolate = _, rescale()) : interpolate;
|
2384 | };
|
2385 |
|
2386 | return rescale();
|
2387 | }
|
2388 |
|
2389 |
|
2390 |
|
2391 |
|
2392 | function formatDecimal(x, p) {
|
2393 | if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null;
|
2394 | var i, coefficient = x.slice(0, i);
|
2395 |
|
2396 |
|
2397 |
|
2398 | return [
|
2399 | coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
|
2400 | +x.slice(i + 1)
|
2401 | ];
|
2402 | }
|
2403 |
|
2404 | function exponent(x) {
|
2405 | return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
|
2406 | }
|
2407 |
|
2408 | function formatGroup(grouping, thousands) {
|
2409 | return function(value, width) {
|
2410 | var i = value.length,
|
2411 | t = [],
|
2412 | j = 0,
|
2413 | g = grouping[0],
|
2414 | length = 0;
|
2415 |
|
2416 | while (i > 0 && g > 0) {
|
2417 | if (length + g + 1 > width) g = Math.max(1, width - length);
|
2418 | t.push(value.substring(i -= g, i + g));
|
2419 | if ((length += g + 1) > width) break;
|
2420 | g = grouping[j = (j + 1) % grouping.length];
|
2421 | }
|
2422 |
|
2423 | return t.reverse().join(thousands);
|
2424 | };
|
2425 | }
|
2426 |
|
2427 | function formatNumerals(numerals) {
|
2428 | return function(value) {
|
2429 | return value.replace(/[0-9]/g, function(i) {
|
2430 | return numerals[+i];
|
2431 | });
|
2432 | };
|
2433 | }
|
2434 |
|
2435 |
|
2436 | var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
|
2437 |
|
2438 | function formatSpecifier(specifier) {
|
2439 | return new FormatSpecifier(specifier);
|
2440 | }
|
2441 |
|
2442 | formatSpecifier.prototype = FormatSpecifier.prototype;
|
2443 |
|
2444 | function FormatSpecifier(specifier) {
|
2445 | if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
|
2446 | var match;
|
2447 | this.fill = match[1] || " ";
|
2448 | this.align = match[2] || ">";
|
2449 | this.sign = match[3] || "-";
|
2450 | this.symbol = match[4] || "";
|
2451 | this.zero = !!match[5];
|
2452 | this.width = match[6] && +match[6];
|
2453 | this.comma = !!match[7];
|
2454 | this.precision = match[8] && +match[8].slice(1);
|
2455 | this.trim = !!match[9];
|
2456 | this.type = match[10] || "";
|
2457 | }
|
2458 |
|
2459 | FormatSpecifier.prototype.toString = function() {
|
2460 | return this.fill
|
2461 | + this.align
|
2462 | + this.sign
|
2463 | + this.symbol
|
2464 | + (this.zero ? "0" : "")
|
2465 | + (this.width == null ? "" : Math.max(1, this.width | 0))
|
2466 | + (this.comma ? "," : "")
|
2467 | + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
|
2468 | + (this.trim ? "~" : "")
|
2469 | + this.type;
|
2470 | };
|
2471 |
|
2472 |
|
2473 | function formatTrim(s) {
|
2474 | out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
|
2475 | switch (s[i]) {
|
2476 | case ".": i0 = i1 = i; break;
|
2477 | case "0": if (i0 === 0) i0 = i; i1 = i; break;
|
2478 | default: if (i0 > 0) { if (!+s[i]) break out; i0 = 0; } break;
|
2479 | }
|
2480 | }
|
2481 | return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
|
2482 | }
|
2483 |
|
2484 | var prefixExponent;
|
2485 |
|
2486 | function formatPrefixAuto(x, p) {
|
2487 | var d = formatDecimal(x, p);
|
2488 | if (!d) return x + "";
|
2489 | var coefficient = d[0],
|
2490 | exponent = d[1],
|
2491 | i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
|
2492 | n = coefficient.length;
|
2493 | return i === n ? coefficient
|
2494 | : i > n ? coefficient + new Array(i - n + 1).join("0")
|
2495 | : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
|
2496 | : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0];
|
2497 | }
|
2498 |
|
2499 | function formatRounded(x, p) {
|
2500 | var d = formatDecimal(x, p);
|
2501 | if (!d) return x + "";
|
2502 | var coefficient = d[0],
|
2503 | exponent = d[1];
|
2504 | return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
|
2505 | : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
|
2506 | : coefficient + new Array(exponent - coefficient.length + 2).join("0");
|
2507 | }
|
2508 |
|
2509 | var formatTypes = {
|
2510 | "%": function(x, p) { return (x * 100).toFixed(p); },
|
2511 | "b": function(x) { return Math.round(x).toString(2); },
|
2512 | "c": function(x) { return x + ""; },
|
2513 | "d": function(x) { return Math.round(x).toString(10); },
|
2514 | "e": function(x, p) { return x.toExponential(p); },
|
2515 | "f": function(x, p) { return x.toFixed(p); },
|
2516 | "g": function(x, p) { return x.toPrecision(p); },
|
2517 | "o": function(x) { return Math.round(x).toString(8); },
|
2518 | "p": function(x, p) { return formatRounded(x * 100, p); },
|
2519 | "r": formatRounded,
|
2520 | "s": formatPrefixAuto,
|
2521 | "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
|
2522 | "x": function(x) { return Math.round(x).toString(16); }
|
2523 | };
|
2524 |
|
2525 | function identity$1(x) {
|
2526 | return x;
|
2527 | }
|
2528 |
|
2529 | var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
|
2530 |
|
2531 | function formatLocale(locale) {
|
2532 | var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$1,
|
2533 | currency = locale.currency,
|
2534 | decimal = locale.decimal,
|
2535 | numerals = locale.numerals ? formatNumerals(locale.numerals) : identity$1,
|
2536 | percent = locale.percent || "%";
|
2537 |
|
2538 | function newFormat(specifier) {
|
2539 | specifier = formatSpecifier(specifier);
|
2540 |
|
2541 | var fill = specifier.fill,
|
2542 | align = specifier.align,
|
2543 | sign = specifier.sign,
|
2544 | symbol = specifier.symbol,
|
2545 | zero = specifier.zero,
|
2546 | width = specifier.width,
|
2547 | comma = specifier.comma,
|
2548 | precision = specifier.precision,
|
2549 | trim = specifier.trim,
|
2550 | type = specifier.type;
|
2551 |
|
2552 |
|
2553 | if (type === "n") comma = true, type = "g";
|
2554 |
|
2555 |
|
2556 | else if (!formatTypes[type]) precision == null && (precision = 12), trim = true, type = "g";
|
2557 |
|
2558 |
|
2559 | if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
|
2560 |
|
2561 |
|
2562 |
|
2563 | var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
|
2564 | suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : "";
|
2565 |
|
2566 |
|
2567 |
|
2568 |
|
2569 | var formatType = formatTypes[type],
|
2570 | maybeSuffix = /[defgprs%]/.test(type);
|
2571 |
|
2572 |
|
2573 |
|
2574 |
|
2575 |
|
2576 | precision = precision == null ? 6
|
2577 | : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
|
2578 | : Math.max(0, Math.min(20, precision));
|
2579 |
|
2580 | function format(value) {
|
2581 | var valuePrefix = prefix,
|
2582 | valueSuffix = suffix,
|
2583 | i, n, c;
|
2584 |
|
2585 | if (type === "c") {
|
2586 | valueSuffix = formatType(value) + valueSuffix;
|
2587 | value = "";
|
2588 | } else {
|
2589 | value = +value;
|
2590 |
|
2591 |
|
2592 | var valueNegative = value < 0;
|
2593 | value = formatType(Math.abs(value), precision);
|
2594 |
|
2595 |
|
2596 | if (trim) value = formatTrim(value);
|
2597 |
|
2598 |
|
2599 | if (valueNegative && +value === 0) valueNegative = false;
|
2600 |
|
2601 |
|
2602 | valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
|
2603 | valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
|
2604 |
|
2605 |
|
2606 |
|
2607 | if (maybeSuffix) {
|
2608 | i = -1, n = value.length;
|
2609 | while (++i < n) {
|
2610 | if (c = value.charCodeAt(i), 48 > c || c > 57) {
|
2611 | valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
|
2612 | value = value.slice(0, i);
|
2613 | break;
|
2614 | }
|
2615 | }
|
2616 | }
|
2617 | }
|
2618 |
|
2619 |
|
2620 | if (comma && !zero) value = group(value, Infinity);
|
2621 |
|
2622 |
|
2623 | var length = valuePrefix.length + value.length + valueSuffix.length,
|
2624 | padding = length < width ? new Array(width - length + 1).join(fill) : "";
|
2625 |
|
2626 |
|
2627 | if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
|
2628 |
|
2629 |
|
2630 | switch (align) {
|
2631 | case "<": value = valuePrefix + value + valueSuffix + padding; break;
|
2632 | case "=": value = valuePrefix + padding + value + valueSuffix; break;
|
2633 | case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
|
2634 | default: value = padding + valuePrefix + value + valueSuffix; break;
|
2635 | }
|
2636 |
|
2637 | return numerals(value);
|
2638 | }
|
2639 |
|
2640 | format.toString = function() {
|
2641 | return specifier + "";
|
2642 | };
|
2643 |
|
2644 | return format;
|
2645 | }
|
2646 |
|
2647 | function formatPrefix(specifier, value) {
|
2648 | var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
|
2649 | e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
|
2650 | k = Math.pow(10, -e),
|
2651 | prefix = prefixes[8 + e / 3];
|
2652 | return function(value) {
|
2653 | return f(k * value) + prefix;
|
2654 | };
|
2655 | }
|
2656 |
|
2657 | return {
|
2658 | format: newFormat,
|
2659 | formatPrefix: formatPrefix
|
2660 | };
|
2661 | }
|
2662 |
|
2663 | var locale;
|
2664 | var format;
|
2665 | var formatPrefix;
|
2666 |
|
2667 | defaultLocale({
|
2668 | decimal: ".",
|
2669 | thousands: ",",
|
2670 | grouping: [3],
|
2671 | currency: ["$", ""]
|
2672 | });
|
2673 |
|
2674 | function defaultLocale(definition) {
|
2675 | locale = formatLocale(definition);
|
2676 | format = locale.format;
|
2677 | formatPrefix = locale.formatPrefix;
|
2678 | return locale;
|
2679 | }
|
2680 |
|
2681 | function precisionFixed(step) {
|
2682 | return Math.max(0, -exponent(Math.abs(step)));
|
2683 | }
|
2684 |
|
2685 | function precisionPrefix(step, value) {
|
2686 | return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
|
2687 | }
|
2688 |
|
2689 | function precisionRound(step, max) {
|
2690 | step = Math.abs(step), max = Math.abs(max) - step;
|
2691 | return Math.max(0, exponent(max) - exponent(step)) + 1;
|
2692 | }
|
2693 |
|
2694 | function tickFormat(domain, count, specifier) {
|
2695 | var start = domain[0],
|
2696 | stop = domain[domain.length - 1],
|
2697 | step = tickStep(start, stop, count == null ? 10 : count),
|
2698 | precision;
|
2699 | specifier = formatSpecifier(specifier == null ? ",f" : specifier);
|
2700 | switch (specifier.type) {
|
2701 | case "s": {
|
2702 | var value = Math.max(Math.abs(start), Math.abs(stop));
|
2703 | if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
|
2704 | return formatPrefix(specifier, value);
|
2705 | }
|
2706 | case "":
|
2707 | case "e":
|
2708 | case "g":
|
2709 | case "p":
|
2710 | case "r": {
|
2711 | if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
|
2712 | break;
|
2713 | }
|
2714 | case "f":
|
2715 | case "%": {
|
2716 | if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
|
2717 | break;
|
2718 | }
|
2719 | }
|
2720 | return format(specifier);
|
2721 | }
|
2722 |
|
2723 | function linearish(scale) {
|
2724 | var domain = scale.domain;
|
2725 |
|
2726 | scale.ticks = function(count) {
|
2727 | var d = domain();
|
2728 | return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
|
2729 | };
|
2730 |
|
2731 | scale.tickFormat = function(count, specifier) {
|
2732 | return tickFormat(domain(), count, specifier);
|
2733 | };
|
2734 |
|
2735 | scale.nice = function(count) {
|
2736 | if (count == null) count = 10;
|
2737 |
|
2738 | var d = domain(),
|
2739 | i0 = 0,
|
2740 | i1 = d.length - 1,
|
2741 | start = d[i0],
|
2742 | stop = d[i1],
|
2743 | step;
|
2744 |
|
2745 | if (stop < start) {
|
2746 | step = start, start = stop, stop = step;
|
2747 | step = i0, i0 = i1, i1 = step;
|
2748 | }
|
2749 |
|
2750 | step = tickIncrement(start, stop, count);
|
2751 |
|
2752 | if (step > 0) {
|
2753 | start = Math.floor(start / step) * step;
|
2754 | stop = Math.ceil(stop / step) * step;
|
2755 | step = tickIncrement(start, stop, count);
|
2756 | } else if (step < 0) {
|
2757 | start = Math.ceil(start * step) / step;
|
2758 | stop = Math.floor(stop * step) / step;
|
2759 | step = tickIncrement(start, stop, count);
|
2760 | }
|
2761 |
|
2762 | if (step > 0) {
|
2763 | d[i0] = Math.floor(start / step) * step;
|
2764 | d[i1] = Math.ceil(stop / step) * step;
|
2765 | domain(d);
|
2766 | } else if (step < 0) {
|
2767 | d[i0] = Math.ceil(start * step) / step;
|
2768 | d[i1] = Math.floor(stop * step) / step;
|
2769 | domain(d);
|
2770 | }
|
2771 |
|
2772 | return scale;
|
2773 | };
|
2774 |
|
2775 | return scale;
|
2776 | }
|
2777 |
|
2778 | function linear$1() {
|
2779 | var scale = continuous(deinterpolateLinear, reinterpolate);
|
2780 |
|
2781 | scale.copy = function() {
|
2782 | return copy(scale, linear$1());
|
2783 | };
|
2784 |
|
2785 | return linearish(scale);
|
2786 | }
|
2787 |
|
2788 | var VERSION = "1.3.2";
|
2789 |
|
2790 | function Slider(selector) {
|
2791 | this.container = select(selector);
|
2792 |
|
2793 | this._width = null;
|
2794 | this._height = null;
|
2795 |
|
2796 | this._handleRadius = 15;
|
2797 | this._channelHeight = 5;
|
2798 | this._channelRadius = null;
|
2799 |
|
2800 | this._handleFill = "black";
|
2801 | this._channelFill = "#eee";
|
2802 |
|
2803 | this._margin = { top: null, left: null, right: null };
|
2804 |
|
2805 | this._domain = [0, 1];
|
2806 | this._value = null;
|
2807 | this._snap = false;
|
2808 |
|
2809 | this._scale = null;
|
2810 | this._axis = false;
|
2811 | this._ticks = null;
|
2812 | this._tickFormat = null;
|
2813 | this._tickSize = null;
|
2814 |
|
2815 | this._label = null;
|
2816 | this._labelSize = 18;
|
2817 |
|
2818 | this._startLabel = null;
|
2819 | this._startLabelBelow = false;
|
2820 |
|
2821 | this._endLabel = null;
|
2822 | this._endLabelBelow = false;
|
2823 |
|
2824 | this._startEndLabelSize = 16;
|
2825 |
|
2826 | this.handlers = { "change": [] };
|
2827 | }
|
2828 |
|
2829 |
|
2830 | function accessor(k) {
|
2831 | if (k.length > 0 && k.charAt(0) == "_") {
|
2832 | Slider.prototype[k.substr(1)] = function(v) {
|
2833 | if (typeof v == "undefined") return this[k];
|
2834 | this[k] = v;
|
2835 | return this;
|
2836 | };
|
2837 | }
|
2838 | }
|
2839 | var s = new Slider();
|
2840 | for (var k in s) {
|
2841 | accessor(k);
|
2842 | }
|
2843 |
|
2844 |
|
2845 | Slider.prototype.margin = function Slider_margin(options) {
|
2846 | if (!options) return this._margin;
|
2847 | for (k in options) {
|
2848 | if (k in this._margin) this._margin[k] = options[k];
|
2849 | else throw "Slider.margin: unrecognised option " + k;
|
2850 | }
|
2851 | return this;
|
2852 | };
|
2853 |
|
2854 |
|
2855 | Slider.prototype.on = function Slider_on(event, handler) {
|
2856 | if (!(event in this.handlers)) throw "Slider.on: No such event: " + event;
|
2857 | this.handlers[event].push(handler);
|
2858 | return this;
|
2859 | };
|
2860 |
|
2861 |
|
2862 | Slider.prototype.fire = function Slider_fire(event, d) {
|
2863 | if (!(event in this.handlers)) throw "Slider.fire: No such event: " + event;
|
2864 | var handlers = this.handlers[event];
|
2865 | for (var i = 0; i < handlers.length; i++) {
|
2866 | handlers[i].call(this, d);
|
2867 | }
|
2868 | return this;
|
2869 | };
|
2870 |
|
2871 |
|
2872 | function closestValue(sorted_list, value, a, b) {
|
2873 | if (typeof a === "undefined") a = 0;
|
2874 | if (typeof b === "undefined") b = sorted_list.length;
|
2875 |
|
2876 | if (b-a == 0) return value;
|
2877 | if (b-a == 1) return sorted_list[a];
|
2878 | if (b-a == 2) {
|
2879 | var d1 = Math.abs(sorted_list[a] - value),
|
2880 | d2 = Math.abs(sorted_list[a+1] - value);
|
2881 | if (d1 <= d2) return sorted_list[a];
|
2882 | else return sorted_list[a+1];
|
2883 | }
|
2884 |
|
2885 | var mid = a + Math.floor((b-a) / 2),
|
2886 | mid_v = sorted_list[mid],
|
2887 | pre = mid - 1,
|
2888 | pre_v = sorted_list[pre];
|
2889 | if (pre_v <= value && value <= mid_v) {
|
2890 | return (Math.abs(pre_v - value) <= Math.abs(mid_v - value)) ? pre_v : mid_v;
|
2891 | }
|
2892 | if (mid_v <= value) return closestValue(sorted_list, value, mid, b);
|
2893 | else return closestValue(sorted_list, value, a, mid);
|
2894 | }
|
2895 |
|
2896 | function snapTo(specification, value) {
|
2897 | if (typeof specification == "boolean") {
|
2898 | return specification ? Math.round(value) : value;
|
2899 | }
|
2900 |
|
2901 | return closestValue(specification, value);
|
2902 | }
|
2903 |
|
2904 |
|
2905 | Slider.prototype.draw = function Slider_draw() {
|
2906 | var that = this;
|
2907 |
|
2908 | var cw = this._width,
|
2909 | ch = this._height;
|
2910 |
|
2911 | var container_node = this.container.node();
|
2912 |
|
2913 |
|
2914 |
|
2915 | if (!cw) {
|
2916 | var r = container_node.getBoundingClientRect();
|
2917 |
|
2918 |
|
2919 | if (!r || r.width == 0) return this;
|
2920 |
|
2921 | cw = r.width;
|
2922 | ch = r.height;
|
2923 | }
|
2924 |
|
2925 | var channel_r = this._channelRadius == null ? this._channelHeight/2 : this._channelRadius,
|
2926 | left_margin = (this._margin.left == null ? Math.max(this._handleRadius, channel_r) : this._margin.left),
|
2927 | right_margin = (this._margin.right == null ? Math.max(this._handleRadius, channel_r) : this._margin.right),
|
2928 | top_margin = this._margin.top == null ? Math.max(this._handleRadius, this._channelHeight/2) : this._margin.top,
|
2929 | w = cw - left_margin - right_margin,
|
2930 | channel_w = w + 2*channel_r,
|
2931 | label_h = this._labelSize * 1.5;
|
2932 |
|
2933 | if (this._label != null && this._margin.top == null) top_margin += label_h;
|
2934 |
|
2935 | var slider;
|
2936 | if (container_node.namespaceURI == "http://www.w3.org/2000/svg") {
|
2937 | slider = this.container;
|
2938 | }
|
2939 | else {
|
2940 | slider = this.container.selectAll("svg").data([{ width: cw, height: ch }]);
|
2941 | slider.exit().remove();
|
2942 | slider = slider.enter().append("svg").merge(slider);
|
2943 | slider.attr("width", function(d) { return d.width; })
|
2944 | .attr("height", function(d) { return d.height; });
|
2945 | }
|
2946 |
|
2947 | var g = slider.selectAll("g.slider-container").data([{left: left_margin, top: top_margin, id: this._id}]);
|
2948 | g.exit().remove();
|
2949 | g = g.enter().append("g").attr("class", "slider-container").merge(g);
|
2950 | g.attr("transform", function(d) {
|
2951 | return "translate(" + d.left + "," + d.top + ")";
|
2952 | })
|
2953 | .attr("id", function(d) { return d.id; });
|
2954 |
|
2955 | this.scale = (this._scale ? this._scale() : linear$1()).domain(this._domain).range([0, w]);
|
2956 |
|
2957 | if (this._value == null || this._value < this._domain[0]) this._value = this._domain[0];
|
2958 | else if (this._value > this._domain[1]) this._value = this._domain[1];
|
2959 |
|
2960 | if (this._snap) this._value = snapTo(this._snap, this._value);
|
2961 |
|
2962 | var axes_data = [];
|
2963 | if (this._axis) {
|
2964 | var axis;
|
2965 | if (typeof this._axis != "boolean") {
|
2966 | axis = this._axis(this.scale);
|
2967 | }
|
2968 | else {
|
2969 | axis = axisBottom().scale(this.scale).tickPadding(6);
|
2970 | }
|
2971 |
|
2972 | if (this._ticks) axis.ticks(this._ticks);
|
2973 | if (this._tickFormat) axis.tickFormat(this._tickFormat);
|
2974 | if (this._tickSize) axis.tickSize(this._tickSize);
|
2975 | else axis.tickSize(Math.max(5, this._handleRadius - this._channelHeight - 2));
|
2976 | axes_data.push(axis);
|
2977 | }
|
2978 |
|
2979 | var axes = g.selectAll(".slider-axis");
|
2980 | var axes_enter = axes.data(axes_data).enter();
|
2981 | axes_enter.append("g").attr("class", "slider-axis")
|
2982 | .attr("transform", "translate(" + 0 + "," + this._channelHeight/2 + ")")
|
2983 | .each(function(axis) { axis(select(this)); });
|
2984 | axes_enter.select(".domain").attr("fill", "none");
|
2985 | axes_enter.selectAll(".tick line").attr("stroke", "black");
|
2986 | axes_enter.exit().remove();
|
2987 |
|
2988 | var channel, handle;
|
2989 | channel = g.selectAll(".slider-channel")
|
2990 | .data([{ width: channel_w, height: this._channelHeight, channel_r: channel_r }]);
|
2991 | channel.exit().remove();
|
2992 |
|
2993 | channel = channel.enter().append("rect").attr("class", "slider-channel")
|
2994 | .attr("cursor", "pointer")
|
2995 | .on("click", function() {
|
2996 | var slider_x = Math.max(0, Math.min(w, d3_mouse(this)[0]));
|
2997 | that._value = that.scale.invert(slider_x);
|
2998 | if (that._snap) that._value = snapTo(that._snap, that._value);
|
2999 | handle.attr("cx", that.scale(that._value));
|
3000 | that.fire("change", that._value);
|
3001 | })
|
3002 | .merge(channel);
|
3003 |
|
3004 | channel.attr("width", function(d) { return d.width; })
|
3005 | .attr("fill", this._channelFill)
|
3006 | .attr("height", function(d) { return d.height; })
|
3007 | .attr("y", function(d) { return -d.height/2; })
|
3008 | .attr("x", function(d) { return -d.channel_r; })
|
3009 | .attr("rx", function(d) { return d.channel_r; });
|
3010 |
|
3011 | var drag_dx_origin, drag_x_origin;
|
3012 | function handleMousedown(event) {
|
3013 | document.addEventListener("mouseup", handleMouseup, false);
|
3014 | document.addEventListener("mousemove", handleMousemove, false);
|
3015 | drag_dx_origin = event.clientX;
|
3016 | drag_x_origin = that.scale(that._value);
|
3017 | }
|
3018 |
|
3019 | function handleMouseup() {
|
3020 | document.removeEventListener("mouseup", handleMouseup, false);
|
3021 | document.removeEventListener("mousemove", handleMousemove, false);
|
3022 | }
|
3023 |
|
3024 | function handleMousemove(event) {
|
3025 | drag(event.clientX - drag_dx_origin);
|
3026 | }
|
3027 |
|
3028 | function handleTouchstart(event) {
|
3029 | if (event.touches.length != 1) return;
|
3030 | document.addEventListener("touchend", handleTouchend, false);
|
3031 | document.addEventListener("touchmove", handleTouchmove, false);
|
3032 | drag_dx_origin = event.touches[0].clientX;
|
3033 | drag_x_origin = that.scale(that._value);
|
3034 | }
|
3035 |
|
3036 | function handleTouchend() {
|
3037 | document.removeEventListener("touchend", handleTouchend, false);
|
3038 | document.removeEventListener("touchmove", handleTouchmove, false);
|
3039 | }
|
3040 |
|
3041 | function handleTouchmove(event) {
|
3042 | if (event.touches.length != 1) return;
|
3043 | drag(event.touches[0].clientX - drag_dx_origin);
|
3044 | }
|
3045 |
|
3046 | function drag(dx) {
|
3047 | var new_x = drag_x_origin + dx;
|
3048 | var slider_x = Math.max(0, Math.min(w, new_x));
|
3049 | var new_value = that.scale.invert(slider_x);
|
3050 | if (that._snap) new_value = snapTo(that._snap, new_value);
|
3051 | handle.attr("cx", that.scale(new_value));
|
3052 | if (new_value != that._value) {
|
3053 | that._value = new_value;
|
3054 | that.fire("change", that._value);
|
3055 | }
|
3056 | }
|
3057 |
|
3058 | handle = g.selectAll(".slider-handle").data([{ v: this._value, x: this.scale(this._value) }]);
|
3059 | handle = handle.enter().append("circle").attr("class", "slider-handle")
|
3060 | .attr("cursor", "col-resize")
|
3061 | .merge(handle);
|
3062 |
|
3063 | handle.attr("cx", function(d) { return d.x; })
|
3064 | .attr("r", this._handleRadius)
|
3065 | .attr("fill", this._handleFill)
|
3066 | .on("mousedown", function() {
|
3067 | event$1.preventDefault();
|
3068 | handleMousedown(event$1);
|
3069 | })
|
3070 | .on("touchstart", function() {
|
3071 | event$1.preventDefault();
|
3072 | handleTouchstart(event$1);
|
3073 | });
|
3074 |
|
3075 | var label_data = [];
|
3076 | if (this._label) {
|
3077 | label_data.push({
|
3078 | label: this._label, x: w/2, y: -label_h, font_size: this._labelSize
|
3079 | });
|
3080 | }
|
3081 | var label = g.selectAll(".slider-label").data(label_data);
|
3082 | label.exit().remove();
|
3083 | label = label.enter()
|
3084 | .append("text").attr("class", "slider-label")
|
3085 | .attr("text-anchor", "middle")
|
3086 | .attr("cursor", "default")
|
3087 | .merge(label);
|
3088 |
|
3089 | label
|
3090 | .text(function(d) { return d.label; })
|
3091 | .attr("x", function(d) { return d.x; })
|
3092 | .attr("y", function(d) { return d.y; })
|
3093 | .attr("font-size", this._labelSize);
|
3094 |
|
3095 | var end_label_data = [];
|
3096 | if (this._startLabel) {
|
3097 | end_label_data.push({
|
3098 | label: this._startLabel,
|
3099 | x: this._startLabelBelow ? 0 : -(channel_r + 5 + Math.max(0, this._handleRadius - channel_r)),
|
3100 | y: this._startLabelBelow ? (channel_r + 15) : this._startEndLabelSize/1.75 - channel_r/2,
|
3101 | anchor: this._startLabelBelow ? "middle" : "end",
|
3102 | font_size: this._startEndLabelSize
|
3103 | });
|
3104 | }
|
3105 | if (this._endLabel) {
|
3106 | end_label_data.push({
|
3107 | label: this._endLabel,
|
3108 | x: this._endLabelBelow ? w : w + (channel_r + Math.max(0, this._handleRadius - channel_r) + 5),
|
3109 | y: this._startLabelBelow ? (channel_r + 15) : this._startEndLabelSize/1.75 - channel_r/2,
|
3110 | anchor: this._endLabelBelow ? "middle" : "start",
|
3111 | font_size: this._startEndLabelSize
|
3112 | });
|
3113 | }
|
3114 |
|
3115 | var end_labels = g.selectAll(".slider-end-labels").data(end_label_data);
|
3116 | end_labels.exit().remove();
|
3117 | end_labels = end_labels.enter().append("text").attr("class", "slider-end-labels")
|
3118 | .attr("pointer-events", "none")
|
3119 | .merge(end_labels);
|
3120 | end_labels
|
3121 | .text(function(d) { return d.label; })
|
3122 | .attr("font-size", function(d) { return d.font_size; })
|
3123 | .attr("x", function(d) { return d.x; })
|
3124 | .attr("y", function(d) { return d.y; })
|
3125 | .attr("text-anchor", function(d) { return d.anchor; });
|
3126 |
|
3127 | return this;
|
3128 | };
|
3129 |
|
3130 | Slider.prototype.update = Slider.prototype.draw;
|
3131 |
|
3132 | function Flourish_slider(selector) {
|
3133 | return new Slider(selector);
|
3134 | }
|
3135 | Flourish_slider.version = VERSION;
|
3136 |
|
3137 | function createPlayButton(colour) {
|
3138 | var start_string = '<svg width="25px" height="30px" viewBox="0 0 25 30"> <polygon fill="';
|
3139 | var end_string = '" stroke="none" points="25 15 0 30 0 0"></polygon> </svg>';
|
3140 | return start_string + colour + end_string;
|
3141 | }
|
3142 |
|
3143 | function createPauseButton(colour) {
|
3144 | var start_string = '<svg width="26px" height="30px" viewBox="0 0 26 30"> <g stroke="none" stroke-width="1" fill="';
|
3145 | var end_string = '"><rect x="2" y="2" width="9" height="26"></rect> <rect x="15" y="2" width="9" height="26"></rect> </g> </svg>';
|
3146 | return start_string + colour + end_string;
|
3147 | }
|
3148 |
|
3149 | function createSlider(control_obj, state, container) {
|
3150 | var slider_obj = {};
|
3151 | var slider_holder = select(container).append("div").attr("class", "fl-control fl-control-slider animatable");
|
3152 | var slider_play_button = slider_holder.append("div").attr("class", "slider-play");
|
3153 | var slider_div = slider_holder.append("div").attr("class", "fl-controls-slider");
|
3154 |
|
3155 | var play_string, pause_string, handle_color;
|
3156 | var sorted_options, timesteps, slider_label, is_playing;
|
3157 | var timer_id = null;
|
3158 |
|
3159 | var clearTimer = function() {
|
3160 | clearTimeout(timer_id);
|
3161 | timer_id = null;
|
3162 | };
|
3163 |
|
3164 | var sliderChangeFunction = function(i) {
|
3165 | var d = sorted_options[i];
|
3166 | if (d.options_index === control_obj.index()) return;
|
3167 | control_obj.index(d.options_index);
|
3168 | control_obj.trigger("change");
|
3169 | };
|
3170 |
|
3171 | var slider = Flourish_slider(slider_div.node())
|
3172 | .snap(true)
|
3173 | .on("change", function(i) {
|
3174 | var is_playing = timer_id !== null;
|
3175 | if (is_playing) clearTimer();
|
3176 | sliderChangeFunction(i);
|
3177 | if (is_playing) setNextTick();
|
3178 | });
|
3179 |
|
3180 |
|
3181 | var stopSliderPlayer = function() {
|
3182 | clearTimer();
|
3183 | slider_holder.classed("playing", false);
|
3184 | slider_play_button.html(play_string);
|
3185 | control_obj._isPlaying_(false);
|
3186 | is_playing = false;
|
3187 | };
|
3188 |
|
3189 |
|
3190 | var setNextTick = function() {
|
3191 | var current_index = control_obj.getSortedIndex();
|
3192 | var current_delay = timesteps[current_index];
|
3193 | var final_index = control_obj.n_options - 1;
|
3194 | var next_index = current_index < final_index ? current_index + 1 : 0;
|
3195 |
|
3196 | timer_id = setTimeout(function() {
|
3197 | sliderChangeFunction(next_index);
|
3198 | if (state.slider_loop || next_index < final_index) setNextTick();
|
3199 | else stopSliderPlayer();
|
3200 | }, current_delay);
|
3201 | };
|
3202 |
|
3203 |
|
3204 | var startSliderPlayer = function() {
|
3205 | slider_holder.classed("playing", true);
|
3206 | slider_play_button.html(pause_string);
|
3207 | setNextTick();
|
3208 | control_obj._isPlaying_(true);
|
3209 | is_playing = true;
|
3210 | };
|
3211 |
|
3212 |
|
3213 | slider_play_button.on("click", function() {
|
3214 | if (timer_id === null) startSliderPlayer();
|
3215 | else stopSliderPlayer();
|
3216 | });
|
3217 |
|
3218 |
|
3219 | var setWidths = function() {
|
3220 | var handle_radius = Math.round(remToPx(state.slider_handle_height) / 2);
|
3221 | slider_holder.style("width", Math.round(remToPx(state.slider_width)) + "px");
|
3222 | slider_play_button
|
3223 | .style("height", handle_radius * 2 + "px")
|
3224 | .style("width", handle_radius * 2 + "px")
|
3225 | .style("display", state.slider_play_button ? null : "none");
|
3226 | var holder_width = slider_holder.node().getBoundingClientRect().width;
|
3227 | var button_width = slider_play_button.node().getBoundingClientRect().width;
|
3228 | slider_div
|
3229 | .style("width", Math.max((holder_width - button_width), 1) + "px")
|
3230 | .style("height", handle_radius * 2 + "px");
|
3231 |
|
3232 | slider
|
3233 | .handleRadius(handle_radius)
|
3234 | .margin({
|
3235 | left: handle_radius + 5,
|
3236 | right: handle_radius + remToPx(state.slider_margin),
|
3237 | top: handle_radius
|
3238 | });
|
3239 | };
|
3240 |
|
3241 |
|
3242 | var setHandles = function() {
|
3243 | if (state.slider_play_button) {
|
3244 | slider_holder.classed("animatable", true);
|
3245 | }
|
3246 | else {
|
3247 | stopSliderPlayer();
|
3248 | slider_holder.classed("animatable", false);
|
3249 | }
|
3250 | if (handle_color !== state.slider_handle_color) {
|
3251 | slider.update();
|
3252 | handle_color = state.slider_handle_color || "currentColor";
|
3253 | slider_holder.select(".slider-handle").style("fill", handle_color);
|
3254 | play_string = createPlayButton(handle_color);
|
3255 | pause_string = createPauseButton(handle_color);
|
3256 | slider_play_button.html(timer_id ? pause_string : play_string);
|
3257 | }
|
3258 | };
|
3259 |
|
3260 |
|
3261 | var showControl = function() {
|
3262 | slider_holder.style("display", "inline-block");
|
3263 | setWidths();
|
3264 | setHandles();
|
3265 | return slider_obj;
|
3266 | };
|
3267 |
|
3268 | var hideControl = function() {
|
3269 | stopSliderPlayer();
|
3270 | slider_holder.style("display", "none");
|
3271 | return slider_obj;
|
3272 | };
|
3273 |
|
3274 | slider_obj.show = showControl;
|
3275 | slider_obj.hide = hideControl;
|
3276 |
|
3277 |
|
3278 | slider_obj.update = function(_sorted_options) {
|
3279 | sorted_options = _sorted_options;
|
3280 | if (!control_obj.n_options || state.control_type !== "slider") {
|
3281 | hideControl();
|
3282 | return slider_obj;
|
3283 | }
|
3284 |
|
3285 | showControl();
|
3286 |
|
3287 | var n_options = control_obj.n_options;
|
3288 | var loop = state.slider_loop;
|
3289 |
|
3290 | timesteps = sorted_options.map(function(d, i) {
|
3291 | var dur_in_seconds = state.slider_step_time + (loop && i === (n_options -1) ? state.slider_restart_pause : 0);
|
3292 | return dur_in_seconds * 1000;
|
3293 | });
|
3294 |
|
3295 | var sorted_index = control_obj.getSortedIndex();
|
3296 | var d = sorted_options[sorted_index];
|
3297 |
|
3298 | slider.domain([0, n_options - 1])
|
3299 | .value(sorted_index)
|
3300 | .endLabel(d.display)
|
3301 | .channelHeight(Math.round(remToPx(state.slider_track_height)))
|
3302 | .channelFill(state.slider_background_color)
|
3303 | .update();
|
3304 |
|
3305 | slider.container.select("svg").attr("fill", "currentColor");
|
3306 |
|
3307 | slider_label = slider_label || slider_div.select("text.slider-end-labels");
|
3308 | slider_label
|
3309 | .style("fill", state.slider_font_color)
|
3310 | .attr("y", "0")
|
3311 | .attr("dy", "0.25em");
|
3312 |
|
3313 |
|
3314 | if (control_obj._isPlaying_() && !is_playing) startSliderPlayer();
|
3315 | else if (!control_obj._isPlaying_() && is_playing) stopSliderPlayer();
|
3316 |
|
3317 | return slider_obj;
|
3318 | };
|
3319 |
|
3320 |
|
3321 | return slider_obj;
|
3322 | }
|
3323 |
|
3324 | var DEFAULTS = Object.freeze({
|
3325 | control_type: "dropdown",
|
3326 | control_title: "",
|
3327 |
|
3328 |
|
3329 | dropdown_width_mode: "auto",
|
3330 | dropdown_width_fixed: 20,
|
3331 |
|
3332 |
|
3333 | button_group: true,
|
3334 | button_group_width_mode: "fixed",
|
3335 | button_group_width_fixed: 20,
|
3336 |
|
3337 |
|
3338 | slider_width: 15,
|
3339 | slider_handle_color: null,
|
3340 | slider_font_color: null,
|
3341 | slider_background_color: "#dddddd",
|
3342 |
|
3343 | slider_handle_height: 1,
|
3344 | slider_track_height: 0.2,
|
3345 | slider_margin: 4.5,
|
3346 |
|
3347 | slider_play_button: true,
|
3348 | slider_step_time: 2,
|
3349 | slider_loop: true,
|
3350 | slider_restart_pause: 0,
|
3351 |
|
3352 |
|
3353 | sort: false,
|
3354 |
|
3355 | _index_: null,
|
3356 | _is_playing_: false
|
3357 | });
|
3358 |
|
3359 | function defaultParser(x) {
|
3360 | return x;
|
3361 | }
|
3362 |
|
3363 | function defaultFormatter(x) {
|
3364 | return x == null ? "" : x.toString();
|
3365 | }
|
3366 |
|
3367 | function init(state) {
|
3368 | var control_obj = {};
|
3369 | var parser = defaultParser;
|
3370 | var formatter = defaultFormatter;
|
3371 | var options = [];
|
3372 | var sorted_options = [];
|
3373 | var changeHandlers = [];
|
3374 | var container = document.createElement("div");
|
3375 | container.setAttribute("class", "fl-controls-container");
|
3376 | var container_title = select(container).append("div").attr("class", "fl-controls-title");
|
3377 | var dropdown_obj = createDropdown(control_obj, state, container);
|
3378 | var buttons_obj = createButtons(control_obj, state, container);
|
3379 | var slider_obj = createSlider(control_obj, state, container);
|
3380 |
|
3381 | for (var key in DEFAULTS) {
|
3382 | if (state[key] === undefined) state[key] = DEFAULTS[key];
|
3383 | }
|
3384 |
|
3385 | var current_index = state._index_;
|
3386 |
|
3387 | var checkValidIndex = function(i) {
|
3388 | return options.length && i >= 0 && i < options.length;
|
3389 | };
|
3390 |
|
3391 | var updateControls = function(sorted_options) {
|
3392 | container.style.display = (sorted_options.length > 1) ? null : "none";
|
3393 | container.style.width = "";
|
3394 | container_title.node().innerHTML = state.control_title;
|
3395 | container_title.node().style.display = (state.control_title === "") ? "none" : "inline-block";
|
3396 | slider_obj.update(sorted_options);
|
3397 | dropdown_obj.update(sorted_options);
|
3398 | buttons_obj.update(sorted_options);
|
3399 | };
|
3400 |
|
3401 | control_obj.appendTo = function(parent_container, bounding_container) {
|
3402 | injectCSS();
|
3403 | select(parent_container).node().appendChild(container);
|
3404 | dropdown_obj.appendedToDOM(bounding_container);
|
3405 | return control_obj;
|
3406 | };
|
3407 |
|
3408 | var callOnChangeCallbacks = function() {
|
3409 | var index = indexFunction();
|
3410 | var value = options[index];
|
3411 | changeHandlers.forEach(function(func) {
|
3412 | func(value, index);
|
3413 | });
|
3414 | return control_obj;
|
3415 | };
|
3416 |
|
3417 | control_obj.remove = function() {
|
3418 | if (container.parentElement) container.parentElement.removeChild(container);
|
3419 | dropdown_obj.removedFromDOM();
|
3420 |
|
3421 | return control_obj;
|
3422 | };
|
3423 |
|
3424 | control_obj.options = function(arr) {
|
3425 | if (arr === undefined) return options.slice();
|
3426 | if (!Array.isArray(arr)) return control_obj;
|
3427 | options = arr.slice();
|
3428 | var n = options.length;
|
3429 | var i = indexFunction();
|
3430 | if (!n) indexFunction(null);
|
3431 | else if (i === null || i >= n) indexFunction(0);
|
3432 | return control_obj;
|
3433 | };
|
3434 |
|
3435 | Object.defineProperty(control_obj, "n_options", { get: function() { return options.length; } });
|
3436 |
|
3437 |
|
3438 | var indexFunction = function(i) {
|
3439 | if (i === undefined) {
|
3440 | if (!state._is_playing_) current_index = state._index_;
|
3441 | return current_index;
|
3442 | }
|
3443 | if (i === null || checkValidIndex(i)) {
|
3444 | current_index = i;
|
3445 | if (!state._is_playing_) state._index_ = current_index;
|
3446 | }
|
3447 | else console.warn("Invalid index, ignoring update call");
|
3448 | return control_obj;
|
3449 | };
|
3450 | control_obj.index = indexFunction;
|
3451 |
|
3452 | control_obj.getSortedIndex = function() {
|
3453 | var options_index = indexFunction();
|
3454 | if (state.sort == "unsorted") return options_index;
|
3455 | var sorted_index;
|
3456 | sorted_options.some(function(d, i) {
|
3457 | if (d.options_index === options_index) {
|
3458 | sorted_index = i;
|
3459 | return true;
|
3460 | }
|
3461 | });
|
3462 | return sorted_index;
|
3463 | };
|
3464 |
|
3465 | control_obj.value = function(value) {
|
3466 | if (value === undefined) return options[indexFunction()];
|
3467 | var index = options.indexOf(value);
|
3468 | if (index !== -1) indexFunction(index);
|
3469 | return control_obj;
|
3470 | };
|
3471 |
|
3472 | control_obj.on = function(event, callback) {
|
3473 | if (event === "change") changeHandlers.push(callback.bind(control_obj));
|
3474 | return control_obj;
|
3475 | };
|
3476 |
|
3477 | control_obj.parser = function (value) {
|
3478 | if (value === undefined) return parser;
|
3479 | if (value === null) parser = defaultParser;
|
3480 | else parser = value;
|
3481 | return control_obj;
|
3482 | };
|
3483 |
|
3484 | control_obj.formatter = function (value) {
|
3485 | if (value === undefined) return formatter;
|
3486 | if (value === null) formatter = defaultFormatter;
|
3487 | else formatter = value;
|
3488 | return control_obj;
|
3489 | };
|
3490 |
|
3491 | control_obj.update = function() {
|
3492 | getRemToPx();
|
3493 | sorted_options = sortArray(options, state.sort, parser, formatter);
|
3494 | updateControls(sorted_options);
|
3495 | return control_obj;
|
3496 | };
|
3497 |
|
3498 | control_obj.trigger = function(event) {
|
3499 | if (event === "change") callOnChangeCallbacks();
|
3500 | return control_obj;
|
3501 | };
|
3502 |
|
3503 | control_obj.getNode = function() {
|
3504 | return container;
|
3505 | };
|
3506 |
|
3507 | var isPlaying = function(is_playing) {
|
3508 | if (is_playing === undefined) return state._is_playing_;
|
3509 | state._is_playing_ = !!is_playing;
|
3510 | if (!is_playing) indexFunction(current_index);
|
3511 | };
|
3512 |
|
3513 | control_obj._isPlaying_ = isPlaying;
|
3514 |
|
3515 | return control_obj;
|
3516 | }
|
3517 |
|
3518 | return init;
|
3519 |
|
3520 | })));
|