【ztree】zTree節點增刪改&ztree對樹節點進行檢索


1.對節點增刪改查 

  今天遇到一個需求是對zTree的節點進行增刪改,經過查閱資料總結如下:

 

效果:

 

 

完成增刪改,要注意幾個關鍵點:

 

  • 使用 編輯功能,必須設置 setting.edit 中的各個屬性
  • 使用 編輯功能的事件回調函數,必須設置 setting.callback.beforeRemove / onRemove / beforeRename / onRename 等屬性
  • zTree 不提供默認的增加按鈕,如要實現需要利用自定義控件的方法 addHoverDom / removeHoverDom 
  • 我們利用 beforeEditName 來觸發自定義的編輯操作

 

首先,我們來看看具體的配置信息(詳細內容見代碼中的注釋):

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>zTree測試</title>
        <link rel="stylesheet" type="text/css" href="css/demo.css" />
        <link rel="stylesheet" type="text/css" href="css/zTreeStyle/zTreeStyle.css" />
        <script src="js/jquery-1.4.4.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/jquery.ztree.all.js" type="text/javascript" charset="utf-8"></script>
    </head>
    <script type="text/javascript">
    var zTree;
    var setting = {
            view:{
                addHoverDom:addHoverDom,
                removeHoverDom:removeHoverDom,
                selectedMulti:false
            },
            edit: {
                enable: true,
                editNameSelectAll:true,
                removeTitle:'刪除',
                renameTitle:'重命名'
            },
            data: {
                /* keep:{
                    parent:true,
                    leaf:true
                }, */
                simpleData: {
                    enable: true
                }
            },
            callback:{
                beforeRemove:beforeRemove,//點擊刪除時觸發,用來提示用戶是否確定刪除(可以根據返回值 true|false 確定是否可以刪除)
                beforeEditName: beforeEditName,//點擊編輯時觸發,用來判斷該節點是否能編輯
                beforeRename:beforeRename,//編輯結束時觸發,用來驗證輸入的數據是否符合要求(也是根據返回值 true|false 確定是否可以編輯完成)
                onRemove:onRemove,//(beforeRemove返回true之后可以進行onRemove)刪除節點后觸發,用戶后台操作
                onRename:onRename,//編輯后觸發,用於操作后台
                beforeDrag:beforeDrag,//用戶禁止拖動節點
                onClick:clickNode//點擊節點觸發的事件
            }
        };
    var zNodes =[
                 { id:1, pId:0, name:"父節點 1", open:true},
                 { id:11, pId:1, name:"去百度",url:'http://www.baidu.com',target:'_blank'},
                 { id:12, pId:1, name:"葉子節點 1-2"},
                 { id:13, pId:1, name:"葉子節點 1-3"},
                 { id:2, pId:0, name:"父節點 2", open:true},
                 { id:21, pId:2, name:"葉子節點 2-1"},
                 { id:22, pId:2, name:"葉子節點 2-2"},
                 { id:23, pId:2, name:"葉子節點 2-3"},
                 { id:3, pId:0, name:"父節點 3", open:true},
                 { id:31, pId:3, name:"葉子節點 3-1"},
                 { id:32, pId:3, name:"葉子節點 3-2"},
                 { id:33, pId:3, name:"葉子節點 3-3"}
             ];
    $(document).ready(function(){
        zTree = $.fn.zTree.init($("#tree"), setting, zNodes);
    });
    function beforeRemove(e,treeId,treeNode){
        return confirm("你確定要刪除嗎?");
    }
    function onRemove(e,treeId,treeNode){
        if(treeNode.isParent){
            var childNodes = zTree.removeChildNodes(treeNode);
            var paramsArray = new Array();
            for(var i = 0; i < childNodes.length; i++){
                paramsArray.push(childNodes[i].id);
            }
            alert("刪除父節點的id為:"+treeNode.id+"\r\n他的孩子節點有:"+paramsArray.join(","));
            return;
        }
        alert("你點擊要刪除的節點的名稱為:"+treeNode.name+"\r\n"+"節點id為:"+treeNode.id);
    }
    function beforeEditName(treeId,treeNode){
        /* if(treeNode.isParent){
            alert("不准編輯非葉子節點!");
            return false;
        } */
        return true;
    }
    function beforeRename(treeId,treeNode,newName,isCancel){
        if(newName.length < 3){
            alert("名稱不能少於3個字符!");
            return false;
        }
        return true;
    }
    function onRename(e,treeId,treeNode,isCancel){
        alert("修改節點的id為:"+treeNode.id+"\n修改后的名稱為:"+treeNode.name);
    }
    function clickNode(e,treeId,treeNode){
        if(treeNode.id == 11){
            location.href=treeNode.url;
        }else{
            alert("節點名稱:"+treeNode.name+"\n節點id:"+treeNode.id);
        }
    }
    function beforeDrag(treeId,treeNodes){
        return false;
    }
    var newCount = 1;
    function addHoverDom(treeId,treeNode){
        var sObj = $("#" + treeNode.tId + "_span");
        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length>0) return;
        var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
            + "' title='添加子節點' onfocus='this.blur();'></span>";
        sObj.after(addStr);
        var btn = $("#addBtn_"+treeNode.tId);
        if (btn) btn.bind("click", function(){
            //在這里向后台發送請求保存一個新建的葉子節點,父id為treeNode.id,讓后將下面的100+newCount換成返回的id
            //zTree.addNodes(treeNode, {id:(100 + newCount), pId:treeNode.id, name:"新建節點" + (newCount++)});
            alert("開始添加節點")
            return false;
        });
    }
    function removeHoverDom(treeId,treeNode){
        $("#addBtn_"+treeNode.tId).unbind().remove();
    }
    </script>
