zoukankan      html  css  js  c++  java
  • 【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+"
    他的孩子节点有:"+paramsArray.join(","));
                return;
            }
            alert("你点击要删除的节点的名称为:"+treeNode.name+"
    "+"节点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+"
    修改后的名称为:"+treeNode.name);
        }
        function clickNode(e,treeId,treeNode){
            if(treeNode.id == 11){
                location.href=treeNode.url;
            }else{
                alert("节点名称:"+treeNode.name+"
    节点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("确认删除?
    将会删除下面的所有视频!")){
            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=" 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 增加关键字搜索功能**********/
  • 相关阅读:
    2558: 游起来吧!超妹!
    2554: 巨巨来袭
    2557: 不如来21玩一局?
    tortoisesvn 本项目的忽略项
    【C语言】随机数随机种子
    【leetcode】按奇偶排序数组
    【leetcode】按奇偶排序数组 II
    【leetcode】根据数字二进制下 1 的数目排序
    【leetcode】合并排序的数组
    【leetcode】稀疏数组搜索
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/8516207.html
Copyright © 2011-2022 走看看