1
0
mirror of https://gitlab.com/JKANetwork/CheckServer.git synced 2026-04-05 02:02:01 +02:00

Start again

This commit is contained in:
2020-10-04 17:14:00 +02:00
parent c0d3912413
commit 091f119048
4382 changed files with 1762543 additions and 9606 deletions

120
vendors/echarts/src/data/DataDiffer.js vendored Normal file
View File

@@ -0,0 +1,120 @@
define(function(require) {
'use strict';
function defaultKeyGetter(item) {
return item;
}
function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter) {
this._old = oldArr;
this._new = newArr;
this._oldKeyGetter = oldKeyGetter || defaultKeyGetter;
this._newKeyGetter = newKeyGetter || defaultKeyGetter;
}
DataDiffer.prototype = {
constructor: DataDiffer,
/**
* Callback function when add a data
*/
add: function (func) {
this._add = func;
return this;
},
/**
* Callback function when update a data
*/
update: function (func) {
this._update = func;
return this;
},
/**
* Callback function when remove a data
*/
remove: function (func) {
this._remove = func;
return this;
},
execute: function () {
var oldArr = this._old;
var newArr = this._new;
var oldKeyGetter = this._oldKeyGetter;
var newKeyGetter = this._newKeyGetter;
var oldDataIndexMap = {};
var newDataIndexMap = {};
var i;
initIndexMap(oldArr, oldDataIndexMap, oldKeyGetter);
initIndexMap(newArr, newDataIndexMap, newKeyGetter);
// Travel by inverted order to make sure order consistency
// when duplicate keys exists (consider newDataIndex.pop() below).
// For performance consideration, these code below do not look neat.
for (i = 0; i < oldArr.length; i++) {
var key = oldKeyGetter(oldArr[i]);
var idx = newDataIndexMap[key];
// idx can never be empty array here. see 'set null' logic below.
if (idx != null) {
// Consider there is duplicate key (for example, use dataItem.name as key).
// We should make sure every item in newArr and oldArr can be visited.
var len = idx.length;
if (len) {
len === 1 && (newDataIndexMap[key] = null);
idx = idx.unshift();
}
else {
newDataIndexMap[key] = null;
}
this._update && this._update(idx, i);
}
else {
this._remove && this._remove(i);
}
}
for (var key in newDataIndexMap) {
if (newDataIndexMap.hasOwnProperty(key)) {
var idx = newDataIndexMap[key];
if (idx == null) {
continue;
}
// idx can never be empty array here. see 'set null' logic above.
if (!idx.length) {
this._add && this._add(idx);
}
else {
for (var i = 0, len = idx.length; i < len; i++) {
this._add && this._add(idx[i]);
}
}
}
}
}
};
function initIndexMap(arr, map, keyGetter) {
for (var i = 0; i < arr.length; i++) {
var key = keyGetter(arr[i]);
var existence = map[key];
if (existence == null) {
map[key] = i;
}
else {
if (!existence.length) {
map[key] = existence = [existence];
}
existence.push(i);
}
}
}
return DataDiffer;
});

515
vendors/echarts/src/data/Graph.js vendored Normal file
View File