<body>
    <ul id="tree" class="ztree"></ul>
</body>
</html>

 

最后附一個完整的與后台交互的例子:

/***********S  QLQ*********************/
var zTree;
var setting = {
    view : {
        addHoverDom : addHoverDom,
        removeHoverDom : removeHoverDom,
        selectedMulti : false
    },
    edit : {
        enable : true,
        editNameSelectAll : true,
        removeTitle : '刪除',
        renameTitle : '重命名'
    },
    data : {
        key : {
            name:"typeName"
        },
        /* keep:{
            parent:true,
            leaf:true
        }, */
        simpleData : {
            enable : true,
            idKey: "typeId",
            pIdKey: "upId",
            rootPId: 1
        }
    },
    callback : {
        beforeRemove : beforeRemove,//點擊刪除時觸發,用來提示用戶是否確定刪除
        beforeEditName : beforeEditName,//點擊編輯時觸發,用來判斷該節點是否能編輯,是否進入編輯狀態
        beforeRename : beforeRename,//編輯結束時觸發,用來驗證輸入的數據是否符合要求
        onRemove : onRemove,//刪除節點后觸發,用戶后台操作
        onRename : onRename,//編輯后觸發,用於操作后台
        onClick : clickNode
    //點擊節點觸發的事件
    }
};
function geneTypeTree(){
    $.getJSON(contextPath+"/trainacontentType_getTraincontenttypeTree.action",function(response){
        var zNodes = response.traincontenttypeTree;
        zTree = $.fn.zTree.init($("#tree"),setting,zNodes);
    });
}

$(document).ready(function() {
    geneTypeTree();
                });


/******S  刪除*******/
function beforeRemove(treeId, treeNode) {
    if(confirm("確認刪除?\n將會刪除下面的所有視頻!")){
        if(treeNode.isParent){
            alert("該目錄下面還有子目錄,請從最底層目錄開始刪除!");
            return false;
        }
        return true;
    }
    return false;
}
function onRemove(e, treeId,treeNode) {
    var typeId = treeNode.typeId;
    $.post(contextPath+"/trainacontentType_deleteTrainContentTypeById.action",
            {"typeId":typeId},
            function(repsonse){
                alert(repsonse.result);
                if("刪除成功"==repsonse.result)//刪除成功之后執行查詢
                    btnFindFy();
            }
            ,'json')
    
    
}
/******E  刪除*******/

function beforeEditName(treeId,treeNode) {
    /* if(treeNode.isParent){
        alert("不准編輯非葉子節點!");
        return false;
    } */
    return true;
}

