d3-svg-annotation
Version:
Full documentation: [http://d3-annotation.susielu.com](http://d3-annotation.susielu.com)
1,878 lines (1,575 loc) • 124 kB
JavaScript
(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 =