@@ -0,0 +1,515 @@
/**
* Graph data structure
*
* @module echarts/data/Graph
* @author Yi Shen(https://www.github.com/pissang)
*/
define(function(require) {
'use strict';
var zrUtil = require('zrender/core/util');
/**
* @alias module:echarts/data/Graph
* @constructor
* @param {boolean} directed
*/
var Graph = function(directed) {
/**
* 是否是有向图
* @type {boolean}
* @private
*/
this._directed = directed || false;
/**
* @type {Array.<module:echarts/data/Graph.Node>}
* @readOnly
*/
this.nodes = [];
/**
* @type {Array.<module:echarts/data/Graph.Edge>}
* @readOnly
*/
this.edges = [];
/**
* @type {Object.<string, module:echarts/data/Graph.Node>}
* @private
*/
this._nodesMap = {};
/**
* @type {Object.<string, module:echarts/data/Graph.Edge>}
* @private
*/
this._edgesMap = {};
/**
* @type {module:echarts/data/List}
* @readOnly
*/
this.data;
/**
* @type {module:echarts/data/List}
* @readOnly
*/
this.edgeData;
};
var graphProto = Graph.prototype;
/**
* @type {string}
*/
graphProto.type = 'graph';
/**
* If is directed graph
* @return {boolean}
*/
graphProto.isDirected = function () {
return this._directed;
};
/**
* Add a new node
* @param {string} id
* @param {number} [dataIndex]
*/
graphProto.addNode = function (id, dataIndex) {
id = id || ('' + dataIndex);
var nodesMap = this._nodesMap;
if (nodesMap[id]) {
return;
}
var node = new Node(id, dataIndex);
node.hostGraph = this;
this.nodes.push(node);
nodesMap[id] = node;
return node;
};
/**
* Get node by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto.getNodeByIndex = function (dataIndex) {
var rawIdx = this.data.getRawIndex(dataIndex);
return this.nodes[rawIdx];
};
/**
* Get node by id
* @param {string} id
* @return {module:echarts/data/Graph.Node}
*/
graphProto.getNodeById = function (id) {
return this._nodesMap[id];
};
/**
* Add a new edge
* @param {number|string|module:echarts/data/Graph.Node} n1
* @param {number|string|module:echarts/data/Graph.Node} n2
* @param {number} [dataIndex=-1]
* @return {module:echarts/data/Graph.Edge}
*/
graphProto.addEdge = function (n1, n2, dataIndex) {
var nodesMap = this._nodesMap;
var edgesMap = this._edgesMap;
// PNEDING
if (typeof n1 === 'number') {
n1 = this.nodes[n1];
}
if (typeof n2 === 'number') {
n2 = this.nodes[n2];
}
if (!(n1 instanceof Node)) {
n1 = nodesMap[n1];
}
if (!(n2 instanceof Node)) {
n2 = nodesMap[n2];
}
if (!n1 || !n2) {
return;
}
var key = n1.id + '-' + n2.id;
// PENDING
if (edgesMap[key]) {
return;
}
var edge = new Edge(n1, n2, dataIndex);
edge.hostGraph = this;
if (this._directed) {
n1.outEdges.push(edge);
n2.inEdges.push(edge);
}
n1.edges.push(edge);
if (n1 !== n2) {
n2.edges.push(edge);
}
this.edges.push(edge);
edgesMap[key] = edge;
return edge;
};
/**
* Get edge by data index
* @param {number} dataIndex
* @return {module:echarts/data/Graph~Node}
*/
graphProto.getEdgeByIndex = function (dataIndex) {
var rawIdx = this.edgeData.getRawIndex(dataIndex);
return this.edges[rawIdx];
};
/**
* Get edge by two linked nodes
* @param {module:echarts/data/Graph.Node|string} n1
* @param {module:echarts/data/Graph.Node|string} n2
* @return {module:echarts/data/Graph.Edge}
*/
graphProto.getEdge = function (n1, n2) {
if (n1 instanceof Node) {
n1 = n1.id;
}
if (n2 instanceof Node) {
n2 = n2.id;
}
var edgesMap = this._edgesMap;
if (this._directed) {
return edgesMap[n1 + '-' + n2];
} else {
return edgesMap[n1 + '-' + n2]
|| edgesMap[n2 + '-' + n1];
}
};
/**
* Iterate all nodes
* @param {Function} cb
* @param {*} [context]
*/
graphProto.eachNode = function (cb, context) {
var nodes = this.nodes;
var len = nodes.length;
for (var i = 0; i < len; i++) {
if (nodes[i].dataIndex >= 0) {
cb.call(context, nodes[i], i);
}
}
};
/**
* Iterate all edges
* @param {Function} cb
* @param {*} [context]
*/
graphProto.eachEdge = function (cb, context) {
var edges = this.edges;
var len = edges.length;
for (var i = 0; i < len; i++) {
if (edges[i].dataIndex >= 0
&& edges[i].node1.dataIndex >= 0
&& edges[i].node2.dataIndex >= 0
) {
cb.call(context, edges[i], i);
}
}
};
/**
* Breadth first traverse
* @param {Function} cb
* @param {module:echarts/data/Graph.Node} startNode
* @param {string} [direction='none'] 'none'|'in'|'out'
* @param {*} [context]
*/
graphProto.breadthFirstTraverse = function (
cb, startNode, direction, context
) {
if (!(startNode instanceof Node)) {
startNode = this._nodesMap[startNode];
}
if (!startNode) {
return;
}
var edgeType = direction === 'out'
? 'outEdges' : (direction === 'in' ? 'inEdges' : 'edges');
for (var i = 0; i < this.nodes.length; i++) {
this.nodes[i].__visited = false;
}
if (cb.call(context, startNode, null)) {
return;
}
var queue = [startNode];
while (queue.length) {
var currentNode = queue.shift();
var edges = currentNode[edgeType];
for (var i = 0; i < edges.length; i++) {
var e = edges[i];
var otherNode = e.node1 === currentNode
? e.node2 : e.node1;
if (!otherNode.__visited) {
if (cb.call(otherNode, otherNode, currentNode)) {
// Stop traversing
return;
}
queue.push(otherNode);
otherNode.__visited = true;
}
}
}
};
// TODO
// graphProto.depthFirstTraverse = function (
// cb, startNode, direction, context
// ) {
// };
// Filter update
graphProto.update = function () {
var data = this.data;
var edgeData = this.edgeData;
var nodes = this.nodes;
var edges = this.edges;
for (var i = 0, len = nodes.length; i < len; i++) {
nodes[i].dataIndex = -1;
}
for (var i = 0, len = data.count(); i < len; i++) {
nodes[data.getRawIndex(i)].dataIndex = i;
}
edgeData.filterSelf(function (idx) {
var edge = edges[edgeData.getRawIndex(idx)];
return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0;
});
// Update edge
for (var i = 0, len = edges.length; i < len; i++) {
edges[i].dataIndex = -1;
}
for (var i = 0, len = edgeData.count(); i < len; i++) {
edges[edgeData.getRawIndex(i)].dataIndex = i;
}
};
/**
* @return {module:echarts/data/Graph}
*/
graphProto.clone = function () {
var graph = new Graph(this._directed);
var nodes = this.nodes;
var edges = this.edges;
for (var i = 0; i < nodes.length; i++) {
graph.addNode(nodes[i].id, nodes[i].dataIndex);
}
for (var i = 0; i < edges.length; i++) {
var e = edges[i];
graph.addEdge(e.node1.id, e.node2.id, e.dataIndex);
}
return graph;
};
/**
* @alias module:echarts/data/Graph.Node
*/
function Node(id, dataIndex) {
/**
* @type {string}
*/
this.id = id == null ? '' : id;
/**
* @type {Array.<module:echarts/data/Graph.Edge>}
*/
this.inEdges = [];
/**
* @type {Array.<module:echarts/data/Graph.Edge>}
*/
this.outEdges = [];
/**
* @type {Array.<module:echarts/data/Graph.Edge>}
*/
this.edges = [];
/**
* @type {module:echarts/data/Graph}
*/
this.hostGraph;
/**
* @type {number}
*/
this.dataIndex = dataIndex == null ? -1 : dataIndex;
}
Node.prototype = {
constructor: Node,
/**
* @return {number}
*/
degree: function () {
return this.edges.length;
},
/**
* @return {number}
*/
inDegree: function () {
return this.inEdges.length;
},
/**
* @return {number}
*/
outDegree: function () {
return this.outEdges.length;
},
/**
* @param {string} [path]
* @return {module:echarts/model/Model}
*/
getModel: function (path) {
if (this.dataIndex < 0) {
return;
}
var graph = this.hostGraph;
var itemModel = graph.data.getItemModel(this.dataIndex);
return itemModel.getModel(path);
}
};
/**
* 图边
* @alias module:echarts/data/Graph.Edge
* @param {module:echarts/data/Graph.Node} n1
* @param {module:echarts/data/Graph.Node} n2
* @param {number} [dataIndex=-1]
*/
function Edge(n1, n2, dataIndex) {
/**
* 节点1如果是有向图则为源节点
* @type {module:echarts/data/Graph.Node}
*/
this.node1 = n1;
/**
* 节点2如果是有向图则为目标节点
* @type {module:echarts/data/Graph.Node}
*/
this.node2 = n2;
this.dataIndex = dataIndex == null ? -1 : dataIndex;
}
/**
* @param {string} [path]
* @return {module:echarts/model/Model}
*/
Edge.prototype.getModel = function (path) {
if (this.dataIndex < 0) {
return;
}
var graph = this.hostGraph;
var itemModel = graph.edgeData.getItemModel(this.dataIndex);
return itemModel.getModel(path);
};
var createGraphDataProxyMixin = function (hostName, dataName) {
return {
/**
* @param {string=} [dimension='value'] Default 'value'. can be 'a', 'b', 'c', 'd', 'e'.
* @return {number}
*/
getValue: function (dimension) {
var data = this[hostName][dataName];
return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
},
/**
* @param {Object|string} key
* @param {*} [value]
*/
setVisual: function (key, value) {
this.dataIndex >= 0
&& this[hostName][dataName].setItemVisual(this.dataIndex, key, value);
},
/**
* @param {string} key
* @return {boolean}
*/
getVisual: function (key, ignoreParent) {
return this[hostName][dataName].getItemVisual(this.dataIndex, key, ignoreParent);
},
/**
* @param {Object} layout
* @return {boolean} [merge=false]
*/
setLayout: function (layout, merge) {
this.dataIndex >= 0
&& this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge);
},
/**
* @return {Object}
*/
getLayout: function () {
return this[hostName][dataName].getItemLayout(this.dataIndex);
},
/**
* @return {module:zrender/Element}
*/
getGraphicEl: function () {
return this[hostName][dataName].getItemGraphicEl(this.dataIndex);
},
/**
* @return {number}
*/
getRawIndex: function () {
return this[hostName][dataName].getRawIndex(this.dataIndex);
}
};
};
zrUtil.mixin(Node, createGraphDataProxyMixin('hostGraph', 'data'));
zrUtil.mixin(Edge, createGraphDataProxyMixin('hostGraph', 'edgeData'));
Graph.Node = Node;
Graph.Edge = Edge;
return Graph;
});