function beforeRename(treeId,treeNode, newName,isCancel) {
    if (newName.length < 3) {
        alert("名稱不能少於3個字符!");
        return false;
    }
    return true;
}
function onRename(e, treeId,treeNode, isCancel) {
    if(confirm("您確認修改類別名稱?")){
        $.post(contextPath+"/trainacontentType_updateTraincontenttypeName.action",
                {
            "traincontenttype.typeid":treeNode.typeId,
            "traincontenttype.typename":treeNode.typeName
                },
                function(response){
                    if(response != null){
                        if("修改成功"==response.result){
                            alert(response.result);
                        }
                    }
                }
                ,
        'json');
    }
}

/************S   點擊事件*********/
function clickNode(e, treeId,treeNode) {
    $("#trainContentTypeId").val(treeNode.typeId);//向隱藏的類別編號賦值
    $("[name='typeId']").val(treeNode.typeId);//向隱藏的類別編號賦值
    $("#yeHao").val("1");
    btnFindFy();
}
/************E   點擊事件*********/


function addHoverDom(treeId,treeNode) {
    var sObj = $("#"+ treeNode.tId+ "_span");
    if (treeNode.editNameFlag|| $("#addBtn_"+ treeNode.tId).length > 0)
        return;
    var addStr = "<span class='button add' id='addBtn_"+ treeNode.tId+ "' title='添加子節點' onfocus='this.blur();'></span>";
    sObj.after(addStr);
    var btn = $("#addBtn_"+ treeNode.tId);
    if (btn)btn.bind("click",function() {
                            if(confirm("確認在該目錄下面添加培訓內容類別?")){
                                var typeName = prompt("請輸入類別名稱");//獲取到的名字
                                if(typeName != null){//點擊確定
                                    if(typeName.length>1){
                                        var upId = treeNode.typeId;//上級編號
                                        $.post(contextPath+"/trainacontentType_addTraincontenttype.action",
                                                {
                                                    "traincontenttype.upid":upId,
                                                    "traincontenttype.typename":typeName
                                                },
                                                function(response){
                                                    if(response!=null){
                                                        alert(response.result);
                                                    }
                                                    if(response.result == "添加成功" ){
                                                        var traincontenttype = response.traincontenttype;//獲取返回來的數據
                                                        zTree.addNodes(treeNode, {typeId:traincontenttype.typeid, upId:treeNode.id, typeName:typeName});
                                                    }
//                                                    geneTypeTree();
                                                },
                                            'json');
                                    }else{
                                        alert("請輸入正確的類別名稱")
                                    }
                                }
                            }
                            //在這里向后台發送請求保存一個新建的葉子節點,父id為treeNode.id,讓后將下面的100+newCount換成返回的id
                            //zTree.addNodes(treeNode, {id:(100 + newCount), pId:treeNode.id, name:"新建節點" + (newCount++)});
                            return false;
                        });
}
function removeHoverDom(treeId,treeNode) {
    $("#addBtn_" + treeNode.tId).unbind().remove();
}

 

下面附一個更加詳細的最近用到的樹:  (包含展開所有節點,點擊,重命名,刪除,添加等事件,以及驗證操作)

/********S   左邊樹相關操作**********/
/**
 * 查詢課程類別樹結構
 */
function getTypeTree(){
    $.getJSON(contextPath + '/courseType/getTypeTree.do',{"trainSchemeId":$("#trainSchemeId").val()},geneTypeTree);
}

/**
 * 生成課程類別樹函數
 * @param typeTree  返回的課程類別信息(多一條虛擬的課程類別節點)
 */
