首页 > 代码库 > 使用 zTree 右键菜单功能的总结

使用 zTree 右键菜单功能的总结

一: 首先什么是zTree?

        zTree 是一个依靠 jQuery 实现的多功能 “树 插件 ”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。专门适合项目开发,尤其是 树状菜单、树状数据的Web显示、权限管理等等。

二:zTree的优点是什么?

      1. zTree v3.0 将核心代码按照功能进行了分割,不需要的代码可以不用加载.

      2.  采用了 延迟加载 技术,上万节点轻松加载,即使在 IE6 下也能基本做到秒杀。

      3.  兼容 IE、FireFox、Chrome、Opera、Safari 等 浏览器 。

      4.  支持 JSON 数据。

      5. 支持 静态 和 Ajax 异步加载节点数据。

      6. 支持任意更换皮肤 / 自定义图标(依靠css)。

      7. 支持极其灵活的 checkbox 或 radio 选择功能。

      8. 提供多种事件响应回调,灵活的编辑(增/删/改/查)功能,可随意拖拽节点,还可以多节点拖拽哟。

要想更多的了解zTree 请阅读官方API   http://www.ztree.me/v3/main.php    嘿嘿!!

前言: 最近在做阿里集团 "置业管理平台"项目,其中遇到最困难的问题是:zTree右键菜单功能的实现。因为以前也没有涉及过这样的 所以说实话有点鸭梨啊 折腾了很久啊! 先看下如下图:

1. 我右键菜单的时候 增加一个没有目录名称的 空节点 -----> 分2种情况 第一:此节点有没有父节点 一般没有父节点 父节点都为null 第二: 如果有父节点的话 那么在右侧的 父目录 显示是那个父目录下的父节点名称。

        2. 在左侧只能新建一项空菜单, 不能接着新建第二项 第三项 因为如果可以新建第二项 第三项的话 然后我在右侧填好后 点击保存按钮 开发分不清那个是那个,所以我们前端需要控制只能新建一项 当点击保存按钮后 左侧没有空菜单项时候 接着可以新建第二项或第二子项。

        3. 当我点击左侧已新建的项时或者点击左侧已有项时 右侧渲染相应的数据。如下图所示:

     4. 每次新建一项时候 判断有没有父节点 如有的话 把父节点ID传给开发(发请求),当然参数要传入有如下四个:1.自身ID,2. 父节点ID,3.当前目录的id 是在哪个目录下的 如上图所示 是在开发类型下的,4. 是什么模式 默认情况分2种(创建:create 还是 修改:update). 当时创建的时候 自身ID肯定是没有的 是undefined,最纠结的是 每次新建一项时候 父节点ID我拿不到  纠结 纳闷就在这里。

     具体的做法暂时先不讲,待会讲,首先让我们来认识下 zTree的基本功能 基本创建节点的方法。首先我们可以先做个demo 比如我想静态实现如下图demo:

父节点可以展开或者收缩 有子节点或者没有子节点,首先我们可以在页面上需要 引入:jquery1.9.1.js  ztree.core.js ztree.css等

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://www.ztree.me/v3/css/demo.css"/>
<link rel="stylesheet" href="http://www.ztree.me/v3/css/zTreeStyle/zTreeStyle.css"/>
<script src="http://www.ztree.me/v3/js/jquery.ztree.core-3.5.js?2013031101"></script>

然后需要在页面上有存放树节点的容器 我们可以如下HTML代码:

<div class="zTreeDemoBackground left">
<ul id="treeDemo" class="ztree"></ul>
</div>

接着就是我们用js对树初始化了。如下:

var setting = {};        var zNodes =[            { name:"父节点1 - 展开", open:true,                children: [                    { name:"父节点11 - 折叠",                        children: [                            { name:"叶子节点111"},                            { name:"叶子节点112"},                            { name:"叶子节点113"},                            { name:"叶子节点114"}                        ]},                    { name:"父节点12 - 没有子节点", isParent:true}                ]},            { name:"父节点2 - 折叠",                children: [                    { name:"父节点21 - 展开", open:true,                        children: [                            { name:"叶子节点211"},                            { name:"叶子节点212"},                            { name:"叶子节点213"},                            { name:"叶子节点214"}                        ]}                ]},            { name:"父节点3 - 没有子节点", isParent:true}        ];        $(document).ready(function(){            $.fn.zTree.init($("#treeDemo"), setting, zNodes);        });

首先 setting对象 是提供默认配置项 不太清楚的 可以看下 API http://www.ztree.me/v3/api.php 特别是提供了丰富的回调函数等。zNodes格式 是我们希望开发 能输出这样的格式出来 然后我们可以直接调用这句 加载出来  $.fn.zTree.init($("#treeDemo"), setting, zNodes); 如果想要某一项以文件夹显示 那么设置isParent:true就可以 否则的话是以子节点文件 表现的。上面的只是静态的加载数据 不是动态的加载。这样有缺点,比如页面上有很多的节点话 那么输出一大串出来 然后js分别渲染进去 相对来说 前端性能变差了。但是我们也可以动态的去加载 也就是说 我们可以默认展开第二项父节点,当我们每次去点击某一项父节点时候 如果有子节点的话  那么去加载对应父节点下的子节点,这样相对来说 性能提高了 不必全部加载出来。那么动态的加载 我们只需要开发那边只提供输出这样如下格式:

[{ id:‘011‘, name:‘n1.n1‘, isParent:true},{ id:‘012‘, name:‘n1.n2‘, isParent:false},{ id:‘013‘, name :‘n1.n3‘, isParent:true},{ id:‘014‘, name:‘n1.n4‘, isParent:false}]。切记:一定是这种格式,不能像这样输出 

{count:[  { id:‘011‘,name:‘n1.n1‘,isParent:true},    { id:‘012‘,	name:‘n1.n2‘,	isParent:false},    { id:‘013‘,	name:‘n1.n3‘,	isParent:true},    { id:‘014‘,	name:‘n1.n4‘,	isParent:false}]}然后就想获取count 就以为可以拿到数据。据我所知,这样输出貌似不行的。动态JS初始化可以如下操作就ok了!
var setting = {  async: {    enable: true,    url:"../asyncData/getNodes.php",    autoParam:["id", "name=n", "level=lv"]  }};$(document).ready(function(){  $.fn.zTree.init($("#treeDemo"), setting);});
首先 他是异步的 所以配置项 async enable: true 表示异步 false表示关闭异步加载模式。url 是我们要请求url 
注意:不需要我们另外发ajax请求 只要上面这种写法就ok了 当我们一点击一项时候 代码内部已经帮我们做了点击事件了 发ajax请求了 所以我们只要这种配置就ok了!好了 我们已经熟悉了下基本的zTree了 要想了解更多的信息 可以去官网看API 再结合自己的需求去折腾 研究了 API: http://www.ztree.me/v3/api.php 下面还是回到我刚刚上面的需求上来看看了,嘿嘿!首先我要说的是:页面一加载时候 我也是静态的加载数据 因为开发据说用的是框架 也无法给到我动态数据那种格式,所以只能开发输出静态数据出来 然后进行初始化。一: 右键菜单,如下图:
 我这边需求有三项 分别是: 作废子目录 增加子目录 刷新子目录。先来看看 增加子目录项,首先我们得在配置里面有个回调函数:如下:
var setting = {  data : {    simpleData : {      enable : true    },    keep: {      parent: true /*如果设置为 true,则所有 isParent = true 的节点,即使该节点的子节点被全部删除或移走,依旧保持父节点状态 */    }  },  callback : {    onRightClick : OnRightClick,    onClick : zTreeOnClick  }};
当我们右键下时候 执行OnRightClick 函数:函数如下:
function OnRightClick(event, treeId, treeNode) {        if(treeNode == null) {        var a = 1; // 什么都不做    }else if(treeNode && treeNode.name) {        curName = treeNode.name;    }else {        curName = undefined;    }      if (!treeNode && event.target.tagName.toLowerCase() != "button"      && $(event.target).parents("a").length == 0) {    zTree.cancelSelectedNode();    $("#idCipherText").val("");    showRMenu("root", event.clientX, event.clientY);  } else if (treeNode && !treeNode.noR) {    zTree.selectNode(treeNode);        if(treeNode.id) {        $("#idCipherText").val(treeNode.id);    }    showRMenu("node", event.clientX, event.clientY);  }  $("#typeIdCipherText").val($("#docType").attr("value"));}

首先 右键回调函数 返回三个参数:event 事件 treeId 最外层容器元素ID treeNode 树节点 返回的是一个对象 如下图:

     由于 是顶级的 没有pId 所以pId肯定是null或者undefined 接着代码里面做了一个判断curName  右键返回对象的 如果有name的话 那么保存到全局对象 否则 undefined 是为了下文后续操作  还有这句代码

if(treeNode.id) {  $("#idCipherText").val(treeNode.id);} 如果有id的话 那么把他们放入form表单隐藏域去,如下:   为了开发提交,下面我们来看这句代码 :
var newNode = {     name:"",    isParent : true,    checked : true,    elemNode: undefined};

每次新建一个新节点时候 默认情况下 我都让他为空:如下图:

function addTreeNode() {    hideRMenu();     var parentId;    var selectedNodes = zTree.getSelectedNodes()[0];        if (selectedNodes) {           if(newNode.name == ‘‘) {               _publicFun(selectedNodes,newNode);           }else {               $(‘#parentDirName‘).html("");           }      } else {        if(newNode.name == ‘‘) {            _publicFun(selectedNodes,newNode);        }            }    var select = $("#docType")[0],        selectVal = getSelectValue(select);           var selectId =  zTree.getSelectedNodes();            if(isBoolean) {       if(selectedNodes && selectedNodes.id) {           parentId = selectedNodes.id;       }        getDir(undefined,parentId,selectVal,‘create‘);        isBoolean = false;    }    zTreeArrs = [];}
/** * 处理基本操作  */function _publicFun(selectedNodes,newNode) {    var curNode =  zTree.addNodes(selectedNodes, newNode),        parentNode = $(‘#‘ + curNode[0].tId);    $(‘a‘).hasClass("curSelectedNode") && $(‘a‘).removeClass("curSelectedNode");    !$(‘a‘,parentNode).hasClass("curSelectedNode") && $(‘a‘,parentNode).addClass("curSelectedNode");    var afirst = $(‘a‘,parentNode).first();    newNode.elemNode = $(‘span‘,afirst).last();      newNode.name = ‘temp‘; }

每次创建一个空节点 然后进行初始化 zTree.addNodes(selectedNodes, newNode),那么页面初始化时空节点菜单,之后给name赋值为临时 temp 目的是希望用户不要老是新建空项 只能新建一项空菜单项 所以在 addTreeNode 函数里面用了 if(newNode.name == ‘‘) {}这个判断语句  当我点击保存按钮后 后台给我返回了name的话 然后我就动态的给左侧空菜单赋值操作 接着 又让newNode对象里面的name = "" 所以左侧菜单又可以新建一项了:

newNode = {                     id: idCipherText,                    pId: parentIdCipherText,                    name:"",                    isParent : true,                    checked : true,                    elemNode: undefined                };

接着 假如我想修改左侧菜单项名称 怎么办?首先我们可以先点击左侧菜单某一项:如下图:

// 修改一项名称 当我点击左侧树形菜单后 再修改name(树名称)后  值覆盖                function removeItemId (id,arrs) {                    for(var i = 0, ilen = arrs.length; i < ilen; i+=1) {                        if(id == arrs[i].id) {                            return arrs.splice(i,1);                        }                    }                }                if(treeNodeArrs.id == idCipherText) {                    removeItemId(idCipherText,zNodes);                                    }else {                   /**                    * 点击保存后 由于左侧树目录要重新初始化下 我不知道哪个选中了 所以 右边的内容清空掉                     */                    $("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());                 }

最后让我们来分析下 我最纠结的问题是: 我每次右键菜单时候 我怎么样能获取父节点ID,首先我做了这么样的一个操作 当我们每次新建的时候 然后保存 我都让她们后台返回的当前id 父元素id name 放入原来数组里去 :

zNodes.push({         id: idCipherText,         pId: parentIdCipherText,         name:name,         isParent : true, });

然后重新初始化下 : $.fn.zTree.init($("#directoryTree"), setting, zNodes); 这样树形菜单会刷新下,但是不会展开 所以接着分析用到了zTree的一个属性 expandNode 让他重新展开 代码如下:

//展开树                var url = "/rocky/document/documentDirectory/getRootId.json";                var cond = "dirCipherText=" + idCipherText;                                 common.f.commonAjaxGet(url, cond, function(data) {                    if(data && data.content) {                         var node = treeObj.getNodeByParam("id", data.content, null);                         if(node){                             treeObj.expandNode(node, true, true, false);                         }                    }                },false);

但是这样做有一个缺点是 当我们展开了很多项的子项时候 我们点击保存后 只能使当前的项及所有子项展开 其他项没有展开。目前我只能想到这个方法了 如果大家有其他好方法可以分享下。通过上面的操作 当我们一增加一个节点addTreeNode时候 我们就可以拿到当前增加项 父节点id了 

if(selectedNodes && selectedNodes.id) {
parentId = selectedNodes.id;
}

var setting = {  /**view : {    dblClickExpand : false  },**/  data : {    simpleData : {      enable : true    },    keep: {      parent: true    }  },  callback : {    onRightClick : OnRightClick,    onClick : zTreeOnClick  }};var zNodes = $.parseJSON($("#hiddenTree").val()),    zTreeArrs = [],    /*zTreeArrs2 = [],*/    zTreeObj = [],    tempVal,    treeNodeArrs = [];function OnRightClick(event, treeId, treeNode) {        if(treeNode == null) {        var a = 1; // 什么都不做    }else if(treeNode && treeNode.name) {        curName = treeNode.name;    }else {        curName = undefined;    }      if (!treeNode && event.target.tagName.toLowerCase() != "button"      && $(event.target).parents("a").length == 0) {    zTree.cancelSelectedNode();    $("#idCipherText").val("");    showRMenu("root", event.clientX, event.clientY);  } else if (treeNode && !treeNode.noR) {    zTree.selectNode(treeNode);        if(treeNode.id) {        $("#idCipherText").val(treeNode.id);    }    showRMenu("node", event.clientX, event.clientY);  }  $("#typeIdCipherText").val($("#docType").attr("value"));}function showRMenu(type, x, y) {  $("#rMenu ul").show();  if (type == "root") {    $("#m_del").hide();    $("#m_check").hide();    $("#m_unCheck").hide();  } else {    $("#m_del").show();    $("#m_check").show();    $("#m_unCheck").show();  }  rMenu.css({    "top" : y + "px",    "left" : x + "px",    "visibility" : "visible"  });  $("body").bind("mousedown", onBodyMouseDown);}function hideRMenu() {  if (rMenu)    rMenu.css({      "visibility" : "hidden"    });  $("body").unbind("mousedown", onBodyMouseDown);}function onBodyMouseDown(event) {  if (!(event.target.id == "rMenu" || $(event.target).parents("#rMenu").length > 0)) {    rMenu.css({      "visibility" : "hidden"    });  }}var newNode = {     name:"",    isParent : true,    checked : true,    elemNode: undefined};var obj = undefined;var isBoolean = true;function getDir(dirId,pId,catalogId,mode) {    if(dirId == undefined) {        dirId = "";    }    if(pId == undefined) {        pId = ‘‘;    }    $("#loadData").load(            "/rocky/document/directory/directoryEditView.vm?docDirIdCipher="                    + dirId+"&parentIdCipher="+pId+"&timestate="+(new Date()).getTime(),function(data){                        // form表单keyup时候 判断必填项是否为空                        formKeyUp();                        $(‘.btns‘).unbind(‘click‘);                        $(‘.btns‘).bind(‘click‘,function(){                            //表单验证  如果为空的话 不发请求                           var code = $.trim($(‘#code‘).val()),                               name = $.trim($(‘#name‘).val());                            if(code == ‘‘) {                                $(‘#errorCode‘).hasClass(‘hidden‘) && $(‘#errorCode‘).removeClass(‘hidden‘);                                $("#errorCode").html("必选字段");                                return;                            }                            if(name == ‘‘){                                $(‘#errorName‘).hasClass(‘hidden‘) && $(‘#errorName‘).removeClass(‘hidden‘);                                $(‘#errorName‘).html(‘必选字段‘);                                return;                                         }                                          if(code.length > 100) {                                return;                            }                            if(name.length > 100) {                                return;                            }                            _request(dirId,pId,catalogId,mode);                        });                    }); }function zTreeOnClick(event, treeId, treeNode) {    treeNodeArrs = treeNode;    var lists = $(‘#‘ + treeId + " li");    $.each(lists,function(i,item) {        $(‘a‘,item).hasClass("curSelectedNode") && $(‘a‘,item).removeClass(‘curSelectedNode‘);     });    var treeName = $(event.target).html();    var curElem = $(‘#‘ + treeNode.tId);    !$(‘a‘,curElem).first().hasClass("curSelectedNode") && $(‘a‘,curElem).first().addClass("curSelectedNode");    //var pId = treeNode.pId;    var pId = treeNode.pId;    if(pId == null) {        pId = ‘‘;    }       if(newNode.id == undefined) {           // 页面一渲染后 页面一有的数据点击 执行下面操作             getDir(treeNode.id,pId,zTreeArrs[2],‘update‘);        }else if(newNode.id != undefined && treeNode.name != ‘‘) {           getDir(treeNode.id,pId,zTreeArrs[2],‘update‘);        }else {           var index = currentIndex(treeName,zTreeObj);           if(index > -1 && zTreeObj.length > 1) {                var idCipherText = zTreeObj[index].idCipherText,                     parentIdCipherText = zTreeObj[index].parentIdCipherText;                // 新建一项后 再新建第二项 接着点击第二项时候 执行下面操作                getDir(idCipherText,parentIdCipherText,zTreeArrs[2],‘update‘);            }else {                              // 当新建一项时候 执行下面的操作               getDir(newNode.id,newNode.pId,zTreeArrs[2],‘update‘);           }                  }        zTreeArrs = [];    };function addTreeNode() {  hideRMenu();   var parentId;  var selectedNodes = zTree.getSelectedNodes()[0];    if (selectedNodes) {           if(newNode.name == ‘‘) {               _publicFun(selectedNodes,newNode);           }else {               $(‘#parentDirName‘).html("");           }      } else {        if(newNode.name == ‘‘) {            _publicFun(selectedNodes,newNode);        }            }    var select = $("#docType")[0],        selectVal = getSelectValue(select);           var selectId =  zTree.getSelectedNodes();            if(isBoolean) {       if(selectedNodes && selectedNodes.id) {           parentId = selectedNodes.id;       }        getDir(undefined,parentId,selectVal,‘create‘);        isBoolean = false;    }    zTreeArrs = [];}/** * 处理基本操作  */function _publicFun(selectedNodes,newNode) {    var curNode =  zTree.addNodes(selectedNodes, newNode),        parentNode = $(‘#‘ + curNode[0].tId);    $(‘a‘).hasClass("curSelectedNode") && $(‘a‘).removeClass("curSelectedNode");    !$(‘a‘,parentNode).hasClass("curSelectedNode") && $(‘a‘,parentNode).addClass("curSelectedNode");    var afirst = $(‘a‘,parentNode).first();    newNode.elemNode = $(‘span‘,afirst).last();      newNode.name = ‘temp‘; }/** * ajax请求  */function _request(dirId,pId,catalogId,mode) {    var select = $("#docType")[0],        selectVal = getSelectValue(select);      if( $("#idCipherText").attr("value")!= undefined && $("#idCipherText").attr("value")!=""){    	  mode=‘update‘;    	  dirId = $("#idCipherText").attr("value");    	  pId =  $("#parentIdCipherText").attr("value");      }    $("input[name=‘mode‘]").attr("value",mode);    $("#idCipherText").attr("value",dirId);    $("#typeIdCipherText").attr(‘value‘,selectVal);    $("#parentIdCipherText").attr("value",pId);    $.ajax({         type:‘post‘,         data: $("#directory").serialize(),         url: ‘/rocky/document/documentDirectory/createDorDir.json?timestate=‘+(new Date()).getTime(),         success: function(data){                         if(data.content) {                var name = data.content.name,                    idCipherText = data.content.idCipherText,                    parentIdCipherText = data.content.parentIdCipherText,                    typeIdCipherText = data.content.typeIdCipherText;                                $(newNode.elemNode).html(name);                                $("#idCipherText").attr("value",idCipherText);                $("#parentIdCipherText").attr("value",parentIdCipherText);                zTreeArrs = [];                zTreeArrs.push(idCipherText,parentIdCipherText,typeIdCipherText);                zTreeObj.push({name:data.content.name,idCipherText:data.content.idCipherText,parentIdCipherText:data.content.parentIdCipherText});                isBoolean = true;                newNode = {                     id: idCipherText,                    pId: parentIdCipherText,                    name:"",                    isParent : true,                    checked : true,                    elemNode: undefined                };                zNodes.push({                    id: idCipherText,                    pId: parentIdCipherText,                    name:name,                    isParent : true,                });                                // 修改一项名称 当我点击左侧树形菜单后 再修改name(树名称)后  值覆盖                function removeItemId (id,arrs) {                    for(var i = 0, ilen = arrs.length; i < ilen; i+=1) {                        if(id == arrs[i].id) {                            return arrs.splice(i,1);                        }                    }                }                if(treeNodeArrs.id == idCipherText) {                    removeItemId(idCipherText,zNodes);                                    }else {                   /**                    * 点击保存后 由于左侧树目录要重新初始化下 我不知道哪个选中了 所以 右边的内容清空掉                     */                    $("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());                 }                $.fn.zTree.init($("#directoryTree"), setting, zNodes);                var treeObj = $.fn.zTree.getZTreeObj("directoryTree");                //展开树                var url = "/rocky/document/documentDirectory/getRootId.json";                var cond = "dirCipherText=" + idCipherText;                                 common.f.commonAjaxGet(url, cond, function(data) {                	if(data && data.content) {                		 var node = treeObj.getNodeByParam("id", data.content, null);                         if(node){                         	treeObj.expandNode(node, true, true, false);                         }                	}                },false);                                 if(dirId){                     $.jBox.success("修改成功", "修改确认", {                        timeout : 3000,                        height : 120                    });                } else{                      $.jBox.success("保存成功", "保存确认", {                        timeout : 3000,                        height : 120                    });                }            }else {                $.jBox.error("目录类别代码重复", "确认", {                        timeout : 3000,                        height : 120                    });            }                        //console.log(newNode);         }     }); }/** *  获取下拉框selelct 选中的值 */function getSelectValue(select) {    var idx = select.selectedIndex, //获取选中的option的索引        option,        value;    if(idx > -1) {        option = select.options[idx];  //获取选中的option元素        value = http://www.mamicode.com/option.attributes.value;"/rocky/document/documentDirectory/deleteDocDir.json";              var cond = "dirCipherText=" + id + "&typeIdCipherText=" + $("#typeIdCipherText").val();              common.f.ajaxPost(url,cond,function(data){              	var results = data.content;              	if(results=="success") {              		zTree.removeNode(nodes[0]);              		$("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());              		$.jBox.success("删除成功", "确定",{timeout: 2000, height: 120});              	} else if(results=="the_doc_dir_had_deleted") {              		$.jBox.error("该目录已经被删除!", "确定",{timeout: 2000, height: 120});              		$("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());              	}              	 else if(results=="has_sub_doc_dir") {              		 $.jBox.error("该目录含有子目录,不能删除!", "确定",{timeout: 2000, height: 120});               	} else if(results == "doc_dir_assoataion_others"){               		 $.jBox.error("该目录含有文档不能删除!", "确定",{timeout: 2000, height: 120});               	} else if(results=="db_error") {               		 $.jBox.error("该目录含有文档不能删除!", "确定",{timeout: 2000, height: 120});               		                	}              });    //}       }  newNode = {         name:"",        isParent : true,        checked : true    };}function checkTreeNode(checked) {  var nodes = zTree.getSelectedNodes();  if (nodes && nodes.length > 0) {    zTree.checkNode(nodes[0], checked, true);      }  hideRMenu();}/** * 从数组里面删除一项对象 [{ id="d04ec6de791520f4d51ca1cdbc7c7c3c", name="1234", isParent=true},{},{}] 等等 * @param {name} 根据name 来删除 * @return [] 返回新的数组  */function removeItem(name,arrs) {    arrs = arrs || [];    var index = currentIndex(name,arrs);    if(index > -1) {        return arrs.splice(1,index);    }else {        return [];    }}/** * 从数组获取当前的索引index * @param {name arrs}  * return {index} 索引  */function currentIndex(name,arrs) {    if(arrs.length > 0) {        for(var j = 0, jlen = arrs.length; j < jlen; j+=1) {            var curName = arrs[j].name;            if(name == curName) {                return j;            }        }        return -1;    }    }function resetTree() {  hideRMenu();  /**newNode = {         name:"",        isParent : true,        checked : true,        elemNode: undefined    };**/        // 重新加载        $("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());        var url = "/rocky/document/documentDirectory/getDocDirTreesByTypeId.json",            select = $("#docType")[0],            selectVal = getSelectValue(select);        var cond = "dirCipherText=" + selectVal;                 common.f.commonAjaxGet(url, cond, function(data) {            hideRMenu();            if(data && !data.hasError) {                zNodes = $.parseJSON(data.content);                $.fn.zTree.init($("#directoryTree"), setting, zNodes);            }        });   /**  $.fn.zTree.init($("#directoryTree"), setting, zNodes);  **/  }var zTree, rMenu;$(document).ready(function() {    $("#m_add").unbind(‘click‘);    $("#m_add").bind(‘click‘,function(){        addTreeNode();    });  $.fn.zTree.init($("#directoryTree"), setting, zNodes);  zTree = $.fn.zTree.getZTreeObj("directoryTree");  rMenu = $("#rMenu");  // docType change event  $("#docType").prev().delegate("a", "click", function() {              // newNode 新建的节点(没有数据情况下)清空掉        newNode = {            name:"",            isParent : true,            checked : true,            elemNode: undefined        };        // 重新加载        $("#loadData").load("/rocky/document/directory/directoryEditView.vm?timestate="+(new Date()).getTime());    var url = "/rocky/document/documentDirectory/getDocDirTreesByTypeId.json";    var cond = "dirCipherText=" + $(this).attr("value");;    common.f.commonAjaxGet(url, cond, function(data) {      hideRMenu();      if(data && !data.hasError) {        zNodes = $.parseJSON(data.content);        $.fn.zTree.init($("#directoryTree"), setting, zNodes);      }    });  });});

使用 zTree 右键菜单功能的总结