1058
vendors/echarts/src/data/List.js vendored Normal file

File diff suppressed because it is too large Load Diff

472
vendors/echarts/src/data/Tree.js vendored Normal file
View File

@@ -0,0 +1,472 @@
/**
* Tree data structure
*
* @module echarts/data/Tree
*/
define(function(require) {
var zrUtil = require('zrender/core/util');
var Model = require('../model/Model');
var List = require('./List');
var linkList = require('./helper/linkList');
var completeDimensions = require('./helper/completeDimensions');
/**
* @constructor module:echarts/data/Tree~TreeNode
* @param {string} name
* @param {module:echarts/data/Tree} hostTree
*/
var TreeNode = function (name, hostTree) {
/**
* @type {string}
*/
this.name = name || '';
/**
* Depth of node
*
* @type {number}
* @readOnly
*/
this.depth = 0;
/**
* Height of the subtree rooted at this node.
* @type {number}
* @readOnly
*/
this.height = 0;
/**
* @type {module:echarts/data/Tree~TreeNode}
* @readOnly
*/
this.parentNode = null;
/**
* Reference to list item.
* Do not persistent dataIndex outside,
* besause it may be changed by list.
* If dataIndex -1,
* this node is logical deleted (filtered) in list.
*
* @type {Object}
* @readOnly
*/
this.dataIndex = -1;
/**
* @type {Array.<module:echarts/data/Tree~TreeNode>}
* @readOnly
*/
this.children = [];
/**
* @type {Array.<module:echarts/data/Tree~TreeNode>}
* @pubilc
*/
this.viewChildren = [];
/**
* @type {moduel:echarts/data/Tree}
* @readOnly
*/
this.hostTree = hostTree;
};
TreeNode.prototype = {
constructor: TreeNode,
/**
* The node is removed.
* @return {boolean} is removed.
*/
isRemoved: function () {
return this.dataIndex < 0;
},
/**
* Travel this subtree (include this node).
* Usage:
* node.eachNode(function () { ... }); // preorder
* node.eachNode('preorder', function () { ... }); // preorder
* node.eachNode('postorder', function () { ... }); // postorder
* node.eachNode(
* {order: 'postorder', attr: 'viewChildren'},
* function () { ... }
* ); // postorder
*
* @param {(Object|string)} options If string, means order.
* @param {string=} options.order 'preorder' or 'postorder'
* @param {string=} options.attr 'children' or 'viewChildren'
* @param {Function} cb If in preorder and return false,
* its subtree will not be visited.
* @param {Object} [context]
*/
eachNode: function (options, cb, context) {
if (typeof options === 'function') {
context = cb;
cb = options;
options = null;
}
options = options || {};
if (zrUtil.isString(options)) {
options = {order: options};
}
var order = options.order || 'preorder';
var children = this[options.attr || 'children'];
var suppressVisitSub;
order === 'preorder' && (suppressVisitSub = cb.call(context, this));
for (var i = 0; !suppressVisitSub && i < children.length; i++) {
children[i].eachNode(options, cb, context);
}
order === 'postorder' && cb.call(context, this);
},
/**
* Update depth and height of this subtree.
*
* @param {number} depth
*/
updateDepthAndHeight: function (depth) {
var height = 0;
this.depth = depth;
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.updateDepthAndHeight(depth + 1);
if (child.height > height) {
height = child.height;
}
}
this.height = height + 1;
},
/**
* @param {string} id
* @return {module:echarts/data/Tree~TreeNode}
*/
getNodeById: function (id) {
if (this.getId() === id) {
return this;
}
for (var i = 0, children = this.children, len = children.length; i < len; i++) {
var res = children[i].getNodeById(id);
if (res) {
return res;
}
}
},
/**
* @param {module:echarts/data/Tree~TreeNode} node
* @return {boolean}
*/
contains: function (node) {
if (node === this) {
return true;
}
for (var i = 0, children = this.children, len = children.length; i < len; i++) {
var res = children[i].contains(node);
if (res) {
return res;
}
}
},
/**
* @param {boolean} includeSelf Default false.
* @return {Array.<module:echarts/data/Tree~TreeNode>} order: [root, child, grandchild, ...]
*/
getAncestors: function (includeSelf) {
var ancestors = [];
var node = includeSelf ? this : this.parentNode;
while (node) {
ancestors.push(node);
node = node.parentNode;
}
ancestors.reverse();
return ancestors;
},
/**
* @param {string|Array=} [dimension='value'] Default 'value'. can be 0, 1, 2, 3
* @return {number} Value.
*/
getValue: function (dimension) {
var data = this.hostTree.data;
return data.get(data.getDimension(dimension || 'value'), this.dataIndex);
},
/**
* @param {Object} layout
* @param {boolean=} [merge=false]
*/
setLayout: function (layout, merge) {
this.dataIndex >= 0
&& this.hostTree.data.setItemLayout(this.dataIndex, layout, merge);
},
/**
* @return {Object} layout
*/
getLayout: function () {
return this.hostTree.data.getItemLayout(this.dataIndex);
},
/**
* @param {string} path
* @return {module:echarts/model/Model}
*/
getModel: function (path) {
if (this.dataIndex < 0) {
return;
}
var hostTree = this.hostTree;
var itemModel = hostTree.data.getItemModel(this.dataIndex);
var levelModel = this.getLevelModel();
return itemModel.getModel(path, (levelModel || hostTree.hostModel).getModel(path));
},
/**
* @return {module:echarts/model/Model}
*/
getLevelModel: function () {
return (this.hostTree.levelModels || [])[this.depth];
},
/**
* @example
* setItemVisual('color', color);
* setItemVisual({
* 'color': color
* });
*/
setVisual: function (key, value) {
this.dataIndex >= 0
&& this.hostTree.data.setItemVisual(this.dataIndex, key, value);
},
/**
* Get item visual
*/
getVisual: function (key, ignoreParent) {
return this.hostTree.data.getItemVisual(this.dataIndex, key, ignoreParent);
},
/**
* @public
* @return {number}
*/
getRawIndex: function () {
return this.hostTree.data.getRawIndex(this.dataIndex);
},
/**
* @public
* @return {string}
*/
getId: function () {
return this.hostTree.data.getId(this.dataIndex);
}
};
/**
* @constructor
* @alias module:echarts/data/Tree
* @param {module:echarts/model/Model} hostModel
* @param {Array.<Object>} levelOptions
*/
function Tree(hostModel, levelOptions) {
/**
* @type {module:echarts/data/Tree~TreeNode}
* @readOnly
*/
this.root;
/**
* @type {module:echarts/data/List}
* @readOnly
*/
this.data;
/**
* Index of each item is the same as the raw index of coresponding list item.
* @private
* @type {Array.<module:echarts/data/Tree~TreeNode}
*/
this._nodes = [];
/**
* @private
* @readOnly
* @type {module:echarts/model/Model}
*/
this.hostModel = hostModel;
/**
* @private
* @readOnly
* @type {Array.<module:echarts/model/Model}
*/
this.levelModels = zrUtil.map(levelOptions || [], function (levelDefine) {
return new Model(levelDefine, hostModel, hostModel.ecModel);
});
}
Tree.prototype = {
constructor: Tree,
type: 'tree',
/**
* Travel this subtree (include this node).
* Usage:
* node.eachNode(function () { ... }); // preorder
* node.eachNode('preorder', function () { ... }); // preorder
* node.eachNode('postorder', function () { ... }); // postorder
* node.eachNode(
* {order: 'postorder', attr: 'viewChildren'},
* function () { ... }
* ); // postorder
*
* @param {(Object|string)} options If string, means order.
* @param {string=} options.order 'preorder' or 'postorder'
* @param {string=} options.attr 'children' or 'viewChildren'
* @param {Function} cb
* @param {Object} [context]
*/
eachNode: function(options, cb, context) {
this.root.eachNode(options, cb, context);
},
/**
* @param {number} dataIndex
* @return {module:echarts/data/Tree~TreeNode}
*/
getNodeByDataIndex: function (dataIndex) {
var rawIndex = this.data.getRawIndex(dataIndex);
return this._nodes[rawIndex];
},
/**
* @param {string} name
* @return {module:echarts/data/Tree~TreeNode}
*/
getNodeByName: function (name) {
return this.root.getNodeByName(name);
},
/**
* Update item available by list,
* when list has been performed options like 'filterSelf' or 'map'.
*/
update: function () {
var data = this.data;
var nodes = this._nodes;
for (var i = 0, len = nodes.length; i < len; i++) {
nodes[i].dataIndex = -1;
}
for (var i = 0, len = data.count(); i < len; i++) {
nodes[data.getRawIndex(i)].dataIndex = i;
}
},
/**
* Clear all layouts
*/
clearLayouts: function () {
this.data.clearItemLayouts();
}
};
/**
* data node format:
* {
* name: ...
* value: ...
* children: [
* {
* name: ...
* value: ...
* children: ...
* },
* ...
* ]
* }
*
* @static
* @param {Objec} dataRoot Root node.
* @param {module:echarts/model/Model} hostModel
* @param {Array.<Object>} levelOptions
* @return module:echarts/data/Tree
*/
Tree.createTree = function (dataRoot, hostModel, levelOptions) {
var tree = new Tree(hostModel, levelOptions);
var listData = [];
buildHierarchy(dataRoot);
function buildHierarchy(dataNode, parentNode) {
listData.push(dataNode);
var node = new TreeNode(dataNode.name, tree);
parentNode
? addChild(node, parentNode)
: (tree.root = node);
tree._nodes.push(node);
var children = dataNode.children;
if (children) {
for (var i = 0; i < children.length; i++) {
buildHierarchy(children[i], node);
}
}
}
tree.root.updateDepthAndHeight(0);
var dimensions = completeDimensions([{name: 'value'}], listData);
var list = new List(dimensions, hostModel);
list.initData(listData);
linkList({
mainData: list,
struct: tree,
structAttr: 'tree'
});
tree.update();
return tree;
};
/**
* It is needed to consider the mess of 'list', 'hostModel' when creating a TreeNote,
* so this function is not ready and not necessary to be public.
*
* @param {(module:echarts/data/Tree~TreeNode|Object)} child
*/
function addChild(child, node) {
var children = node.children;
if (child.parentNode === node) {
return;
}
children.push(child);
child.parentNode = node;
}
return Tree;
});

