fineui是帆软报表和BI产品线所使用的前端框架。
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.
 
 
 

516 lines
15 KiB

(function () {
BI.Tree = function () {
this.root = new BI.Node(BI.UUID());
};
BI.Tree.prototype = {
constructor: BI.Tree,
addNode: function (node, newNode, index) {
if (BI.isNull(newNode)) {
this.root.addChild(node, index);
} else if (BI.isNull(node)) {
this.root.addChild(newNode, index);
} else {
node.addChild(newNode, index);
}
},
isRoot: function (node) {
return node === this.root;
},
getRoot: function () {
return this.root;
},
clear: function () {
this.root.clear();
},
initTree: function (nodes) {
var self = this;
this.clear();
var queue = [];
BI.each(nodes, function (i, node) {
var n = new BI.Node(node);
n.set("data", node);
self.addNode(n);
queue.push(n);
});
while (!BI.isEmpty(queue)) {
var parent = queue.shift();
var node = parent.get("data");
BI.each(node.children, function (i, child) {
var n = new BI.Node(child);
n.set("data", child);
queue.push(n);
self.addNode(parent, n);
});
}
},
_toJSON: function (node) {
var self = this;
var children = [];
BI.each(node.getChildren(), function (i, child) {
children.push(self._toJSON(child));
});
return BI.extend({
id: node.id
}, BI.deepClone(node.get("data")), (children.length > 0 ? {
children: children
} : {}));
},
toJSON: function (node) {
var self = this, result = [];
BI.each((node || this.root).getChildren(), function (i, child) {
result.push(self._toJSON(child));
});
return result;
},
_toJSONWithNode: function (node) {
var self = this;
var children = [];
BI.each(node.getChildren(), function (i, child) {
children.push(self._toJSONWithNode(child));
});
return BI.extend({
id: node.id
}, BI.deepClone(node.get("data")), {
node: node
}, (children.length > 0 ? {
children: children
} : {}));
},
toJSONWithNode: function (node) {
var self = this, result = [];
BI.each((node || this.root).getChildren(), function (i, child) {
result.push(self._toJSONWithNode(child));
});
return result;
},
search: function (root, target, param) {
if (!(root instanceof BI.Node)) {
return arguments.callee.apply(this, [this.root, root, target]);
}
var self = this, next = null;
if (BI.isNull(target)) {
return null;
}
if (BI.isEqual(root[param || "id"], target)) {
return root;
}
BI.any(root.getChildren(), function (i, child) {
next = self.search(child, target, param);
if (null !== next) {
return true;
}
});
return next;
},
_traverse: function (node, callback) {
var queue = [];
queue.push(node);
while (!BI.isEmpty(queue)) {
var temp = queue.shift();
var b = callback && callback(temp);
if (b === false) {
break;
}
if (b === true) {
continue;
}
if (temp != null) {
queue = queue.concat(temp.getChildren());
}
}
},
traverse: function (callback) {
this._traverse(this.root, callback);
},
_recursion: function (node, route, callback) {
var self = this;
return BI.every(node.getChildren(), function (i, child) {
var next = BI.clone(route);
next.push(child.id);
var b = callback && callback(child, next);
if (b === false) {
return false;
}
if (b === true) {
return true;
}
return self._recursion(child, next, callback);
});
},
recursion: function (callback) {
this._recursion(this.root, [], callback);
},
inOrderTraverse: function (callback) {
this._inOrderTraverse(this.root, callback);
},
// 中序遍历(递归)
_inOrderTraverse: function (node, callback) {
if (node != null) {
this._inOrderTraverse(node.getLeft());
callback && callback(node);
this._inOrderTraverse(node.getRight());
}
},
// 中序遍历(非递归)
nrInOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
while (node != null || !BI.isEmpty(stack)) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
node = stack.pop();
callback && callback(node);
node = node.getRight();
}
},
preOrderTraverse: function (callback) {
this._preOrderTraverse(this.root, callback);
},
// 先序遍历(递归)
_preOrderTraverse: function (node, callback) {
if (node != null) {
callback && callback(node);
this._preOrderTraverse(node.getLeft());
this._preOrderTraverse(node.getRight());
}
},
// 先序遍历(非递归)
nrPreOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
while (node != null || !BI.isEmpty(stack)) {
while (node != null) {
callback && callback(node);
stack.push(node);
node = node.getLeft();
}
node = stack.pop();
node = node.getRight();
}
},
postOrderTraverse: function (callback) {
this._postOrderTraverse(this.root, callback);
},
// 后序遍历(递归)
_postOrderTraverse: function (node, callback) {
if (node != null) {
this._postOrderTraverse(node.getLeft());
this._postOrderTraverse(node.getRight());
callback && callback(node);
}
},
// 后续遍历(非递归)
nrPostOrderTraverse: function (callback) {
var stack = [];
var node = this.root;
var preNode = null;// 表示最近一次访问的节点
while (node != null || !BI.isEmpty(stack)) {
while (node != null) {
stack.push(node);
node = node.getLeft();
}
node = BI.last(stack);
if (node.getRight() == null || node.getRight() == preNode) {
callback && callback(node);
node = stack.pop();
preNode = node;
node = null;
} else {
node = node.getRight();
}
}
}
};
BI.Node = function (id) {
if (BI.isObject(id)) {
BI.extend(this, id);
} else {
this.id = id;
}
this.clear.apply(this, arguments);
};
BI.Node.prototype = {
constructor: BI.Node,
set: function (key, value) {
if (BI.isObject(key)) {
BI.extend(this, key);
return;
}
this[key] = value;
},
get: function (key) {
return this[key];
},
isLeaf: function () {
return BI.isEmpty(this.children);
},
getChildren: function () {
return this.children;
},
getChildrenLength: function () {
return this.children.length;
},
getFirstChild: function () {
return BI.first(this.children);
},
getLastChild: function () {
return BI.last(this.children);
},
setLeft: function (left) {
this.left = left;
},
getLeft: function () {
return this.left;
},
setRight: function (right) {
this.right = right;
},
getRight: function () {
return this.right;
},
setParent: function (parent) {
this.parent = parent;
},
getParent: function () {
return this.parent;
},
getChild: function (index) {
return this.children[index];
},
getChildIndex: function (id) {
return BI.findIndex(this.children, function (i, ch) {
return ch.get("id") === id;
});
},
removeChild: function (id) {
this.removeChildByIndex(this.getChildIndex(id));
},
removeChildByIndex: function (index) {
var before = this.getChild(index - 1);
var behind = this.getChild(index + 1);
if (before != null) {
before.setRight(behind || null);
}
if (behind != null) {
behind.setLeft(before || null);
}
this.children.splice(index, 1);
},
removeAllChilds: function () {
this.children = [];
},
addChild: function (child, index) {
var cur = null;
if (BI.isUndefined(index)) {
cur = this.children.length - 1;
} else {
cur = index - 1;
}
child.setParent(this);
if (cur >= 0) {
this.getChild(cur) && this.getChild(cur).setRight(child);
child.setLeft(this.getChild(cur));
}
if (BI.isUndefined(index)) {
this.children.push(child);
} else {
this.children.splice(index, 0, child);
}
},
equals: function (obj) {
return this === obj || this.id === obj.id;
},
clear: function () {
this.parent = null;
this.left = null;
this.right = null;
this.children = [];
}
};
BI.extend(BI.Tree, {
transformToArrayFormat: function (nodes, pId) {
if (!nodes) return [];
var r = [];
if (BI.isArray(nodes)) {
for (var i = 0, l = nodes.length; i < l; i++) {
var node = BI.clone(nodes[i]);
node.pId = node.pId == null ? pId : node.pId;
delete node.children;
r.push(node);
if (nodes[i]["children"]) {
r = r.concat(BI.Tree.transformToArrayFormat(nodes[i]["children"], node.id));
}
}
} else {
var newNodes = BI.clone(nodes);
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
delete newNodes.children;
r.push(newNodes);
if (nodes["children"]) {
r = r.concat(BI.Tree.transformToArrayFormat(nodes["children"], newNodes.id));
}
}
return r;
},
arrayFormat: function (nodes, pId) {
if (!nodes) {
return [];
}
var r = [];
if (BI.isArray(nodes)) {
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
node.pId = node.pId == null ? pId : node.pId;
r.push(node);
if (nodes[i]["children"]) {
r = r.concat(BI.Tree.arrayFormat(nodes[i]["children"], node.id));
}
}
} else {
var newNodes = nodes;
newNodes.pId = newNodes.pId == null ? pId : newNodes.pId;
r.push(newNodes);
if (nodes["children"]) {
r = r.concat(BI.Tree.arrayFormat(nodes["children"], newNodes.id));
}
}
return r;
},
transformToTreeFormat: function (sNodes) {
var i, l;
if (!sNodes) {
return [];
}
if (BI.isArray(sNodes)) {
var r = [];
var tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (BI.isNull(sNodes[i].id)) {
return sNodes;
}
tmpMap[sNodes[i].id] = BI.clone(sNodes[i]);
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
}
delete tmpMap[sNodes[i].id].pId;
}
return r;
}
return [sNodes];
},
treeFormat: function (sNodes) {
var i, l;
if (!sNodes) {
return [];
}
if (BI.isArray(sNodes)) {
var r = [];
var tmpMap = {};
for (i = 0, l = sNodes.length; i < l; i++) {
if (BI.isNull(sNodes[i].id)) {
return sNodes;
}
tmpMap[sNodes[i].id] = sNodes[i];
}
for (i = 0, l = sNodes.length; i < l; i++) {
if (tmpMap[sNodes[i].pId] && sNodes[i].id !== sNodes[i].pId) {
if (!tmpMap[sNodes[i].pId].children) {
tmpMap[sNodes[i].pId].children = [];
}
tmpMap[sNodes[i].pId].children.push(tmpMap[sNodes[i].id]);
} else {
r.push(tmpMap[sNodes[i].id]);
}
}
return r;
}
return [sNodes];
},
traversal: function (array, callback, pNode) {
if (BI.isNull(array)) {
return;
}
var self = this;
BI.some(array, function (i, item) {
if (callback(i, item, pNode) === false) {
return true;
}
self.traversal(item.children, callback, item);
});
}
});
})();