var setting = {
edit: {
enable: true,
showRemoveBtn: false,//顯示後,節點可刪除
showRenameBtn: false,//顯示後,節點可重命名
drag:{
isCopy:true, //允許複製
isMove:false, //允許移動
prev:false, //允許插在前面
inner:false, //允許插在裏面
next:false //允許插在後面
}
},
data: {
simpleData: {
enable: true
}
},
callback: {
beforeDrag: beforeDrag,
beforeDrop: beforeDrop
}
};
var setting2 = {
edit: {
enable: true,
showRemoveBtn: true,
showRenameBtn: true,
drag:{
isCopy:false,
isMove:true,
prev:false,
inner:true,
next:false
}
},
data: {
simpleData: {
enable: true,
idKey: "id",
pIdKey: "pId",
rootPId: 0
}
},
callback: {
beforeDrag: beforeDrag,
beforeDrop: beforeDrop
}
};
var zNodes2 =[
{ id:1, pId:0, name:"fast", open:true, myAttr:"root"},//額外的屬性幫助顯示不同的圖標
//如果用自帶level,拖動之後圖標會亂,項目特性需要綁定到節點上
{ id:2, pId:1, name:"ceph10", open:true, myAttr:"host"},
{ id:5, pId:2, name:"osd.0"},
{ id:6, pId:2, name:"osd.1"},
{ id:7, pId:2, name:"osd.2"},
{ id:8, pId:2, name:"osd.3"},
{ id:3, pId:1, name:"ceph20", open:true, myAttr:"host"},
{ id:9, pId:3, name:"osd.4"},
{ id:10, pId:3, name:"osd.5"},
{ id:11, pId:3, name:"osd.6"},
{ id:12, pId:3, name:"osd.7"},
{ id:4, pId:1, name:"ceph30", open:true, myAttr:"host"},
{ id:13, pId:4, name:"osd.8"},
{ id:14, pId:4, name:"osd.9"},
{ id:15, pId:4, name:"osd.10"},
{ id:16, pId:4, name:"osd.11"},
{ id:21, pId:0, name:"default", open:true, myAttr:"root"},
{ id:22, pId:21, name:"ceph10", open:true, myAttr:"host"},
{ id:25, pId:22, name:"osd.0"},
{ id:26, pId:22, name:"osd.1"},
{ id:27, pId:22, name:"osd.2"},
{ id:28, pId:22, name:"osd.3"},
{ id:23, pId:21, name:"ceph20", open:true, myAttr:"host"},
{ id:29, pId:23, name:"osd.4"},
{ id:30, pId:23, name:"osd.5"},
{ id:31, pId:23, name:"osd.6"},
{ id:32, pId:23, name:"osd.7"},
{ id:24, pId:21, name:"ceph30", open:true, myAttr:"host"},
{ id:33, pId:24, name:"osd.8"},
{ id:34, pId:24, name:"osd.9"},
{ id:35, pId:24, name:"osd.10"},
{ id:36, pId:24, name:"osd.11"}
];
function beforeDrag(treeId, treeNodes) {
//更加深入的定製啓動點的條件
for (var i=0,l=treeNodes.length; i<l; i++) {
if (treeNodes[i].drag === false) {
return false;
}
}
return true;
}
function beforeDrop(treeId, treeNodes, targetNode, moveType) {
//更加深入的定製落點的條件
if (targetNode && targetNode.myAttr==undefined){
return false
}
return targetNode ? targetNode.drop !== false : true;
}
function fixIcon(demotree){
var treeObj = $.fn.zTree.getZTreeObj(demotree);
//過濾出某一類的節點,選出myAttr=='host'的節點
var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="host"});
for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
folderNode[j].isParent = true;
folderNode[j].icon="/static/images/8.png";
}
var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="root"});
for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
folderNode[j].isParent = true;
folderNode[j].iconOpen="/static/images/1_open.png";
folderNode[j].iconClose="/static/images/1_close.png"
}
treeObj.refresh();//調用api自帶的refresh函數。
}
function fixopen(demotree) {
var treeObj = $.fn.zTree.getZTreeObj(demotree);
var folderNode = treeObj.getNodesByFilter(function (node) { return node.myAttr=="host" || node.myAttr=="root"});
for(j=0 ; j<folderNode.length; j++){//遍歷目錄節點,設置isParent屬性爲true;
folderNode[j].open = true;
}
treeObj.refresh();//調用api自帶的refresh函數。
}
//異步加載數據,數據格式如zNodes2定義的地方
zNodes2 = JSON.parse(arg.topo);
$.fn.zTree.init($("#treeDemo2"), setting2, zNodes2);
fixIcon("treeDemo2");
fixopen("treeDemo2");
父子節點(關係節點)的列表,轉化成tree的算法:、
from collections import namedtuple
#原始機構
Relation = namedtuple("RELATION",["name","id","pId","myAttr"])
#舒型結構,多一個children,其他語言可以用類或者結構體實現也一樣
Tree = namedtuple("TREE",["name","id","pId","myAttr","children"])
#需要保證關係列表是有序的,否則父節點沒有插入就插入字節點會失敗
#如果實在不保序, 解決辦法建立一個節點添加標誌的字典,失敗的重複添加
def make_tree(nodes):
res = Tree("super", 0, 0, "super", []) #根節點,不同語言根節點生成不一樣
for node in nodes:
add_tree(res, node)
return res
def add_tree(root, node):
data = Tree(node["name"], node["id"], node["pId"], node["myAttr"], [])
if node["pId"]== root.id: #只有符合條件的才真正添加
root.children.append(data)
return
for child in root.children: #可迭代對象自動判空
add_tree(child,node) #所有節點都嘗試添加
def traverse_tree(res, root):
if root:
res.append(Relation(root.name, root.id, root.pId, root.myAttr)._asdict())
for child in root.children:
traverse_tree(res, child)
#逆向操作,樹生成關係節點
def tree_to_relation(root):
res =[]
traverse_tree(res, root)
return res
項目中還遇到js的問題,後臺傳的數據給前臺下拉列表;下拉列表(本身也是異步數據,生成的時候會清空再存入選項)會觸發監聽,相互覆蓋的下拉選項;目前解決是後臺數據傳給下拉框的時候,不調用trigger,並且也傳入完整的下拉列表和選中情況;
也許有辦法直接根據後臺數據,直接修改下拉列表的選中選中情況;