View File

@@ -0,0 +1,65 @@
/**
* Complete dimensions by data (guess dimension).
*/
define(function (require) {
var zrUtil = require('zrender/core/util');
/**
* Complete the dimensions array guessed from the data structure.
* @param {Array.<string>} dimensions Necessary dimensions, like ['x', 'y']
* @param {Array} data Data list. [[1, 2, 3], [2, 3, 4]]
* @param {Array.<string>} defaultNames Default names to fill not necessary dimensions, like ['value']
* @param {string} extraPrefix Prefix of name when filling the left dimensions.
* @return {Array.<string>}
*/
function completeDimensions(dimensions, data, defaultNames, extraPrefix) {
if (!data) {
return dimensions;
}
var value0 = retrieveValue(data[0]);
var dimSize = zrUtil.isArray(value0) && value0.length || 1;
defaultNames = defaultNames || [];
extraPrefix = extraPrefix || 'extra';
for (var i = 0; i < dimSize; i++) {
if (!dimensions[i]) {
var name = defaultNames[i] || (extraPrefix + (i - defaultNames.length));
dimensions[i] = guessOrdinal(data, i)
? {type: 'ordinal', name: name}
: name;
}
}
return dimensions;
}
// The rule should not be complex, otherwise user might not
// be able to known where the data is wrong.
function guessOrdinal(data, dimIndex) {
for (var i = 0, len = data.length; i < len; i++) {
var value = retrieveValue(data[i]);
if (!zrUtil.isArray(value)) {
return false;
}
var value = value[dimIndex];
if (value != null && isFinite(value)) {
return false;
}
else if (zrUtil.isString(value) && value !== '-') {
return true;
}
}
return false;
}
function retrieveValue(o) {
return zrUtil.isArray(o) ? o : zrUtil.isObject(o) ? o.value: o;
}
return completeDimensions;
});

