/** * Created by Mai on 2017/4/5. */ var cacheTree = { createNew: function (owner) { var tools = { findNode: function (nodes, check) { for (var i = 0; i < nodes.length; i++) { if (check(nodes[i])) { return nodes[i]; } } return null; }, reSortNodes: function (nodes, recursive) { var temp = [], first; var findFirstNode = function (nodes) { return tools.findNode(nodes, function (node) { return node.preSibling === null; }); }; var moveNode = function (node, orgArray, newArray, newIndex) { var next; orgArray.splice(orgArray.indexOf(node), 1); newArray.splice(newIndex, 0, node); if (node.getNextSiblingID() !== -1) { next = node.nextSibling; if (next && (orgArray.indexOf(next) >= 0)) { moveNode(next, orgArray, newArray, newIndex + 1); } } }; if (nodes.length === 0) { return nodes; } if (recursive) { nodes.forEach(function (node) { node.children = tools.reSortNodes(node.children, recursive); }); } while (nodes.length > 0) { first = findFirstNode(nodes); first = first ? first : nodes[0]; moveNode(first, nodes, temp, temp.length); } nodes = null; tools.reSiblingNodes(temp); return temp; }, reSiblingNodes: function (nodes) { var i; for (i = 0; i < nodes.length; i++) { nodes[i].preSibling = (i === 0) ? null : nodes[i - 1]; nodes[i].nextSibling = (i === nodes.length - 1) ? null : nodes[i + 1]; } }, // ��nodes�У���iIndex����������ʼȫ���Ƴ� removeNodes: function (tree, parent, iIndex, count) { var children = parent ? parent.children : tree.roots; var pre = (iIndex < 0 || iIndex >= children.length) ? null : children[iIndex].preSibling; var next = (pre && iIndex + count - 1 < children.length) ? children[iIndex + count] : null; if (pre) { pre.setNextSibling(next); } else if (next) { next.preSibling = null; } if (arguments.length === 4) { children.splice(iIndex, count); } else { children.splice(iIndex, children.length - iIndex); } }, // 在parent.children/tree.roots中增加nodes, 位置从index开始 addNodes: function (tree, parent, nodes, iIndex) { var children = parent ? parent.children : tree.roots; var pre, next, i; if (nodes.length === 0) { return; } if (arguments.length === 4) { pre = (iIndex <=0 || iIndex > children.length) ? null : children[iIndex-1]; if(pre==null){ next = iIndex==0?children[0]:null; }else { next = pre.nextSibling; } } else if (arguments.length === 3) { pre = children.length === 0 ? null : children[children.length - 1]; next = null; } if (pre) { pre.setNextSibling(nodes[0]); } else { nodes[0].preSibling = null; } nodes[nodes.length - 1].setNextSibling(next); for (i = 0; i < nodes.length; i++) { if (arguments.length === 4) { children.splice(iIndex + i, 0, nodes[i]); } else if (arguments.length === 3) { children.push(nodes[i]); } nodes[i].parent = parent; } } }; var Node = function (tree, id) { var ID = id; // ���µ����ԣ�����Ԫ��������ֱ���޸� this.tree = tree; this.children = []; this.parent = null; this.nextSibling = null; this.preSibling = null; this.expanded = true; this.visible = true; this.sourceType = null; this.source = null; this.getID = function () { return ID; } }; Node.prototype.getParentID = function () { return this.parent ? this.parent.getID() : -1; }; Node.prototype.getNextSiblingID = function () { return this.nextSibling ? this.nextSibling.getID() : -1; }; Node.prototype.setParent = function (parent) { this.parent = parent; }; Node.prototype.setNextSibling = function (nextSibling) { this.nextSibling = nextSibling; if (nextSibling) { nextSibling.preSibling = this; } } Node.prototype.firstChild = function () { return this.children.length === 0 ? null : this.children[0]; }; Node.prototype.lastChild = function () { return this.children.length === 0 ? null : this.children[this.children.length - 1]; }; Node.prototype.depth = function () { return this.parent ? this.parent.depth() + 1 : 0; }; Node.prototype.isFirst = function () { if (this.parent) { return this.parent.children.indexOf(this) === 0 ? true : false; } else { return this.tree.roots.indexOf(this) === 0 ? true : false; } }; Node.prototype.isLast = function () { if (this.parent) { return this.parent.children.indexOf(this) === this.parent.children.length - 1 ? true : false; } else { return this.tree.roots.indexOf(this) === this.tree.roots.length - 1 ? true : false; } }; Node.prototype.siblingIndex = function () { return this.parent ? this.parent.children.indexOf(this) : this.tree.roots.indexOf(this); } Node.prototype.posterityCount = function () { var iCount = 0; if (this.children.length !== 0) { iCount += this.children.length; this.children.forEach(function (child) { iCount += child.posterityCount(); }); } return iCount; }; Node.prototype.setExpanded = function (expanded) { var setNodesVisible = function (nodes, visible) { nodes.forEach(function (node) { node.visible = visible; setNodesVisible(node.children, visible && node.expanded); }) }; this.expanded = expanded; setNodesVisible(this.children, expanded); }; Node.prototype.serialNo = function () { return this.tree.items.indexOf(this); } Node.prototype.addChild = function (node) { var preSibling = this.children.length === 0 ? null : this.children[this.children.length - 1]; node.parent = this; if (preSibling) { preSibling.nextSibling = node; } node.preSibling = preSibling; this.children.push(node); }; Node.prototype.removeChild = function (node) { var preSibling = node.preSibling, nextSibling = node.nextSibling; if (preSibling) { preSibling.nextSibling = nextSibling; } if (nextSibling) { nextSibling.preSibling = preSibling; } this.children.splice(this.children.re) }; Node.prototype.canUpLevel = function () { if (this.sourceType === this.tree.owner.Bills.getSourceType()) { return this.parent ? true : false; } else { return false; } }; Node.prototype.canDownLevel = function () { return this.sourceType === this.tree.owner.Bills.getSourceType() ? !this.isFirst() : false; }; Node.prototype.canUpMove = function () { return !this.isFirst(); }; Node.prototype.canDownMove = function () { return !this.isLast(); } Node.prototype.upLevel = function () { var success = false, iIndex = this.parent.children.indexOf(this), orgParent = this.parent, newNextSibling = this.parent.nextSibling; if (this.canUpLevel) { // NextSiblings become child tools.addNodes(this.tree, this, this.parent.children.slice(iIndex + 1)); // Orginal Parent remove node and nextSiblings tools.removeNodes(this.tree, this.parent, iIndex); // New Parent add node tools.addNodes(this.tree, this.parent.parent, [this], this.parent.siblingIndex() + 1); if (!this.expanded) { this.setExpanded(true); } success = true; } return success; }; Node.prototype.downLevel = function () { var success = false, iIndex = this.parent ? this.parent.children.indexOf(this) : this.tree.roots.indexOf(this); var newParent = this.preSibling; if (this.canDownLevel()) { tools.removeNodes(this.tree, this.parent, this.siblingIndex(), 1); tools.addNodes(this.tree, this.preSibling, [this]); if (!newParent.expanded) { newParent.setExpanded(true); } success = true; } return success; }; Node.prototype.upMove = function () { var success = false; var iIndex = this.siblingIndex(), belongArray = this.parent ? this.parent.children : this.tree.roots, orgPre = this.preSibling; if (this.canUpMove()) { if (orgPre.preSibling) { orgPre.preSibling.setNextSibling(this); } else { this.preSibling = null; } orgPre.setNextSibling(this.nextSibling); this.setNextSibling(orgPre); belongArray.splice(iIndex, 1); belongArray.splice(iIndex - 1, 0, this); this.tree.sortTreeItems(); success = true; } return success; }; Node.prototype.downMove = function () { var success = false; var iIndex = this.siblingIndex(), belongArray = this.parent ? this.parent.children : this.tree.roots, orgNext = this.nextSibling; if (this.canDownMove()) { if (this.preSibling) { this.preSibling.setNextSibling(orgNext); } else if (orgNext) { orgNext.preSibling = null; } this.setNextSibling(orgNext.nextSibling); orgNext.setNextSibling(this); belongArray.splice(iIndex, 1); belongArray.splice(iIndex + 1, 0, this); this.tree.sortTreeItems(); success = true; } return success; }; var Tree = function (owner) { this.owner = owner; this.nodes = {}; this.roots = []; this.items = []; this.prefix = 'id_'; this.selected = null; var _MaxID = 0; this.newNodeID = function (id) { if (arguments.length === 0) { _MaxID += 1; return _MaxID; } else { _MaxID = Math.max(_MaxID, id); } }; var rootId = -1; this.rootID = function () { return rootId; } }; Tree.prototype.addNode = function (parent, nextSibling, id) { if(!isDef(id) || id == -1){ return null; } var newNode = new Node(this, id); this.nodes[this.prefix + newNode.getID()] = newNode; if (nextSibling) { tools.addNodes(this, parent, [newNode], nextSibling.siblingIndex()); } else { tools.addNodes(this, parent, [newNode]); } return newNode; }; Tree.prototype.sortTreeItems = function () { var that = this; var addItems = function (nodes) { var i; for (i = 0; i < nodes.length; i++) { that.items.push(nodes[i]); addItems(nodes[i].children); } }; this.items.splice(0, this.items.length); addItems(this.roots); }; Tree.prototype.firstNode = function () { return this.roots.length === 0 ? null : this.roots[0]; }; Tree.prototype.findNode = function (id) { return this.nodes[this.prefix + id]; }; Tree.prototype.count = function () { var iCount = 0; if (this.roots.length !== 0) { iCount += this.roots.length; this.roots.forEach(function (node) { iCount += node.posterityCount(); }); } return iCount; }; Tree.prototype.insert = function (parentID, nextSiblingID, id) { var parent = !parentID || parentID === -1 ? null : this.nodes[this.prefix + parentID]; var nextSibling = !nextSiblingID || nextSiblingID === -1 ? null: this.nodes[this.prefix + nextSiblingID]; var newNode = this.addNode(parent, nextSibling, id); this.sortTreeItems(); return newNode; }; Tree.prototype.insertByDatas = function (datas) { let rst = []; for(let data of datas){ this.nodes[this.prefix + data.ID] = new Node(this, data.ID); rst.push(this.nodes[this.prefix + data.ID]); } for(let data of datas){ let node = this.nodes[this.prefix + data.ID]; let parent = data.ParentID == -1 ? null : this.nodes[this.prefix + data.ParentID]; node.parent = parent; if(!parent){ this.roots.push(node); } else { parent.children.push(node); } let next = data.NextSiblingID == -1 ? null : this.nodes[this.prefix + data.NextSiblingID]; node.nextSibling = next; if(next){ next.preSibling = node; } } //resort this.roots = tools.reSortNodes(this.roots, true); this.sortTreeItems(); return rst; }; Tree.prototype.delete = function (node) { var success = false; success=this.cascadeRemove(node); this.sortTreeItems(); this.preSelected = null; return success; }; Tree.prototype.cascadeRemove = function (node) { var success = false; var me = this; var removeNodes = function (node) { delete me.nodes[me.prefix + node.getID()]; for(let ch of node.children){ removeNodes(ch); } }; if (node) { removeNodes(node); if (node.preSibling) { node.preSibling.setNextSibling(node.nextSibling); } else if (node.nextSibling) { node.nextSibling.preSibling = null; } if (node.parent) { node.parent.children.splice(node.siblingIndex(), 1); } else { this.roots.splice(node.siblingIndex(), 1); } success = true; } return success; }; Tree.prototype.m_delete = function (nodes) {//删除多个节点,级联删除 for(let node of nodes){ this.cascadeRemove(node); } this.sortTreeItems(); return true; }; Tree.prototype.singleDelete = function (node) {//只删除当前节点,不删除子节点 var success = false; var me = this; if(node){ delete me.nodes[me.prefix + node.getID()]; if (node.parent) {//从父项的子节点中移除 node.parent.children.splice(node.siblingIndex(), 1); } else { this.roots.splice(node.siblingIndex(), 1); } if(node.children.length>0){ if(node.preSibling){//子项变成前兄弟的子项 for(let c of node.children){ node.preSibling.addChild(c); } }else if(node.nextSibling){//没有前兄弟,有后兄弟 let oldChild = node.parent.children; node.parent.children = []; for(let c of node.children){ node.parent.addChild(c); } for(let oc of oldChild){ node.parent.addChild(oc); } }else {//都没有的情况 node.parent.children = [];//删除本身节点 for(let c of node.children){ node.parent.addChild(c); } } this.sortTreeItems(); success = true; } } return success }; Tree.prototype.getAllSubNode = function (node,nodeArray) { for(let c of node.children){ nodeArray.push(c); this.getAllSubNode(c,nodeArray); } }; Tree.prototype.getLeavesNodes = function (node) {//取该节点下的所有叶子节点 let leaves = []; getLeaves(node,leaves); return leaves; function getLeaves(node,nodeArr) { if(node.children.length>0){ for(let ch of node.children){ getLeaves(ch,nodeArr); } }else { nodeArr.push(node); } } }; Tree.prototype.getNodeByID = function (ID) { let node = this.nodes[this.prefix+ID]; return node; }; return new Tree(owner); } };