UNPKG

ag-charts-community

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

482 lines 18.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var node_1 = require("./node"); var EnterNode = /** @class */ (function () { function EnterNode(parent, datum) { this.next = null; this.scene = parent.scene; this.parent = parent; this.datum = datum; } EnterNode.prototype.appendChild = function (node) { // This doesn't work without the `strict: true` in the `tsconfig.json`, // so we must have two `if` checks below, instead of this single one. // if (this.next && !Node.isNode(this.next)) { // throw new Error(`${this.next} is not a Node.`); // } if (this.next === null) { return this.parent.insertBefore(node, null); } if (!node_1.Node.isNode(this.next)) { throw new Error(this.next + " is not a Node."); } return this.parent.insertBefore(node, this.next); }; EnterNode.prototype.insertBefore = function (node, nextNode) { return this.parent.insertBefore(node, nextNode); }; return EnterNode; }()); exports.EnterNode = EnterNode; /** * G - type of the selected node(s). * GDatum - type of the datum of the selected node(s). * P - type of the parent node(s). * PDatum - type of the datum of the parent node(s). */ var Selection = /** @class */ (function () { function Selection(groups, parents) { this.groups = groups; this.parents = parents; } Selection.select = function (node) { return new Selection([[typeof node === 'function' ? node() : node]], [undefined]); }; Selection.selectAll = function (nodes) { return new Selection([nodes == null ? [] : nodes], [undefined]); }; /** * Creates new nodes, appends them to the nodes of this selection and returns them * as a new selection. The created nodes inherit the datums and the parents of the nodes * they replace. * @param Class The constructor function to use to create the new nodes. */ Selection.prototype.append = function (Class) { return this.select(function (node) { return node.appendChild(new Class()); }); }; /** * Same as the {@link append}, but accepts a custom creator function with the * {@link NodeSelector} signature rather than a constructor function. * @param creator */ Selection.prototype.appendFn = function (creator) { return this.select(function (node, data, index, group) { return node.appendChild(creator(node, data, index, group)); }); }; /** * Runs the given selector that returns a single node for every node in each group. * The original nodes are then replaced by the nodes returned by the selector * and returned as a new selection. * The selected nodes inherit the datums and the parents of the original nodes. */ Selection.prototype.select = function (selector) { var groups = this.groups; var numGroups = groups.length; var subgroups = []; for (var j = 0; j < numGroups; j++) { var group = groups[j]; var groupSize = group.length; var subgroup = subgroups[j] = new Array(groupSize); for (var i = 0; i < groupSize; i++) { var node = group[i]; if (node) { var subnode = selector(node, node.datum, i, group); if (subnode) { subnode.datum = node.datum; } subgroup[i] = subnode; } // else this can be a group of the `enter` selection, // for example, with no nodes at the i-th position, // only nodes at the end of the group } } return new Selection(subgroups, this.parents); }; /** * Same as {@link select}, but uses the given {@param Class} (constructor) as a selector. * @param Class The constructor function to use to find matching nodes. */ Selection.prototype.selectByClass = function (Class) { return this.select(function (node) { if (node_1.Node.isNode(node)) { var children = node.children; var n = children.length; for (var i = 0; i < n; i++) { var child = children[i]; if (child instanceof Class) { return child; } } } }); }; Selection.prototype.selectByTag = function (tag) { return this.select(function (node) { if (node_1.Node.isNode(node)) { var children = node.children; var n = children.length; for (var i = 0; i < n; i++) { var child = children[i]; if (child.tag === tag) { return child; } } } }); }; Selection.prototype.selectAllByClass = function (Class) { return this.selectAll(function (node) { var nodes = []; if (node_1.Node.isNode(node)) { var children = node.children; var n = children.length; for (var i = 0; i < n; i++) { var child = children[i]; if (child instanceof Class) { nodes.push(child); } } } return nodes; }); }; Selection.prototype.selectAllByTag = function (tag) { return this.selectAll(function (node) { var nodes = []; if (node_1.Node.isNode(node)) { var children = node.children; var n = children.length; for (var i = 0; i < n; i++) { var child = children[i]; if (child.tag === tag) { nodes.push(child); } } } return nodes; }); }; Selection.prototype.selectNone = function () { return []; }; /** * Runs the given selector that returns a group of nodes for every node in each group. * The original nodes are then replaced by the groups of nodes returned by the selector * and returned as a new selection. The original nodes become the parent nodes for each * group in the new selection. The selected nodes do not inherit the datums of the original nodes. * If called without any parameters, creates a new selection with an empty group for each * node in this selection. */ Selection.prototype.selectAll = function (selectorAll) { if (!selectorAll) { selectorAll = this.selectNone; } // Each subgroup is populated with the selector (run on each group node) results. var subgroups = []; // In the new selection that we return, subgroups become groups, // and group nodes become parents. var parents = []; var groups = this.groups; var groupCount = groups.length; for (var j = 0; j < groupCount; j++) { var group = groups[j]; var groupLength = group.length; for (var i = 0; i < groupLength; i++) { var node = group[i]; if (node) { subgroups.push(selectorAll(node, node.datum, i, group)); parents.push(node); } } } return new Selection(subgroups, parents); }; /** * Runs the given callback for every node in this selection and returns this selection. * @param cb */ Selection.prototype.each = function (cb) { var groups = this.groups; var numGroups = groups.length; for (var j = 0; j < numGroups; j++) { var group = groups[j]; var groupSize = group.length; for (var i = 0; i < groupSize; i++) { var node = group[i]; if (node) { cb(node, node.datum, i, group); } } } return this; }; Selection.prototype.remove = function () { return this.each(function (node) { if (node_1.Node.isNode(node)) { var parent_1 = node.parent; if (parent_1) { parent_1.removeChild(node); } } }); }; Selection.prototype.merge = function (other) { var groups0 = this.groups; var groups1 = other.groups; var m0 = groups0.length; var m1 = groups1.length; var m = Math.min(m0, m1); var merges = new Array(m0); var j = 0; for (; j < m; j++) { var group0 = groups0[j]; var group1 = groups1[j]; var n = group0.length; var merge = merges[j] = new Array(n); for (var i = 0; i < n; i++) { var node = group0[i] || group1[i]; merge[i] = node || undefined; } } for (; j < m0; j++) { merges[j] = groups0[j]; } return new Selection(merges, this.parents); }; /** * Return the first non-null element in this selection. * If the selection is empty, returns null. */ Selection.prototype.node = function () { var groups = this.groups; var numGroups = groups.length; for (var j = 0; j < numGroups; j++) { var group = groups[j]; var groupSize = group.length; for (var i = 0; i < groupSize; i++) { var node = group[i]; if (node) { return node; } } } return null; }; Selection.prototype.attr = function (name, value) { this.each(function (node) { node[name] = value; }); return this; }; Selection.prototype.attrFn = function (name, value) { this.each(function (node, datum, index, group) { node[name] = value(node, datum, index, group); }); return this; }; /** * Invokes the given function once, passing in this selection. * Returns this selection. Facilitates method chaining. * @param cb */ Selection.prototype.call = function (cb) { cb(this); return this; }; Object.defineProperty(Selection.prototype, "size", { /** * Returns the total number of nodes in this selection. */ get: function () { var size = 0; this.each(function () { return size++; }); return size; }, enumerable: true, configurable: true }); Object.defineProperty(Selection.prototype, "data", { /** * Returns the array of data for the selected elements. */ get: function () { var data = []; this.each(function (_, datum) { return data.push(datum); }); return data; }, enumerable: true, configurable: true }); Object.defineProperty(Selection.prototype, "enter", { get: function () { return new Selection(this.enterGroups ? this.enterGroups : [[]], this.parents); }, enumerable: true, configurable: true }); Object.defineProperty(Selection.prototype, "exit", { get: function () { return new Selection(this.exitGroups ? this.exitGroups : [[]], this.parents); }, enumerable: true, configurable: true }); /** * Binds the given value to each selected node and returns this selection * with its {@link GDatum} type changed to the type of the given value. * This method doesn't compute a join and doesn't affect indexes or the enter and exit selections. * This method can also be used to clear bound data. * @param value */ Selection.prototype.setDatum = function (value) { return this.each(function (node) { node.datum = value; }); }; Object.defineProperty(Selection.prototype, "datum", { /** * Returns the bound datum for the first non-null element in the selection. * This is generally useful only if you know the selection contains exactly one element. */ get: function () { var node = this.node(); return node ? node.datum : null; }, enumerable: true, configurable: true }); /** * Binds the specified array of values with the selected nodes, returning a new selection * that represents the _update_ selection: the nodes successfully bound to the values. * Also defines the {@link enter} and {@link exit} selections on the returned selection, * which can be used to add or remove the nodes to correspond to the new data. * The `values` is an array of values of a particular type, or a function that returns * an array of values for each group. * When values are assigned to the nodes, they are stored in the {@link Node.datum} property. * @param values * @param key */ Selection.prototype.setData = function (values, key) { if (typeof values !== 'function') { var data_1 = values; values = function () { return data_1; }; } var groups = this.groups; var parents = this.parents; var numGroups = groups.length; var updateGroups = new Array(numGroups); var enterGroups = new Array(numGroups); var exitGroups = new Array(numGroups); for (var j = 0; j < numGroups; j++) { var group = groups[j]; var parent_2 = parents[j]; if (!parent_2) { throw new Error("Group #" + j + " has no parent: " + group); } var groupSize = group.length; var data = values(parent_2, parent_2.datum, j, parents); var dataSize = data.length; var enterGroup = enterGroups[j] = new Array(dataSize); var updateGroup = updateGroups[j] = new Array(dataSize); var exitGroup = exitGroups[j] = new Array(groupSize); if (key) { this.bindKey(parent_2, group, enterGroup, updateGroup, exitGroup, data, key); } else { this.bindIndex(parent_2, group, enterGroup, updateGroup, exitGroup, data); } // 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; i0 < dataSize; i0++) { var previous = enterGroup[i0]; if (previous) { if (i0 >= i1) { i1 = i0 + 1; } var next = void 0; while (!(next = updateGroup[i1]) && i1 < dataSize) { i1++; } previous.next = next || null; } } } var result = new Selection(updateGroups, parents); result.enterGroups = enterGroups; result.exitGroups = exitGroups; return result; }; Selection.prototype.bindIndex = function (parent, group, enter, update, exit, data) { var groupSize = group.length; var dataSize = data.length; var i = 0; for (; i < dataSize; i++) { var node = group[i]; if (node) { node.datum = data[i]; update[i] = node; } else { // more datums than group nodes enter[i] = new EnterNode(parent, data[i]); } } // more group nodes than datums for (; i < groupSize; i++) { var node = group[i]; if (node) { exit[i] = node; } } }; Selection.prototype.bindKey = function (parent, group, enter, update, exit, data, key) { var groupSize = group.length; var dataSize = data.length; var keyValues = new Array(groupSize); var nodeByKeyValue = {}; // Compute the key for each node. // If multiple nodes have the same key, the duplicates are added to exit. for (var i = 0; i < groupSize; i++) { var node = group[i]; if (node) { var keyValue = keyValues[i] = Selection.keyPrefix + key(node, node.datum, i, group); if (keyValue in nodeByKeyValue) { exit[i] = node; } else { nodeByKeyValue[keyValue] = node; } } } // Compute the key for each datum. // If there is 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 (var i = 0; i < dataSize; i++) { var keyValue = Selection.keyPrefix + key(parent, data[i], i, data); var node = nodeByKeyValue[keyValue]; if (node) { update[i] = node; node.datum = data[i]; nodeByKeyValue[keyValue] = undefined; } else { enter[i] = new EnterNode(parent, data[i]); } } // Add any remaining nodes that were not bound to data to exit. for (var i = 0; i < groupSize; i++) { var node = group[i]; if (node && (nodeByKeyValue[keyValues[i]] === node)) { exit[i] = node; } } }; Selection.keyPrefix = '$'; // Protect against keys like '__proto__'. return Selection; }()); exports.Selection = Selection; //# sourceMappingURL=selection.js.map