View File

@@ -0,0 +1,133 @@
/**
* Link lists and struct (graph or tree)
*/
define(function (require) {
var zrUtil = require('zrender/core/util');
var each = zrUtil.each;
var DATAS = '\0__link_datas';
var MAIN_DATA = '\0__link_mainData';
// Caution:
// In most case, either list or its shallow clones (see list.cloneShallow)
// is active in echarts process. So considering heap memory consumption,
// we do not clone tree or graph, but share them among list and its shallow clones.
// But in some rare case, we have to keep old list (like do animation in chart). So
// please take care that both the old list and the new list share the same tree/graph.
/**
* @param {Object} opt
* @param {module:echarts/data/List} opt.mainData
* @param {Object} [opt.struct] For example, instance of Graph or Tree.
* @param {string} [opt.structAttr] designation: list[structAttr] = struct;
* @param {Object} [opt.datas] {dataType: data},
* like: {node: nodeList, edge: edgeList}.
* Should contain mainData.
* @param {Object} [opt.datasAttr] {dataType: attr},
* designation: struct[datasAttr[dataType]] = list;
*/
function linkList(opt) {
var mainData = opt.mainData;
var datas = opt.datas;
if (!datas) {
datas = {main: mainData};
opt.datasAttr = {main: 'data'};
}
opt.datas = opt.mainData = null;
linkAll(mainData, datas, opt);
// Porxy data original methods.
each(datas, function (data) {
each(mainData.TRANSFERABLE_METHODS, function (methodName) {
data.wrapMethod(methodName, zrUtil.curry(transferInjection, opt));
});
});
// Beyond transfer, additional features should be added to `cloneShallow`.
mainData.wrapMethod('cloneShallow', zrUtil.curry(cloneShallowInjection, opt));
// Only mainData trigger change, because struct.update may trigger
// another changable methods, which may bring about dead lock.
each(mainData.CHANGABLE_METHODS, function (methodName) {
mainData.wrapMethod(methodName, zrUtil.curry(changeInjection, opt));
});
// Make sure datas contains mainData.
zrUtil.assert(datas[mainData.dataType] === mainData);
}
function transferInjection(opt, res) {
if (isMainData(this)) {
// Transfer datas to new main data.
var datas = zrUtil.extend({}, this[DATAS]);
datas[this.dataType] = res;
linkAll(res, datas, opt);
}
else {
// Modify the reference in main data to point newData.
linkSingle(res, this.dataType, this[MAIN_DATA], opt);
}
return res;
}
function changeInjection(opt, res) {
opt.struct && opt.struct.update(this);
return res;
}
function cloneShallowInjection(opt, res) {
// cloneShallow, which brings about some fragilities, may be inappropriate
// to be exposed as an API. So for implementation simplicity we can make
// the restriction that cloneShallow of not-mainData should not be invoked
// outside, but only be invoked here.
each(res[DATAS], function (data, dataType) {
data !== res && linkSingle(data.cloneShallow(), dataType, res, opt);
});
return res;
}
/**
* Supplement method to List.
*
* @public
* @param {string} [dataType] If not specified, return mainData.
* @return {module:echarts/data/List}
*/
function getLinkedData(dataType) {
var mainData = this[MAIN_DATA];
return (dataType == null || mainData == null)
? mainData
: mainData[DATAS][dataType];
}
function isMainData(data) {
return data[MAIN_DATA] === data;
}
function linkAll(mainData, datas, opt) {
mainData[DATAS] = {};
each(datas, function (data, dataType) {
linkSingle(data, dataType, mainData, opt);
});
}
function linkSingle(data, dataType, mainData, opt) {
mainData[DATAS][dataType] = data;
data[MAIN_DATA] = mainData;
data.dataType = dataType;
if (opt.struct) {
data[opt.structAttr] = opt.struct;
opt.struct[opt.datasAttr[dataType]] = data;
}
// Supplement method.
data.getLinkedData = getLinkedData;
}
return linkList;
});