function geneTypeTree(typeTree){
    var setting = {
        view : {
            addHoverDom : addHoverDom,//用於當鼠標移動到節點上時,顯示用戶自定義控件,顯示隱藏狀態同 zTree 內部的編輯、刪除按鈕
            removeHoverDom : removeHoverDom,//用於當鼠標移出節點時,隱藏用戶自定義控件,顯示隱藏狀態同 zTree 內部的編輯、刪除按鈕
            selectedMulti : false //設置是否允許同時選中多個節點。
        },
        edit : {
            enable : true,//設置 zTree 是否處於編輯狀態
            editNameSelectAll : true,//節點編輯名稱 input 初次顯示時,設置 txt 內容是否為全選狀態。
            removeTitle : '刪除課程類別',
            renameTitle : '重命名課程類別'
        },
        data : {
            simpleData : {
                enable : true,
                idKey : "typenum",
                pIdKey : "uptypenum",
                rootPId : "1"
            },
            key : {
                name : "typename",
            }
        },
        callback : {
            beforeRemove : beforeRemove,//點擊刪除時觸發,用來提示用戶是否確定刪除
            beforeEditName : beforeEditName,//點擊編輯時觸發,用來判斷該節點是否能編輯
            beforeRename : beforeRename,//編輯結束時觸發,用來驗證輸入的數據是否符合要求
            onRemove : onRemove,//刪除節點后觸發,用戶后台操作
            onRename : onRename,//編輯后觸發,用於操作后台
            onClick : clickNode//點擊節點觸發的事件
        }
    };
    var treeNodes = typeTree;//樹節點數據(從后台獲取)
    $.fn.zTree.init($("#treeDiv"), setting, treeNodes);//在界面生成一顆樹
    openAllTreenode();//展開樹的所有節點
}

/**
 * 展開樹的所有節點
 */
function openAllTreenode(){

    // 獲取樹對象
    var treeObj = $.fn.zTree.getZTreeObj("treeDiv");
    /* 獲取所有樹節點 */
    var nodes = treeObj.transformToArray(treeObj.getNodes());
    // 展開除第一級之外的其他節點
    for (var i = 0, length_1 = nodes.length; i < length_1; i++) {
        if(nodes[i].level == 0){
            continue;
        }
        nodes[i].open = true;
    }
    //展開第一級節點
    treeObj.expandNode(nodes[0], true);

}



/******S  刪除*******/
/**
 * 刪除前的詢問(驗證是否可以刪除)
 * @param treeId
 * @param treeNode  需要刪除的樹節點
 * @returns {boolean} 是否可以執行刪除函數
 */
function beforeRemove(treeId, treeNode) {
    var layer =getLauiLayer();
    if(treeNode.level == 0){
        layer.msg("您不可以刪除根節點!請從二級節點開始操作!",{icon:2,shade: [0.8, '#393D49']})
        return false;
    }
    if(treeNode.isParent){
        layer.msg("該目錄下面還有子目錄,請從最底層目錄開始刪除!",{icon:2,shade: [0.8, '#393D49']})
        return false;
    }
    //如果表格中有數據就不讓刪除
    if($("#trainCourseTbody").children("tr").length>0){
        layer.msg("該節點已經排有課程,不允許刪除課程類別!先刪除培養方案課程!",{icon:2,time:2*1000,shade: [0.8, '#393D49']});
        return false;
    }
    if(confirm("確認刪除?")){
        return true;
    }
    return false;
}

/**
 * 刪除的操作
 * @param e 事件
 * @param treeId    樹的界面中的ID
 * @param treeNode  節點
 */
function onRemove(e, treeId,treeNode) {
    var layer = getLauiLayer();
    var trainSchemeId = getTrainSchemeId();//培養方案編號
    var typeNum = treeNode.typenum;//類別num
    $.post(contextPath+"/courseType/deleteCourseType.do",{"trainSchemeId":trainSchemeId,"typeNum":typeNum},function (response) {
        layer.msg(response,{time:2*1000,shade: [0.8, '#393D49']},function () {
            if("刪除成功" == response){
                getTypeTree();//重新生成樹
                //1.清空條件
                var form = $("#queryTrainCourseForm");
                form.find("input").not("#queryTrainCourseTrainshemeId").val("");
                form.find("select").val("");
                //2.重新查詢一次
                queryTrainCourseByCondition();
            }
        })
    },'text')
}
/******E  刪除*******/



/****S  編輯根節點****/
/**
 * 驗證是否可以進入編輯模式
 * @param treeId
 * @param treeNode
 * @returns {boolean}   true|false代表是否進入編輯模式
 */
