UNPKG

d3-svg-annotation

Version:

Full documentation: [http://d3-annotation.susielu.com](http://d3-annotation.susielu.com)

1,878 lines (1,575 loc) 124 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3 = global.d3 || {}))); }(this, (function (exports) { 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; var Annotation = function () { function Annotation(_ref) { var _ref$x = _ref.x, x = _ref$x === undefined ? 0 : _ref$x, _ref$y = _ref.y, y = _ref$y === undefined ? 0 : _ref$y, nx = _ref.nx, ny = _ref.ny, _ref$dy = _ref.dy, dy = _ref$dy === undefined ? 0 : _ref$dy, _ref$dx = _ref.dx, dx = _ref$dx === undefined ? 0 : _ref$dx, _ref$color = _ref.color, color = _ref$color === undefined ? "grey" : _ref$color, data = _ref.data, type = _ref.type, subject = _ref.subject, connector = _ref.connector, note = _ref.note, disable = _ref.disable, id = _ref.id, className = _ref.className; classCallCheck(this, Annotation); this._dx = nx !== undefined ? nx - x : dx; this._dy = ny !== undefined ? ny - y : dy; this._x = x; this._y = y; this._color = color; this.id = id; this._className = className || ""; this._type = type || ""; this.data = data; this.note = note || {}; this.connector = connector || {}; this.subject = subject || {}; this.disable = disable || []; } createClass(Annotation, [{ key: "updatePosition", value: function updatePosition() { if (this.type.setPosition) { this.type.setPosition(); if (this.type.subject && this.type.subject.selectAll(":not(.handle)").nodes().length !== 0) { this.type.redrawSubject(); } } } }, { key: "clearComponents", value: function clearComponents() { this.type.clearComponents && this.type.clearComponents(); } }, { key: "updateOffset", value: function updateOffset() { if (this.type.setOffset) { this.type.setOffset(); if (this.type.connector.selectAll(":not(.handle)").nodes().length !== 0) { this.type.redrawConnector(); } this.type.redrawNote(); } } }, { key: "className", get: function get$$1() { return this._className; }, set: function set$$1(className) { this._className = className; if (this.type.setClassName) this.type.setClassName(); } }, { key: "type", get: function get$$1() { return this._type; }, set: function set$$1(type) { this._type = type; this.clearComponents(); } }, { key: "x", get: function get$$1() { return this._x; }, set: function set$$1(x) { this._x = x; this.updatePosition(); } }, { key: "y", get: function get$$1() { return this._y; }, set: function set$$1(y) { this._y = y; this.updatePosition(); } }, { key: "color", get: function get$$1() { return this._color; }, set: function set$$1(color) { this._color = color; this.updatePosition(); } }, { key: "dx", get: function get$$1() { return this._dx; }, set: function set$$1(dx) { this._dx = dx; this.updateOffset(); } }, { key: "dy", get: function get$$1() { return this._dy; }, set: function set$$1(dy) { this._dy = dy; this.updateOffset(); } }, { key: "nx", set: function set$$1(nx) { this._dx = nx - this._x; this.updateOffset(); } }, { key: "ny", set: function set$$1(ny) { this._dy = ny - this._y; this.updateOffset(); } }, { key: "offset", get: function get$$1() { return { x: this._dx, y: this._dy }; }, set: function set$$1(_ref2) { var x = _ref2.x, y = _ref2.y; this._dx = x; this._dy = y; this.updateOffset(); } }, { key: "position", get: function get$$1() { return { x: this._x, y: this._y }; }, set: function set$$1(_ref3) { var x = _ref3.x, y = _ref3.y; this._x = x; this._y = y; this.updatePosition(); } }, { key: "translation", get: function get$$1() { return { x: this._x + this._dx, y: this._y + this._dy }; } }, { key: "json", get: function get$$1() { var json = { x: this._x, y: this._y, dx: this._dx, dy: this._dy }; if (this.data && Object.keys(this.data).length > 0) json.data = this.data; if (this.type) json.type = this.type; if (this._className) json.className = this._className; if (Object.keys(this.connector).length > 0) json.connector = this.connector; if (Object.keys(this.subject).length > 0) json.subject = this.subject; if (Object.keys(this.note).length > 0) json.note = this.note; return json; } }]); return Annotation; }(); var AnnotationCollection = function () { function AnnotationCollection(_ref) { var annotations = _ref.annotations, accessors = _ref.accessors, accessorsInverse = _ref.accessorsInverse; classCallCheck(this, AnnotationCollection); this.accessors = accessors; this.accessorsInverse = accessorsInverse; this.annotations = annotations; } createClass(AnnotationCollection, [{ key: "clearTypes", value: function clearTypes(newSettings) { this.annotations.forEach(function (d) { d.type = undefined; d.subject = newSettings && newSettings.subject || d.subject; d.connector = newSettings && newSettings.connector || d.connector; d.note = newSettings && newSettings.note || d.note; }); } }, { key: "setPositionWithAccessors", value: function setPositionWithAccessors() { var _this = this; this.annotations.forEach(function (d) { d.type.setPositionWithAccessors(_this.accessors); }); } }, { key: "editMode", value: function editMode(_editMode) { this.annotations.forEach(function (a) { if (a.type) { a.type.editMode = _editMode; a.type.updateEditMode(); } }); } }, { key: "updateDisable", value: function updateDisable(disable) { this.annotations.forEach(function (a) { a.disable = disable; if (a.type) { disable.forEach(function (d) { if (a.type[d]) { a.type[d].remove && a.type[d].remove(); a.type[d] = undefined; } }); } }); } }, { key: "updateTextWrap", value: function updateTextWrap(textWrap) { this.annotations.forEach(function (a) { if (a.type && a.type.updateTextWrap) { a.type.updateTextWrap(textWrap); } }); } }, { key: "updateText", value: function updateText() { this.annotations.forEach(function (a) { if (a.type && a.type.drawText) { a.type.drawText(); } }); } }, { key: "updateNotePadding", value: function updateNotePadding(notePadding) { this.annotations.forEach(function (a) { if (a.type) { a.type.notePadding = notePadding; } }); } }, { key: "json", get: function get$$1() { var _this2 = this; return this.annotations.map(function (a) { var json = a.json; if (_this2.accessorsInverse && a.data) { json.data = {}; Object.keys(_this2.accessorsInverse).forEach(function (k) { json.data[k] = _this2.accessorsInverse[k]({ x: a.x, y: a.y }); //TODO make this feasible to map back to data for other types of subjects }); } return json; }); } }, { key: "noteNodes", get: function get$$1() { return this.annotations.map(function (a) { return _extends({}, a.type.getNoteBBoxOffset(), { positionX: a.x, positionY: a.y }); }); } //TODO: come back and rethink if a.x and a.y are applicable in all situations // get connectorNodes() { // return this.annotations.map(a => ({ ...a.type.getConnectorBBox(), startX: a.x, startY: a.y})) // } // get subjectNodes() { // return this.annotations.map(a => ({ ...a.type.getSubjectBBox(), startX: a.x, startY: a.y})) // } // get annotationNodes() { // return this.annotations.map(a => ({ ...a.type.getAnnotationBBox(), startX: a.x, startY: a.y})) // } }]); return AnnotationCollection; }(); var xhtml = "http://www.w3.org/1999/xhtml"; var namespaces = { svg: "http://www.w3.org/2000/svg", xhtml: xhtml, xlink: "http://www.w3.org/1999/xlink", xml: "http://www.w3.org/XML/1998/namespace", xmlns: "http://www.w3.org/2000/xmlns/" }; var namespace = function (name) { var prefix = name += "", i = prefix.indexOf(":"); if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); return namespaces.hasOwnProperty(prefix) ? { space: namespaces[prefix], local: name } : name; }; function creatorInherit(name) { return function () { var document = this.ownerDocument, uri = this.namespaceURI; return uri === xhtml && document.documentElement.namespaceURI === xhtml ? document.createElement(name) : document.createElementNS(uri, name); }; } function creatorFixed(fullname) { return function () { return this.ownerDocument.createElementNS(fullname.space, fullname.local); }; } var creator = function (name) { var fullname = namespace(name); return (fullname.local ? creatorFixed : creatorInherit)(fullname); }; function none() {} var selector = function (selector) { return selector == null ? none : function () { return this.querySelector(selector); }; }; var selection_select = function (select) { if (typeof select !== "function") select = selector(select); for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { if ("__data__" in node) subnode.__data__ = node.__data__; subgroup[i] = subnode; } } } return new Selection(subgroups, this._parents); }; function empty() { return []; } var selectorAll = function (selector) { return selector == null ? empty : function () { return this.querySelectorAll(selector); }; }; var selection_selectAll = function (select) { if (typeof select !== "function") select = selectorAll(select); for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { if (node = group[i]) { subgroups.push(select.call(node, node.__data__, i, group)); parents.push(node); } } } return new Selection(subgroups, parents); }; var matcher = function (selector) { return function () { return this.matches(selector); }; }; var selection_filter = function (match) { if (typeof match !== "function") match = matcher(match); for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { if ((node = group[i]) && match.call(node, node.__data__, i, group)) { subgroup.push(node); } } } return new Selection(subgroups, this._parents); }; var sparse = function (update) { return new Array(update.length); }; var selection_enter = function () { return new Selection(this._enter || this._groups.map(sparse), this._parents); }; function EnterNode(parent, datum) { this.ownerDocument = parent.ownerDocument; this.namespaceURI = parent.namespaceURI; this._next = null; this._parent = parent; this.__data__ = datum; } EnterNode.prototype = { constructor: EnterNode, appendChild: function appendChild(child) { return this._parent.insertBefore(child, this._next); }, insertBefore: function insertBefore(child, next) { return this._parent.insertBefore(child, next); }, querySelector: function querySelector(selector) { return this._parent.querySelector(selector); }, querySelectorAll: function querySelectorAll(selector) { return this._parent.querySelectorAll(selector); } }; var constant = function (x) { return function () { return x; }; }; var keyPrefix = "$"; // Protect against keys like “__proto__”. function bindIndex(parent, group, enter, update, exit, data) { var i = 0, node, groupLength = group.length, dataLength = data.length; // Put any non-null nodes that fit into update. // Put any null nodes into enter. // Put any remaining data into enter. for (; i < dataLength; ++i) { if (node = group[i]) { node.__data__ = data[i]; update[i] = node; } else { enter[i] = new EnterNode(parent, data[i]); } } // Put any non-null nodes that don’t fit into exit. for (; i < groupLength; ++i) { if (node = group[i]) { exit[i] = node; } } } function bindKey(parent, group, enter, update, exit, data, key) { var i, node, nodeByKeyValue = {}, groupLength = group.length, dataLength = data.length, keyValues = new Array(groupLength), keyValue; // Compute the key for each node. // If multiple nodes have the same key, the duplicates are added to exit. for (i = 0; i < groupLength; ++i) { if (node = group[i]) { keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); if (keyValue in nodeByKeyValue) { exit[i] = node; } else { nodeByKeyValue[keyValue] = node; } } } // Compute the key for each datum. // If there a node associated with this key, join and add it to update. // If there is not (or the key is a duplicate), add it to enter. for (i = 0; i < dataLength; ++i) { keyValue = keyPrefix + key.call(parent, data[i], i, data); if (node = nodeByKeyValue[keyValue]) { update[i] = node; node.__data__ = data[i]; nodeByKeyValue[keyValue] = null; } else { enter[i] = new EnterNode(parent, data[i]); } } // Add any remaining nodes that were not bound to data to exit. for (i = 0; i < groupLength; ++i) { if ((node = group[i]) && nodeByKeyValue[keyValues[i]] === node) { exit[i] = node; } } } var selection_data = function (value, key) { if (!value) { data = new Array(this.size()), j = -1; this.each(function (d) { data[++j] = d; }); return data; } var bind = key ? bindKey : bindIndex, parents = this._parents, groups = this._groups; if (typeof value !== "function") value = constant(value); for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { var parent = parents[j], group = groups[j], groupLength = group.length, data = value.call(parent, parent && parent.__data__, j, parents), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength); bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); // Now connect the enter nodes to their following update node, such that // appendChild can insert the materialized enter node before this node, // rather than at the end of the parent node. for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { if (previous = enterGroup[i0]) { if (i0 >= i1) i1 = i0 + 1; while (!(next = updateGroup[i1]) && ++i1 < dataLength) {} previous._next = next || null; } } } update = new Selection(update, parents); update._enter = enter; update._exit = exit; return update; }; var selection_exit = function () { return new Selection(this._exit || this._groups.map(sparse), this._parents); }; var selection_join = function (onenter, onupdate, onexit) { var enter = this.enter(), update = this, exit = this.exit(); enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + ""); if (onupdate != null) update = onupdate(update); if (onexit == null) exit.remove();else onexit(exit); return enter && update ? enter.merge(update).order() : update; }; var selection_merge = function (selection) { 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) { for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { if (node = group0[i] || group1[i]) { merge[i] = node; } } } for (; j < m0; ++j) { merges[j] = groups0[j]; } return new Selection(merges, this._parents); }; var selection_order = function () { for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { if (node = group[i]) { if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next); next = node; } } } return this; }; var selection_sort = function (compare) { if (!compare) compare = ascending; function compareNode(a, b) { return a && b ? compare(a.__data__, b.__data__) : !a - !b; } for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { if (node = group[i]) { sortgroup[i] = node; } } sortgroup.sort(compareNode); } return new Selection(sortgroups, this._parents).order(); }; function ascending(a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; } var selection_call = function () { var callback = arguments[0]; arguments[0] = this; callback.apply(null, arguments); return this; }; var selection_nodes = function () { var nodes = new Array(this.size()), i = -1; this.each(function () { nodes[++i] = this; }); return nodes; }; var selection_node = function () { for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { var node = group[i]; if (node) return node; } } return null; }; var selection_size = function () { var size = 0; this.each(function () { ++size; }); return size; }; var selection_empty = function () { return !this.node(); }; var selection_each = function (callback) { for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { if (node = group[i]) callback.call(node, node.__data__, i, group); } } return this; }; function attrRemove(name) { return function () { this.removeAttribute(name); }; } function attrRemoveNS(fullname) { return function () { this.removeAttributeNS(fullname.space, fullname.local); }; } function attrConstant(name, value) { return function () { this.setAttribute(name, value); }; } function attrConstantNS(fullname, value) { return function () { this.setAttributeNS(fullname.space, fullname.local, value); }; } function attrFunction(name, value) { return function () { var v = value.apply(this, arguments); if (v == null) this.removeAttribute(name);else this.setAttribute(name, v); }; } function attrFunctionNS(fullname, value) { return function () { var v = value.apply(this, arguments); if (v == null) this.removeAttributeNS(fullname.space, fullname.local);else this.setAttributeNS(fullname.space, fullname.local, v); }; } var selection_attr = function (name, value) { var fullname = namespace(name); if (arguments.length < 2) { var node = this.node(); return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname); } return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === "function" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value)); }; var defaultView = function (node) { return node.ownerDocument && node.ownerDocument.defaultView || // node is a Node node.document && node // node is a Window || node.defaultView; // node is a Document }; function styleRemove(name) { return function () { this.style.removeProperty(name); }; } function styleConstant(name, value, priority) { return function () { this.style.setProperty(name, value, priority); }; } function styleFunction(name, value, priority) { return function () { var v = value.apply(this, arguments); if (v == null) this.style.removeProperty(name);else this.style.setProperty(name, v, priority); }; } var selection_style = function (name, value, priority) { return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === "function" ? styleFunction : styleConstant)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name); }; function styleValue(node, name) { return node.style.getPropertyValue(name) || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); } function propertyRemove(name) { return function () { delete this[name]; }; } function propertyConstant(name, value) { return function () { this[name] = value; }; } function propertyFunction(name, value) { return function () { var v = value.apply(this, arguments); if (v == null) delete this[name];else this[name] = v; }; } var selection_property = function (name, value) { return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name]; }; function classArray(string) { return string.trim().split(/^|\s+/); } function classList(node) { return node.classList || new ClassList(node); } function ClassList(node) { this._node = node; this._names = classArray(node.getAttribute("class") || ""); } ClassList.prototype = { add: function add(name) { var i = this._names.indexOf(name); if (i < 0) { this._names.push(name); this._node.setAttribute("class", this._names.join(" ")); } }, remove: function remove(name) { var i = this._names.indexOf(name); if (i >= 0) { this._names.splice(i, 1); this._node.setAttribute("class", this._names.join(" ")); } }, contains: function contains(name) { return this._names.indexOf(name) >= 0; } }; function classedAdd(node, names) { var list = classList(node), i = -1, n = names.length; while (++i < n) { list.add(names[i]); } } function classedRemove(node, names) { var list = classList(node), i = -1, n = names.length; while (++i < n) { list.remove(names[i]); } } function classedTrue(names) { return function () { classedAdd(this, names); }; } function classedFalse(names) { return function () { classedRemove(this, names); }; } function classedFunction(names, value) { return function () { (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); }; } var selection_classed = function (name, value) { var names = classArray(name + ""); if (arguments.length < 2) { var list = classList(this.node()), i = -1, n = names.length; while (++i < n) { if (!list.contains(names[i])) return false; }return true; } return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value)); }; function textRemove() { this.textContent = ""; } function textConstant(value) { return function () { this.textContent = value; }; } function textFunction(value) { return function () { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; }; } var selection_text = function (value) { return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction : textConstant)(value)) : this.node().textContent; }; function htmlRemove() { this.innerHTML = ""; } function htmlConstant(value) { return function () { this.innerHTML = value; }; } function htmlFunction(value) { return function () { var v = value.apply(this, arguments); this.innerHTML = v == null ? "" : v; }; } var selection_html = function (value) { return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML; }; function raise() { if (this.nextSibling) this.parentNode.appendChild(this); } var selection_raise = function () { return this.each(raise); }; function lower() { if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); } var selection_lower = function () { return this.each(lower); }; var selection_append = function (name) { var create = typeof name === "function" ? name : creator(name); return this.select(function () { return this.appendChild(create.apply(this, arguments)); }); }; function constantNull() { return null; } var selection_insert = function (name, before) { var create = typeof name === "function" ? name : creator(name), select = before == null ? constantNull : typeof before === "function" ? before : selector(before); return this.select(function () { return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); }); }; function remove() { var parent = this.parentNode; if (parent) parent.removeChild(this); } var selection_remove = function () { return this.each(remove); }; function selection_cloneShallow() { return this.parentNode.insertBefore(this.cloneNode(false), this.nextSibling); } function selection_cloneDeep() { return this.parentNode.insertBefore(this.cloneNode(true), this.nextSibling); } var selection_clone = function (deep) { return this.select(deep ? selection_cloneDeep : selection_cloneShallow); }; var selection_datum = function (value) { return arguments.length ? this.property("__data__", value) : this.node().__data__; }; var filterEvents = {}; var event = null; if (typeof document !== "undefined") { var element = document.documentElement; if (!("onmouseenter" in element)) { filterEvents = { mouseenter: "mouseover", mouseleave: "mouseout" }; } } function filterContextListener(listener, index, group) { listener = contextListener(listener, index, group); return function (event) { var related = event.relatedTarget; if (!related || related !== this && !(related.compareDocumentPosition(this) & 8)) { listener.call(this, event); } }; } function contextListener(listener, index, group) { return function (event1) { var event0 = event; // Events can be reentrant (e.g., focus). event = event1; try { listener.call(this, this.__data__, index, group); } finally { event = event0; } }; } function parseTypenames(typenames) { return typenames.trim().split(/^|\s+/).map(function (t) { var name = "", i = t.indexOf("."); if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); return { type: t, name: name }; }); } function onRemove(typename) { return function () { var on = this.__on; if (!on) return; for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { this.removeEventListener(o.type, o.listener, o.capture); } else { on[++i] = o; } } if (++i) on.length = i;else delete this.__on; }; } function onAdd(typename, value, capture) { var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; return function (d, i, group) { var on = this.__on, o, listener = wrap(value, i, group); if (on) for (var j = 0, m = on.length; j < m; ++j) { if ((o = on[j]).type === typename.type && o.name === typename.name) { this.removeEventListener(o.type, o.listener, o.capture); this.addEventListener(o.type, o.listener = listener, o.capture = capture); o.value = value; return; } } this.addEventListener(typename.type, listener, capture); o = { type: typename.type, name: typename.name, value: value, listener: listener, capture: capture }; if (!on) this.__on = [o];else on.push(o); }; } var selection_on = function (typename, value, capture) { var typenames = parseTypenames(typename + ""), i, n = typenames.length, t; if (arguments.length < 2) { var on = this.node().__on; if (on) for (var j = 0, m = on.length, o; j < m; ++j) { for (i = 0, o = on[j]; i < n; ++i) { if ((t = typenames[i]).type === o.type && t.name === o.name) { return o.value; } } } return; } on = value ? onAdd : onRemove; if (capture == null) capture = false; for (i = 0; i < n; ++i) { this.each(on(typenames[i], value, capture)); }return this; }; function customEvent(event1, listener, that, args) { var event0 = event; event1.sourceEvent = event; event = event1; try { return listener.apply(that, args); } finally { event = event0; } } function dispatchEvent(node, type, params) { var window = defaultView(node), event = window.CustomEvent; if (typeof event === "function") { event = new event(type, params); } else { event = window.document.createEvent("Event"); if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;else event.initEvent(type, false, false); } node.dispatchEvent(event); } function dispatchConstant(type, params) { return function () { return dispatchEvent(this, type, params); }; } function dispatchFunction(type, params) { return function () { return dispatchEvent(this, type, params.apply(this, arguments)); }; } var selection_dispatch = function (type, params) { return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params)); }; var root = [null]; function Selection(groups, parents) { this._groups = groups; this._parents = parents; } function selection() { return new Selection([[document.documentElement]], root); } Selection.prototype = selection.prototype = { constructor: Selection, select: selection_select, selectAll: selection_selectAll, filter: selection_filter, data: selection_data, enter: selection_enter, exit: selection_exit, join: selection_join, merge: selection_merge, order: selection_order, sort: selection_sort, call: selection_call, nodes: selection_nodes, node: selection_node, size: selection_size, empty: selection_empty, each: selection_each, attr: selection_attr, style: selection_style, property: selection_property, classed: selection_classed, text: selection_text, html: selection_html, raise: selection_raise, lower: selection_lower, append: selection_append, insert: selection_insert, remove: selection_remove, clone: selection_clone, datum: selection_datum, on: selection_on, dispatch: selection_dispatch }; var select = function (selector) { return typeof selector === "string" ? new Selection([[document.querySelector(selector)]], [document.documentElement]) : new Selection([[selector]], root); }; var sourceEvent = function () { var current = event, source; while (source = current.sourceEvent) { current = source; }return current; }; var point = function (node, event) { var svg = node.ownerSVGElement || node; if (svg.createSVGPoint) { var point = svg.createSVGPoint(); point.x = event.clientX, point.y = event.clientY; point = point.matrixTransform(node.getScreenCTM().inverse()); return [point.x, point.y]; } var rect = node.getBoundingClientRect(); return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; }; var mouse = function (node) { var event = sourceEvent(); if (event.changedTouches) event = event.changedTouches[0]; return point(node, event); }; var touch = function (node, touches, identifier) { if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { if ((touch = touches[i]).identifier === identifier) { return point(node, touch); } } return null; }; var noop = { value: function value() {} }; function dispatch() { for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { if (!(t = arguments[i] + "") || t in _) throw new Error("illegal type: " + t); _[t] = []; } return new Dispatch(_); } function Dispatch(_) { this._ = _; } function parseTypenames$1(typenames, types) { return typenames.trim().split(/^|\s+/).map(function (t) { var name = "", i = t.indexOf("."); if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); return { type: t, name: name }; }); } Dispatch.prototype = dispatch.prototype = { constructor: Dispatch, on: function on(typename, callback) { var _ = this._, T = parseTypenames$1(typename + "", _), t, i = -1, n = T.length; // If no callback was specified, return the callback of the given type and name. if (arguments.length < 2) { while (++i < n) { if ((t = (typename = T[i]).type) && (t = get$1(_[t], typename.name))) return t; }return; } // If a type was specified, set the callback for the given type and name. // Otherwise, if a null callback was specified, remove callbacks of the given name. if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); while (++i < n) { if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback);else if (callback == null) for (t in _) { _[t] = set$1(_[t], typename.name, null); } } return this; }, copy: function copy() { var copy = {}, _ = this._; for (var t in _) { copy[t] = _[t].slice(); }return new Dispatch(copy); }, call: function call(type, that) { if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) { args[i] = arguments[i + 2]; }if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); for (t = this._[type], i = 0, n = t.length; i < n; ++i) { t[i].value.apply(that, args); } }, apply: function apply(type, that, args) { if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); for (var t = this._[type], i = 0, n = t.length; i < n; ++i) { t[i].value.apply(that, args); } } }; function get$1(type, name) { for (var i = 0, n = type.length, c; i < n; ++i) { if ((c = type[i]).name === name) { return c.value; } } } function set$1(type, name, callback) { for (var i = 0, n = type.length; i < n; ++i) { if (type[i].name === name) { type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); break; } } if (callback != null) type.push({ name: name, value: callback }); return type; } function nopropagation() { event.stopImmediatePropagation(); } var noevent = function () { event.preventDefault(); event.stopImmediatePropagation(); }; var nodrag = function (view) { var root = view.document.documentElement, selection$$1 = select(view).on("dragstart.drag", noevent, true); if ("onselectstart" in root) { selection$$1.on("selectstart.drag", noevent, true); } else { root.__noselect = root.style.MozUserSelect; root.style.MozUserSelect = "none"; } }; function yesdrag(view, noclick) { var root = view.document.documentElement, selection$$1 = select(view).on("dragstart.drag", null); if (noclick) { selection$$1.on("click.drag", noevent, true); setTimeout(function () { selection$$1.on("click.drag", null); }, 0); } if ("onselectstart" in root) { selection$$1.on("selectstart.drag", null); } else { root.style.MozUserSelect = root.__noselect; delete root.__noselect; } } var constant$1 = function (x) { return function () { return x; }; }; function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) { this.target = target; this.type = type; this.subject = subject; this.identifier = id; this.active = active; this.x = x; this.y = y; this.dx = dx; this.dy = dy; this._ = dispatch; } DragEvent.prototype.on = function () { var value = this._.on.apply(this._, arguments); return value === this._ ? this : value; }; // Ignore right-click, since that should open the context menu. function defaultFilter() { return !event.button; } function defaultContainer() { return this.parentNode; } function defaultSubject(d) { return d == null ? { x: event.x, y: event.y } : d; } function defaultTouchable() { return "ontouchstart" in this; } var drag = function () { var filter = defaultFilter, container = defaultContainer, subject = defaultSubject, touchable = defaultTouchable, gestures = {}, listeners = dispatch("start", "drag", "end"), active = 0, mousedownx, mousedowny, mousemoving, touchending, clickDistance2 = 0; function drag(selection$$1) { selection$$1.on("mousedown.drag", mousedowned).filter(touchable).on("touchstart.drag", touchstarted).on("touchmove.drag", touchmoved).on("touchend.drag touchcancel.drag", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); } function mousedowned() { if (touchending || !filter.apply(this, arguments)) return; var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments); if (!gesture) return; select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); nodrag(event.view); nopropagation(); mousemoving = false; mousedownx = event.clientX; mousedowny = event.clientY; gesture("start"); } function mousemoved() { noevent(); if (!mousemoving) { var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny; mousemoving = dx * dx + dy * dy > clickDistance2; } gestures.mouse("drag"); } function mouseupped() { select(event.view).on("mousemove.drag mouseup.drag", null); yesdrag(event.view, mousemoving); noevent(); gestures.mouse("end"); } function touchstarted() { if (!filter.apply(this, arguments)) return; var touches$$1 = event.changedTouches, c = container.apply(this, arguments), n = touches$$1.length, i, gesture; for (i = 0; i < n; ++i) { if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) { nopropagation(); gesture("start"); } } } function touchmoved() { var touches$$1 = event.changedTouches, n = touches$$1.length, i, gesture; for (i = 0; i < n; ++i) { if (gesture = gestures[touches$$1[i].identifier]) { noevent(); gesture("drag"); } } } function touchended() { var touches$$1 = event.changedTouches, n = touches$$1.length, i, gesture; if (touchending) clearTimeout(touchending); touchending = setTimeout(function () { touchending = null; }, 500); // Ghost clicks are delayed! for (i = 0; i < n; ++i) { if (gesture = gestures[touches$$1[i].identifier]) { nopropagation(); gesture("end"); } } } function beforestart(id, container, point, that, args) { var p = point(container, id), s, dx, dy, sublisteners = listeners.copy(); if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function () { if ((event.subject = s = subject.apply(that, args)) == null) return false; dx = s.x - p[0] || 0; dy = s.y - p[1] || 0; return true; })) return; return function gesture(type) { var p0 = p, n; switch (type) { case "start": gestures[id] = gesture, n = active++;break; case "end": delete gestures[id], --active; // nobreak case "drag": p = point(container, id), n = active;break; } customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); }; } drag.filter = function (_) { return arguments.length ? (filter = typeof _ === "function" ? _ : constant$1(!!_), drag) : filter; }; drag.container = function (_) { return arguments.length ? (container = typeof _ === "function" ? _ : constant$1(_), drag) : container; }; drag.subject = function (_) { return arguments.length ? (subject = typeof _ === "function" ? _ : constant$1(_), drag) : subject; }; drag.touchable = function (_) { return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$1(!!_), drag) : touchable; }; drag.on = function () { var value = listeners.on.apply(listeners, arguments); return value === listeners ? drag : value; }; drag.clickDistance = function (_) { return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); }; return drag; }; var pointHandle = function pointHandle(_ref) { var _ref$cx = _ref.cx, cx = _ref$cx === undefined ? 0 : _ref$cx, _ref$cy = _ref.cy, cy = _ref$cy === undefined ? 0 : _ref$cy; return { move: { x: cx, y: cy } }; }; var circleHandles = function circleHandles(_ref2) { var _ref2$cx = _ref2.cx, cx = _ref2$cx === undefined ? 0 : _ref2$cx, _ref2$cy = _ref2.cy, cy = _ref2$cy === undefined ? 0 : _ref2$cy, r1 = _ref2.r1, r2 = _ref2.r2, padding = _ref2.padding; var h = { move: { x: cx, y: cy } }; if (r1 !== undefined) { h.r1 = { x: cx + r1 / Math.sqrt(2), y: cy + r1 / Math.sqrt(2) }; } if (r2 !== undefined) { h.r2 = { x: cx + r2 / Math.sqrt(2), y: cy + r2 / Math.sqrt(2) }; } if (padding !== undefined) { h.padding = { x: cx + r1 + padding, y: cy }; } return h; }; //arc handles var addHandles = function addHandles(_ref5) { var group = _ref5.group, handles = _ref5.handles, _ref5$r = _ref5.r, r = _ref5$r === undefined ? 10 : _ref5$r; //give it a group and x,y to draw handles //then give it instructions on what the handles change var h = group.selectAll("circle.handle").data(handles); h.enter().append("circle").attr("class", "handle").attr("fill", "grey").attr("fill-opacity", 0.1).attr("cursor", "move").attr("stroke-dasharray", 5).attr("stroke", "grey").call(drag().container(select("g.annotations").node()).on("start", function (d) { return d.start && d.start(d); }).on("drag", function (d) { return d.drag && d.drag(d); }).on("end", function (d) { return d.end && d.end(d); })); group.selectAll("circle.handle").attr("cx", function (d) { return d.x; }).attr("cy", function (d) { return d.y; }).attr("r", function (d) { return d.r || r; }).attr("class", function (d) { return "handle " + (d.className || ""); }); h.exit().remove(); }; var leftRightDynamic = function leftRightDynamic(align, y) { if (align === "dynamic" || align === "left" || align === "right") { if (y < 0) { align = "top"; } else { align = "bottom"; } } return align; }; var topBottomDynamic = function topBottomDynamic(align, x) { if (align === "dynamic" || align === "top" || align === "bottom") { if (x < 0) { align = "right"; } else { align = "left"; } } return align; }; var orientationTopBottom = ["topBottom", "top", "bottom"]; var orientationLeftRight = ["leftRight", "left", "right"]; var noteAlignment = (function (_ref) { var _ref$padding = _ref.padding, padding = _ref$padding === undefined ? 0 : _ref$padding, _ref$bbox = _ref.bbox, bbox = _ref$bbox === undefined ? { x: 0, y: 0, width: 0, height: 0 } : _ref$bbox, align = _ref.align, orientation = _ref.orientation, _ref$offset = _ref.offset, offset = _ref$offset === undefined ? { x: 0, y: 0 } : _ref$offset; var x = -bbox.x; var y = 0; //-bbox.y if (orientationTopBottom.indexOf(orientation) !== -1) { align = topBottomDynamic(align, offset.x); if (offset.y < 0 && orientation === "topBottom" || orientation === "top") { y -= bbox.height + padding; } else { y += padding; } if (align === "middle") { x -= bbox.width / 2; } else if (align === "right") { x -= bbox.width; } } else if (orientationLeftRight.indexOf(orientation) !== -1) { align = leftRightDynamic(align, offset.y); if (offset.x < 0 && orientation === "leftRight" || orientation === "left") { x -= bbox.width + padding; } else { x += padding; } if (align === "middle") { y -= bbox.height / 2; } else if (align === "top") { y -= bbox.height; } } return { x: x, y: y }; }); var pi = Math.PI; var tau = 2 * pi; var epsilon = 1e-6; var tauEpsilon = tau - epsilon; function Path() { this._x0 = this._y0 = // start of current subpath this._x1 = this._y1 = null; // end of current subpath this._ = ""; } function path() { return new Path(); } Path.prototype = path.prototype = { constructor: Path, moveTo: function moveTo(x, y) { this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); }, closePath: function closePath() { if (this._x1 !== null) { this._x1 = this._x0, this._y1 = this._y0; this._ += "Z"; } }, lineTo: function lineTo(x, y) { this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); }, quadraticCurveTo: function quadraticCurveTo(x1, y1, x, y) { this._ += "Q" + +x1 + "," + +y1 + "," + (this._x1 = +x) + "," + (this._y1 =