You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					569 lines
				
				13 KiB
			
		
		
			
		
	
	
					569 lines
				
				13 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								* Licensed to the Apache Software Foundation (ASF) under one
							 | 
						||
| 
								 | 
							
								* or more contributor license agreements.  See the NOTICE file
							 | 
						||
| 
								 | 
							
								* distributed with this work for additional information
							 | 
						||
| 
								 | 
							
								* regarding copyright ownership.  The ASF licenses this file
							 | 
						||
| 
								 | 
							
								* to you under the Apache License, Version 2.0 (the
							 | 
						||
| 
								 | 
							
								* "License"); you may not use this file except in compliance
							 | 
						||
| 
								 | 
							
								* with the License.  You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								*   http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* Unless required by applicable law or agreed to in writing,
							 | 
						||
| 
								 | 
							
								* software distributed under the License is distributed on an
							 | 
						||
| 
								 | 
							
								* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
							 | 
						||
| 
								 | 
							
								* KIND, either express or implied.  See the License for the
							 | 
						||
| 
								 | 
							
								* specific language governing permissions and limitations
							 | 
						||
| 
								 | 
							
								* under the License.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var zrUtil = require("zrender/lib/core/util");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Model = require("../model/Model");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var linkList = require("./helper/linkList");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var List = require("./List");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var createDimensions = require("./helper/createDimensions");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								* Licensed to the Apache Software Foundation (ASF) under one
							 | 
						||
| 
								 | 
							
								* or more contributor license agreements.  See the NOTICE file
							 | 
						||
| 
								 | 
							
								* distributed with this work for additional information
							 | 
						||
| 
								 | 
							
								* regarding copyright ownership.  The ASF licenses this file
							 | 
						||
| 
								 | 
							
								* to you under the Apache License, Version 2.0 (the
							 | 
						||
| 
								 | 
							
								* "License"); you may not use this file except in compliance
							 | 
						||
| 
								 | 
							
								* with the License.  You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								*   http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								*
							 | 
						||
| 
								 | 
							
								* Unless required by applicable law or agreed to in writing,
							 | 
						||
| 
								 | 
							
								* software distributed under the License is distributed on an
							 | 
						||
| 
								 | 
							
								* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
							 | 
						||
| 
								 | 
							
								* KIND, either express or implied.  See the License for the
							 | 
						||
| 
								 | 
							
								* specific language governing permissions and limitations
							 | 
						||
| 
								 | 
							
								* under the License.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Tree data structure
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @module echarts/data/Tree
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @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();
							 | 
						||
| 
								 | 
							
								    var leavesModel;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!levelModel && (this.children.length === 0 || this.children.length !== 0 && this.isExpand === false)) {
							 | 
						||
| 
								 | 
							
								      leavesModel = this.getLeavesModel();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return itemModel.getModel(path, (levelModel || leavesModel || hostTree.hostModel).getModel(path));
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @return {module:echarts/model/Model}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  getLevelModel: function () {
							 | 
						||
| 
								 | 
							
								    return (this.hostTree.levelModels || [])[this.depth];
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @return {module:echarts/model/Model}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  getLeavesModel: function () {
							 | 
						||
| 
								 | 
							
								    return this.hostTree.leavesModel;
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @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);
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * if this is an ancestor of another node
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @public
							 | 
						||
| 
								 | 
							
								   * @param {TreeNode} node another node
							 | 
						||
| 
								 | 
							
								   * @return {boolean} if is ancestor
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  isAncestorOf: function (node) {
							 | 
						||
| 
								 | 
							
								    var parent = node.parentNode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while (parent) {
							 | 
						||
| 
								 | 
							
								      if (parent === this) {
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      parent = parent.parentNode;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * if this is an descendant of another node
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @public
							 | 
						||
| 
								 | 
							
								   * @param {TreeNode} node another node
							 | 
						||
| 
								 | 
							
								   * @return {boolean} if is descendant
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  isDescendantOf: function (node) {
							 | 
						||
| 
								 | 
							
								    return node !== this && node.isAncestorOf(this);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @constructor
							 | 
						||
| 
								 | 
							
								 * @alias module:echarts/data/Tree
							 | 
						||
| 
								 | 
							
								 * @param {module:echarts/model/Model} hostModel
							 | 
						||
| 
								 | 
							
								 * @param {Array.<Object>} levelOptions
							 | 
						||
| 
								 | 
							
								 * @param {Object} leavesOption
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Tree(hostModel, levelOptions, leavesOption) {
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @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);
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  this.leavesModel = new Model(leavesOption || {}, 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 {Object} dataRoot Root node.
							 | 
						||
| 
								 | 
							
								 * @param {module:echarts/model/Model} hostModel
							 | 
						||
| 
								 | 
							
								 * @param {Object} treeOptions
							 | 
						||
| 
								 | 
							
								 * @param {Array.<Object>} treeOptions.levels
							 | 
						||
| 
								 | 
							
								 * @param {Array.<Object>} treeOptions.leaves
							 | 
						||
| 
								 | 
							
								 * @return module:echarts/data/Tree
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Tree.createTree = function (dataRoot, hostModel, treeOptions) {
							 | 
						||
| 
								 | 
							
								  var tree = new Tree(hostModel, treeOptions.levels, treeOptions.leaves);
							 | 
						||
| 
								 | 
							
								  var listData = [];
							 | 
						||
| 
								 | 
							
								  var dimMax = 1;
							 | 
						||
| 
								 | 
							
								  buildHierarchy(dataRoot);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function buildHierarchy(dataNode, parentNode) {
							 | 
						||
| 
								 | 
							
								    var value = dataNode.value;
							 | 
						||
| 
								 | 
							
								    dimMax = Math.max(dimMax, zrUtil.isArray(value) ? value.length : 1);
							 | 
						||
| 
								 | 
							
								    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 dimensionsInfo = createDimensions(listData, {
							 | 
						||
| 
								 | 
							
								    coordDimensions: ['value'],
							 | 
						||
| 
								 | 
							
								    dimensionsCount: dimMax
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  var list = new List(dimensionsInfo, 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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _default = Tree;
							 | 
						||
| 
								 | 
							
								module.exports = _default;
							 |