function beforeEditName(treeId,treeNode) {
    var layer;
    layui.use(['layer'],function () {
        layer = layui.layer;
    });
    //如果是根節點不允許編輯
    if(treeNode.level == 0 ){
        layer.msg("您不能編輯根節點!",{icon:2,shade: [0.8, '#393D49']});
        return false;
    }
    return true;
}

/**
 * 用於捕獲節點編輯名稱結束(Input 失去焦點 或 按下 Enter 鍵)之后,更新節點名稱數據之前的事件回調函數,並且根據返回值確定是否允許更改名稱的操作
 * @param treeId
 * @param treeNode
 * @param newName
 * @param isCancel
 * @returns {boolean}   是否成功
 */
function beforeRename(treeId,treeNode, newName,isCancel) {
    var layer;
    layui.use(['layer'],function () {
        layer = layui.layer;
    })
    if (($.trim(newName)).length < 2) {
        layer.alert("名稱不能少於2個字符!")
        return false;
    }
    return true;
}

/**
 * 修改名稱的操作(正經的修改傳到后台進行操作)
 * @param e
 * @param treeId
 * @param treeNode
 * @param isCancel
 */
function onRename(e, treeId,treeNode, isCancel) {
    //如果選擇了取消,重新查一下樹
    if(isCancel == true){
        getTypeTree()
        return false;
    }
    if(confirm("您確認修改類別名稱?")) {
        $.post(contextPath+"/courseType/updateCourseType.do",
            {
                "trainSchemeId":$("#trainSchemeId").val(),
                "typeNum":treeNode.typenum,
                "typeName":treeNode.typename
            },
            function(response){
                if(response != null){
                    var layer;
                    layui.use("layer",function () {
                        layer = layui.layer;
                    });
                    layer.msg(response,{shade: [0.8, '#393D49'],time:2*1000,icon:1},function () {
                        if("修改成功"==response){
                            getTypeTree();//修改成功之后重新查一下樹
                        }
                    })
                }
            }
            ,
            'text');
    }else {//如果選擇了取消重新查一下樹
        getTypeTree();//取消之后重新查樹
    }

}


/****E  編輯根節點****/

/************S   點擊事件*********/
/**
 * 點擊事件
 * @param e 事件
 * @param treeId    樹節點的ID
 * @param treeNode  樹節點
 */
function clickNode(e, treeId,treeNode) {
    $("#trainCourseTypeNum").val(treeNode.typenum);//向隱藏的課程類別編號賦值(最后添加到表單中傳到后台保存)
    $("#trainCourseTypeName").val(treeNode.typename);//
    $("#typeNum_0").val(treeNode.typenum);//向隱藏的課程類別編號賦值
    // queryTrainCourseByCondition();//分頁查詢培養方案課程信息
    clearConditionAndQueryTrainCourse();
}
/************E   點擊事件*********/

/**
 * 增加一個課程類別事件(自定義組件),用於當鼠標移動到節點上時,顯示用戶自定義控件,顯示隱藏狀態同 zTree 內部的編輯、刪除按鈕
 * @param treeId    樹節點在界面的編號
 * @param treeNode      樹節點
 */
function addHoverDom(treeId,treeNode) {
    //1.初始化layer模塊
    var layer;
    layui.use(['layer'],function () {
        layer = layui.layer;
    })
    //2.
    var sObj = $("#"+ treeNode.tId+ "_span");
    if (treeNode.editNameFlag|| $("#addBtn_"+ treeNode.tId).length > 0)
        return;
    var addStr = "<span class='button add' id='addBtn_"+ treeNode.tId+ "' title='添加子節點' onfocus='this.blur();'></span>";
    sObj.after(addStr);
    var btn = $("#addBtn_"+ treeNode.tId);
    if (btn)btn.bind("click",function() {//增加的業務邏輯寫在這里
        var name = treeNode.typename ; //獲取到當前的節點的名稱
        var typenum = treeNode.typenum ; //獲取到當前的節點的編號
        var layer = getLauiLayer();
        //如果是葉子節點並且排有課程不允許再添加
        if(!treeNode.isParent &&$("#trainCourseTbody").children("tr").length>0){
            layer.msg("該節點已經排有課程,不允許添加課程類別!",{icon:2,time:2*1000,shade: [0.8, '#393D49']});
            return;
        }
        if(confirm("確認在類別  "+name+"  下添加新的類別?")){
            //1.向隱藏的地方賦值
            $(".clear-input").val("");//清空殘留的數據
            $("#addType_uptypenum").val(typenum);//上級編號
            $("#add_trainingschemeid").val($("#trainSchemeId").val());//培養方案編號
            $("#addType_upTypeName").val(name);//上級類別名稱
            $("#addType_remark").val("無");//描述默認無
            //2.打開模態框
            var index = layer.open({
                title:'添加課程類別',
                area: [$(window).width()*0.80+'px', $(window).height()*0.70 +'px'],//大小
                fix: true, //不固定
                maxmin: true,
                zIndex:500,
                shadeClose: false,
                shade:0.4,
                type:1,
                content:$('#addTypeModal')
            });
            //向頁面隱藏index
            $("#hidden_addType_index").val(index);
        }
    });
}

