| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- import { __classPrivateFieldGet, __read, __spreadArray, __values } from "tslib";
- import { group } from 'd3-array';
- import { Circle, Ellipse, Group, HTML, Image, Line, Path, Polygon, Polyline, Rect, Text } from '../shapes';
- function error(msg) {
- throw new Error(msg);
- }
- /**
- * A simple implementation of d3-selection for @antv/g.
- * It has the core features of d3-selection and extended ability.
- * Every methods of selection returns new selection if elements
- * are mutated(e.g. append, remove), otherwise return the selection itself(e.g. attr, style).
- * @see https://github.com/d3/d3-selection
- * @see https://github.com/antvis/g
- * @todo Nested selections.
- * @todo More useful functor.
- */
- var Selection = /** @class */ (function () {
- function Selection(elements, data, parent, document, selections, transitions, updateElements) {
- if (elements === void 0) { elements = null; }
- if (data === void 0) { data = null; }
- if (parent === void 0) { parent = null; }
- if (document === void 0) { document = null; }
- if (selections === void 0) { selections = [null, null, null, null, null]; }
- if (transitions === void 0) { transitions = []; }
- if (updateElements === void 0) { updateElements = []; }
- _Selection_instances.add(this);
- this._elements = Array.from(elements);
- this._data = data;
- this._parent = parent;
- this._document = document;
- this._enter = selections[0];
- this._update = selections[1];
- this._exit = selections[2];
- this._merge = selections[3];
- this._split = selections[4];
- this._transitions = transitions;
- this._facetElements = updateElements;
- }
- Selection.prototype.selectAll = function (selector) {
- var elements = typeof selector === 'string' ? this._parent.querySelectorAll(selector) : selector;
- return new Selection(elements, null, this._elements[0], this._document);
- };
- Selection.prototype.selectFacetAll = function (selector) {
- var elements = typeof selector === 'string' ? this._parent.querySelectorAll(selector) : selector;
- return new Selection(this._elements, null, this._parent, this._document, undefined, undefined, elements);
- };
- /**
- * @todo Replace with querySelector which has bug now.
- */
- Selection.prototype.select = function (selector) {
- var element = typeof selector === 'string' ? this._parent.querySelectorAll(selector)[0] || null : selector;
- return new Selection([element], null, element, this._document);
- };
- Selection.prototype.append = function (node) {
- var _this = this;
- var callback = typeof node === 'function' ? node : function () { return _this.createElement(node); };
- var elements = [];
- if (this._data !== null) {
- // For empty selection, append new element to parent.
- // Each element is bind with datum.
- for (var i = 0; i < this._data.length; i++) {
- var d = this._data[i];
- var _a = __read(Array.isArray(d) ? d : [d, null], 2), datum = _a[0], from = _a[1];
- var newElement = callback(datum, i);
- newElement.__data__ = datum;
- if (from !== null)
- newElement.__fromElements__ = from;
- this._parent.appendChild(newElement);
- elements.push(newElement);
- }
- return new Selection(elements, null, this._parent, this._document);
- }
- // For non-empty selection, append new element to
- // selected element and return new selection.
- for (var i = 0; i < this._elements.length; i++) {
- var element = this._elements[i];
- var datum = element.__data__;
- var newElement = callback(datum, i);
- element.appendChild(newElement);
- elements.push(newElement);
- }
- return new Selection(elements, null, elements[0], this._document);
- };
- Selection.prototype.maybeAppend = function (id, node) {
- var element = __classPrivateFieldGet(this, _Selection_instances, "m", _Selection_maybeAppend).call(this, id[0] === '#' ? id : "#".concat(id), node);
- element.attr('id', id);
- return element;
- };
- Selection.prototype.maybeAppendByClassName = function (className, node) {
- var cls = className.toString();
- var element = __classPrivateFieldGet(this, _Selection_instances, "m", _Selection_maybeAppend).call(this, cls[0] === '.' ? cls : ".".concat(cls), node);
- element.attr('className', cls);
- return element;
- };
- Selection.prototype.maybeAppendByName = function (name, node) {
- var element = __classPrivateFieldGet(this, _Selection_instances, "m", _Selection_maybeAppend).call(this, "[name=\"".concat(name, "\"]"), node);
- element.attr('name', name);
- return element;
- };
- /**
- * Bind data to elements, and produce three selection:
- * Enter: Selection with empty elements and data to be bind to elements.
- * Update: Selection with elements to be updated.
- * Exit: Selection with elements to be removed.
- */
- Selection.prototype.data = function (data, id, groupId) {
- var e_1, _a;
- if (id === void 0) { id = function (d) { return d; }; }
- if (groupId === void 0) { groupId = function () { return null; }; }
- // An Array of new data.
- var enter = [];
- // An Array of elements to be updated.
- var update = [];
- // A Set of elements to be removed.
- var exit = new Set(this._elements);
- // An Array of data to be merged into one element.
- var merge = [];
- // A Set of elements to be split into multiple datum.
- var split = new Set();
- // A Map from key to each element.
- var keyElement = new Map(this._elements.map(function (d, i) { return [id(d.__data__, i), d]; }));
- // A Map from key to exist element. The Update Selection
- // can get element from this map, this is for diff among
- // facets.
- var keyUpdateElement = new Map(this._facetElements.map(function (d, i) { return [id(d.__data__, i), d]; }));
- // A Map from groupKey to a group of elements.
- var groupKeyElements = group(this._elements, function (d) { return groupId(d.__data__); });
- // Diff data with selection(elements with data).
- // !!! Note
- // The switch is strictly ordered, not not change the order of them.
- for (var i = 0; i < data.length; i++) {
- var datum = data[i];
- var key = id(datum, i);
- var groupKey = groupId(datum, i);
- // Append element to update selection if incoming data has
- // exactly the same key with elements.
- if (keyElement.has(key)) {
- var element = keyElement.get(key);
- element.__data__ = datum;
- element.__facet__ = false;
- update.push(element);
- exit.delete(element);
- keyElement.delete(key);
- // Append element to update selection if incoming data has
- // exactly the same key with updateElements.
- }
- else if (keyUpdateElement.has(key)) {
- var element = keyUpdateElement.get(key);
- element.__data__ = datum;
- // Flag this element should update its parentNode.
- element.__facet__ = true;
- update.push(element);
- keyUpdateElement.delete(key);
- // Append datum to merge selection if existed elements has
- // its key as groupKey.
- }
- else if (groupKeyElements.has(key)) {
- var group_2 = groupKeyElements.get(key);
- merge.push([datum, group_2]);
- try {
- for (var group_1 = (e_1 = void 0, __values(group_2)), group_1_1 = group_1.next(); !group_1_1.done; group_1_1 = group_1.next()) {
- var element = group_1_1.value;
- exit.delete(element);
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (group_1_1 && !group_1_1.done && (_a = group_1.return)) _a.call(group_1);
- }
- finally { if (e_1) throw e_1.error; }
- }
- groupKeyElements.delete(key);
- // Append element to split selection if incoming data has
- // groupKey as its key, and bind to datum for it.
- }
- else if (keyElement.has(groupKey)) {
- var element = keyElement.get(groupKey);
- if (element.__toData__)
- element.__toData__.push(datum);
- else
- element.__toData__ = [datum];
- split.add(element);
- exit.delete(element);
- }
- else {
- enter.push(datum);
- }
- }
- // Create new selection with enter, update and exit.
- var S = [
- new Selection([], enter, this._parent, this._document),
- new Selection(update, null, this._parent, this._document),
- new Selection(exit, null, this._parent, this._document),
- new Selection([], merge, this._parent, this._document),
- new Selection(split, null, this._parent, this._document),
- ];
- return new Selection(this._elements, null, this._parent, this._document, S);
- };
- Selection.prototype.merge = function (other) {
- var elements = __spreadArray(__spreadArray([], __read(this._elements), false), __read(other._elements), false);
- var transitions = __spreadArray(__spreadArray([], __read(this._transitions), false), __read(other._transitions), false);
- return new Selection(elements, null, this._parent, this._document, undefined, transitions);
- };
- Selection.prototype.createElement = function (type) {
- if (this._document) {
- return this._document.createElement(type, {});
- }
- var Ctor = Selection.registry[type];
- if (Ctor)
- return new Ctor();
- return error("Unknown node type: ".concat(type));
- };
- /**
- * Apply callback for each selection(enter, update, exit)
- * and merge them into one selection.
- */
- Selection.prototype.join = function (enter, update, exit, merge, split) {
- if (enter === void 0) { enter = function (d) { return d; }; }
- if (update === void 0) { update = function (d) { return d; }; }
- if (exit === void 0) { exit = function (d) { return d.remove(); }; }
- if (merge === void 0) { merge = function (d) { return d; }; }
- if (split === void 0) { split = function (d) { return d.remove(); }; }
- var newEnter = enter(this._enter);
- var newUpdate = update(this._update);
- var newExit = exit(this._exit);
- var newMerge = merge(this._merge);
- var newSplit = split(this._split);
- return newUpdate.merge(newEnter).merge(newExit).merge(newMerge).merge(newSplit);
- };
- Selection.prototype.remove = function () {
- var _loop_1 = function (i) {
- var element = this_1._elements[i];
- var transition = this_1._transitions[i];
- if (transition) {
- transition.then(function () { return element.remove(); });
- }
- else {
- element.remove();
- }
- };
- var this_1 = this;
- // Remove node immediately if there is no transition,
- // otherwise wait until transition finished.
- for (var i = 0; i < this._elements.length; i++) {
- _loop_1(i);
- }
- return new Selection([], null, this._parent, this._document, undefined, this._transitions);
- };
- Selection.prototype.each = function (callback) {
- for (var i = 0; i < this._elements.length; i++) {
- var element = this._elements[i];
- var datum = element.__data__;
- callback.call(element, datum, i);
- }
- return this;
- };
- Selection.prototype.attr = function (key, value) {
- var callback = typeof value !== 'function' ? function () { return value; } : value;
- return this.each(function (d, i) {
- if (value !== undefined)
- this[key] = callback.call(this, d, i);
- });
- };
- Selection.prototype.style = function (key, value, callbackable) {
- if (callbackable === void 0) { callbackable = true; }
- var callback = typeof value !== 'function' || !callbackable ? function () { return value; } : value;
- return this.each(function (d, i) {
- if (value !== undefined)
- this.style[key] = callback.call(this, d, i);
- });
- };
- Selection.prototype.styles = function (style, callbackable) {
- if (style === void 0) { style = {}; }
- if (callbackable === void 0) { callbackable = true; }
- return this.each(function (d, i) {
- var _this = this;
- Object.entries(style).forEach(function (_a) {
- var _b = __read(_a, 2), key = _b[0], value = _b[1];
- var callback = typeof value !== 'function' || !callbackable ? function () { return value; } : value;
- if (value !== undefined)
- _this.attr(key, callback.call(_this, d, i));
- });
- });
- };
- Selection.prototype.update = function (option, callbackable) {
- if (callbackable === void 0) { callbackable = true; }
- var callback = typeof option !== 'function' || !callbackable ? function () { return option; } : option;
- return this.each(function (d, i) {
- if (option && this.update)
- this.update(callback.call(this, d, i));
- });
- };
- /** if current stage is maybeAppend, skip update stage */
- Selection.prototype.maybeUpdate = function (option, callbackable) {
- if (callbackable === void 0) { callbackable = true; }
- var callback = typeof option !== 'function' || !callbackable ? function () { return option; } : option;
- return this.each(function (d, i) {
- if (option && this.update)
- this.update(callback.call(this, d, i));
- });
- };
- Selection.prototype.transition = function (callback) {
- var T = this._transitions;
- return this.each(function (d, i) {
- T[i] = callback.call(this, d, i);
- });
- };
- Selection.prototype.on = function (event, handler) {
- this.each(function () {
- this.addEventListener(event, handler);
- });
- return this;
- };
- Selection.prototype.call = function (callback) {
- var args = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- args[_i - 1] = arguments[_i];
- }
- callback.call.apply(callback, __spreadArray([this._parent, this], __read(args), false));
- return this;
- };
- Selection.prototype.node = function () {
- return this._elements[0];
- };
- Selection.prototype.nodes = function () {
- return this._elements;
- };
- Selection.prototype.transitions = function () {
- return this._transitions.filter(function (t) { return !!t; });
- };
- Selection.prototype.parent = function () {
- return this._parent;
- };
- var _Selection_instances, _Selection_maybeAppend;
- _Selection_instances = new WeakSet(), _Selection_maybeAppend = function _Selection_maybeAppend(selector, node) {
- var element = this._elements[0];
- var child = element.querySelector(selector);
- if (child)
- return new Selection([child], null, this._parent, this._document);
- var newChild = typeof node === 'string' ? this.createElement(node) : node();
- element.appendChild(newChild);
- return new Selection([newChild], null, this._parent, this._document);
- };
- Selection.registry = {
- g: Group,
- rect: Rect,
- circle: Circle,
- path: Path,
- text: Text,
- ellipse: Ellipse,
- image: Image,
- line: Line,
- polygon: Polygon,
- polyline: Polyline,
- html: HTML,
- };
- return Selection;
- }());
- export { Selection };
- export function select(node) {
- return new Selection([node], null, node, node.ownerDocument);
- }
- export function maybeAppend(parent, selector, node) {
- if (!parent.querySelector(selector)) {
- return select(parent).append(node);
- }
- return select(parent).select(selector);
- }
- //# sourceMappingURL=selection.js.map
|