/**
 *用於當鼠標移出節點時,隱藏用戶自定義控件,顯示隱藏狀態同 zTree 內部的編輯、刪除按鈕
 * @param treeId
 * @param treeNode
 */
function removeHoverDom(treeId,treeNode) {
    $("#addBtn_" + treeNode.tId).unbind().remove();
}
/********S   左邊樹相關操作**********/

 

效果:

 2. 對樹進行檢索

  在數據很多的情況下,樹形結構會變得比較復雜。需要增加關鍵字查詢功能,如下:

 

 HTML代碼:

                        <!---->
                        <div class="el_leftTree">
                            <!--標題類,添加了一個顏色-->
                            <span class="el_treeTitle">檢修單位</span>
                            <select class="btn btn-default mark-type" id="el_bigStatusMark"    title="請選擇" onchange="historyBigInfoFind()">
                                    <option value="0">當前檢修</option>
                                    <option value="1">歷史檢修</option>
                            </select>
                            <div style="margin: 5px 0px;">
                                <input type="text" id="keyword" style="width: 80%;" placeholder="關鍵字" onchange="filterKeywords()"/>
                            </div>
                            <ul id="departmentAndOverHaulTree" class="ztree"></ul>
                        </div>

需要引入的JS

 

JS代碼:

/*******S 增加關鍵字搜索功能**********/
/**
 * 查找子結點,如果找到,返回true,否則返回false
 */
function searchChildren(keyword,children){
    if(children == null || children.length == 0){
        return false;
    }
    for(var i = 0;i < children.length;i++){
        var node = children[i];
        if(node.name.indexOf(keyword)!=-1){
            return true;
        }
        //遞歸查找子結點
        var result = searchChildren(keyword,node.children);
        if(result){
            return true;
        }
    }
    return false;
}

/**
 * 查找當前結點和父結點,如果找到,返回ture,否則返回false
 */
function searchParent(keyword,node){
    if(node == null){
        return false;
    }
    if(node.name.indexOf(keyword)!=-1){
        return true;
    }
    //遞歸查找父結點
    return searchParent(keyword,node.getParentNode());
}

var hiddenNodes = []; //用於存儲被隱藏的結點

//過濾ztree顯示數據
function filterKeywords(){
    var ztreeObj = $.fn.zTree.getZTreeObj("departmentAndOverHaulTree");
    //顯示上次搜索后隱藏的結點
    ztreeObj.showNodes(hiddenNodes);
    //查找不符合條件的結點
    //返回true表示要過濾,需要隱藏,返回false表示不需要過濾,不需要隱藏
    function filterFunc(node){
        var keyword=$("#keyword").val();
    //如果當前結點,或者其父結點可以找到,或者當前結點的子結點可以找到,則該結點不隱藏
        if(searchParent(keyword,node) || searchChildren(keyword,node.children)){
            return false;
        }
        return true;
    };

    //獲取不符合條件的葉子結點
    hiddenNodes=ztreeObj.getNodesByFilter(filterFunc);

    //隱藏不符合條件的葉子結點
    ztreeObj.hideNodes(hiddenNodes);
};
/*******E 增加關鍵字搜索功能**********/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM