jQuery zTree搜索-关键字查询 递归无限层功能实现代码

 唠叨一哈

  前两天朋友跟我说要一个ztree的搜索功能,我劈头就是一巴掌:这种方法难道无数前辈还做少了?自己去找,我很忙~然后我默默地蹲着写zTree的搜索方法去了。为什么呢?因为我说了句“找不到是不可能的啊,肯定有很多人早做了无数了,找不到我给你写还请你恰午饭”,然而我也去找了很久也没有找到(泪崩,我的计划,我的午饭~)。绝大多数都是用的API里面的getNodesByParamFuzzy()或者高亮之类的。然而朋友表示需求不符合:1. 匹配失败父节点也隐藏;2.能自定义匹配规则,即能匹配name还能匹配属性......(反正就是我想要的不是辣个,小生脸上笑嘻嘻,心里.......那我给你写呗~),下面进入正文:

思维导图

  

  一般搜索功能只是在“既定范围内(方便称呼)”匹配关键字,“既定范围”即我们已经知道搜索的范围:比如说一个文本库,一个下拉框,换而言之我们匹配的对象集大小已经确定了。然而这一点在ztree上不可行,为什么呢?在我考虑了一下ztree搜索功能实现逻辑的时候问了一句:那啥,这棵树的层级是固定的吗?还是说不确定有多少层?老哥看着我会心一笑:你按无限层来写~小生小腿肚子一抽。。因为树的层级不确定,所以搜索范围不确定,举个栗子:目标节点匹配成功,如果这个节点是子节点,那么它的父节点也应该是显示的,然后它父节点的父节点也应该是显示的,然后它父节点的父节点的父节点的...Orz...这仿佛永远写不到尽头了...没办法,只能:递归,找到目标节点的所有父节点和子节点。

逻辑关键点

  在上面的思维导图中我大致列出了逻辑,目标节点在什么情况下显示,什么情况下隐藏,这是我们必须清楚的关键点,下面我们具体看下目标节点存在的情况:

  

  到了这里,相信对于如何实现满足我们需求的搜索功能开发,已经能做到了然于心了,剩下的只是实现的方法,然而这完全不是事~(小生窃以为真正让人忧心的理不清功能的流程,至于实现方法你们都懂的吧?0.0..)

关于树节点

  要完成上述流程中各种方法,我们需要知道树节点的一系列属性,我们都知道有api这种神器,然而api有一个特点就是齐全(齐全得我们想精确的找到某一个属性或者方法时可能得一顿好找),这里我们想要的是如何快速得到自己想要的属性或者方法,我们在控制台打印出树节点集合: 

 var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 设置根节点
  var node = treeObj.getNodes(); // 获取根节点
  var nodes = treeObj.transformToArray(node); // 获取所有节点
  console.log(nodes); 

  看图:我们能看到所有节点,其中有id,name等各种属性

  再看图:我们能看到任意节点的各种属性,有我们想要的子节点集合 childern,父节点属性 isParent ,节点id tId,父节点id parentTid...

万事俱备,动手

  下面看一下相关方法,很多小细节需要在真正编码过程中才能发现,这里为了方便展示就直接列举方法了。

  声明备用数组:

// 地区搜索
 var parentArray = [];
 var childArray = [];

  递归获取目标节点父节点集合:

 // 递归获取目标节点所有父节点
 function getParentsNode(treeNode){
  var thisParentNode = treeNode.getParentNode(); //得到该节点的父节点
  if( thisParentNode != null ){ // 父节点存在
   parentArray.push(thisParentNode); // 储存至数组
   getParentsNode(thisParentNode); // 重调
  }else{
   return false;
  }
 }

  递归获取目标节点子节点集合:

 // 递归获取目标节点所有子节点
 function getChildrenNode(treeNode){
  var thisIsParent = treeNode.isParent; // 获取目标节点 isParent 属性,判断是否为父节点
  if( thisIsParent == true ){
   var thisChildrenNode = treeNode.children; // 得到该节点的子节点集合
   for(var i=0;i<thisChildrenNode.length;i++){
    childArray.push(thisChildrenNode[i]); // 将该子节点加入数组中
    getChildrenNode(thisChildrenNode[i]); // 重调
   }
  }else{
   return false;
  }
 }

  这里建议将匹配节点部分摘出来单独写一个方法,方便进行拓展匹配规则,这里我们假设除了匹配name还需要匹配节点的 entity_code 属性:

 //匹配节点
 function matchNode(treeNode,num){
  var inputArea = $("input[name='searchArea']");
  var name = treeNode.name;
  var entityCode = treeNode.entity_code|| '';
  var val = inputArea.val(); // 获取检索值
  var numName = name.indexOf(val);
  var numCode = entityCode.indexOf(val);
  var num = -1;
  if( numName != -1 || numCode !=-1 ){
   num = 1;
  }
  if( numName == -1 && numCode == -1 ){
   num = -1;
  }
  return num;
 }

  节点匹配成功方法:

 // 节点匹配成功
 function checkTrueArray(arr,treeNode){
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  for(var n=0;n<arr.length;n++){
   var thisNodeId = arr[n].tId;
   var thisNodeLi = $("#"+thisNodeId);
   thisLi.show();
   thisNodeLi.show();
  }
 }

  节点匹配失败方法:

 // 节点匹配失败
 function checkFalseArray(arr,treeNode){
  var result = [];
  var result2 = [];
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  var val = inputArea.val(); // 获取检索值
  var thisParent = treeNode.getParentNode(); // 获取目标节点父节点
  if( thisParent != null ){ // 有父节点
   var thisBrotherArr = treeNode.getParentNode().children; // 得到包含自身的兄弟数组
   for(var m=0;m<arr.length;m++){ // 匹配父节点
    var num = matchNode(arr[m]);
    if( num != -1 ){
     result.push(arr[m]);
    }
   }
   var resultLength = result.length;
   for( var m=0;m<thisBrotherArr.length;m++ ){ // 匹配兄弟节点
    var num = matchNode(thisBrotherArr[m]);
    if( num != -1 ){
     result2.push(thisBrotherArr[m]);
    }
   }
   var resultLength2 = result2.length;
   // 对于自身匹配失败的节点,要显示必须满足有父节点匹配成功,且兄弟级节点都匹配失败
   if( (resultLength == 0 && resultLength2 == 0) || resultLength2 != 0 ){
    thisLi.hide();
   }
   if( resultLength !=0 && resultLength2 == 0 ){
    thisLi.show();
   }
  }else{
   thisLi.hide();
  }
 }

   目标节点匹配失败 目标节点即有父节点又有子节点:

 // 目标节点匹配失败 目标节点即有父节点又有子节点
 function checkAllArray(arr,arr2,treeNode){
  var result = [];
  var result2 = [];
  var thisTid = treeNode.tId;
  var thisLi = $("#"+thisTid);
  var val = inputArea.val(); // 获取检索值
  for(var m=0;m<arr.length;m++){ // 匹配子节点或父节点
   var num = matchNode(arr[m]);
   if( num != -1 ){
    result.push(arr[m]); // 匹配成功储存至数组
   }
  }
  var resultLength = result.length; // 获取匹配成功后返回的数组长度
  for(var m=0;m<arr2.length;m++){ // 匹配子节点或父节点
   var num = matchNode(arr2[m]);
   if( num != -1 ){
    result2.push(arr2[m]); // 匹配成功储存至数组
   }
  }
  var resultLength2 = result2.length; // 获取匹配成功后返回的数组长度
  if( resultLength == 0 && resultLength2 == 0 ){ // 子节点和父节点都匹配失败
   thisLi.hide();
  }else{
   thisLi.show(); // 有一种匹配成功或都匹配成功
  }
 }

  定义搜索方法:

 function searchArea(treeId, treeNode){ // 定义搜索方法
  var inputArea = $("input[name='searchArea']");
  var val = inputArea.val(); // 获取检索值
  var treeObj=$.fn.zTree.getZTreeObj("homeTree"); // 设置根节点
  var node = treeObj.getNodes(); // 获取根节点
  var nodes = treeObj.transformToArray(node); // 获取所有节点
  console.log(nodes);
  for(var i=0;i<nodes.length;i++){
   var thisNodePid = nodes[i].pId;
   var thisParentNode =
   parentArray = [];
   childArray = [];
   getParentsNode(nodes[i]); // 获取目标节点所有父节点 返回数组
   getChildrenNode(nodes[i]); // 获取目标节点所有子节点 返回数组
   var num = matchNode(nodes[i]);
   if( nodes[i].isParent == false ){
    if( num != -1 ){
     checkTrueArray(parentArray,nodes[i]);
    }else{
     checkFalseArray(parentArray,nodes[i]);
    }
   }
   if( nodes[i].isParent == true ){
    if( num != -1 ){
     checkTrueArray(parentArray,nodes[i]);
     checkTrueArray(childArray,nodes[i]);
    }else{
     checkAllArray(parentArray,childArray,nodes[i]);
    }
   }
  }

 }

  调用搜索方法:

 // 调用搜索方法
 $(".searchAreaBtn").click(function(treeId, treeNode){
  searchArea(treeId, treeNode);
 });
 var inputArea = $("input[name='searchArea']");
 inputArea.keyup(function(treeId, treeNode,e){
  var e = event || window.event;
  var val = inputArea.val();
  if( e.keyCode == 13 || val == "" ){
   searchArea(treeId, treeNode);
  }
 });

  看效果(电脑ps出问题了,用美图秀秀拼的图~囧...):

结语

  理论上来说应该是能支持无限层的,最多试了四层,没有问题,没有做更多测试,有兴趣的看官可以试试,需要demo的可以留言,互相学习,一起进步,么么哒~

总结

以上所述是小编给大家介绍的jQuery zTree搜索-关键字查询 递归无限层功能实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 基于jQuery实现搜索关键字自动匹配功能

    今天我们就一起来看一个简单的基于jquery的关键字自动匹配的例子,希望文章能够对各位有帮助. 例子一 在项目中,有时候需要用户选择城市,但是城市太多,用户选择起来不太方便,所以提供了一个用户可以通过输入框输入城市的汉字或者拼音简写.结果示意图如下: 当输入拼音后结果示意图如下: 实现代码如下: <html><head><title>实时查询城市通过姓名或拼音简写</title></head><meta charset = "ut

  • 基于jquery的表格排序

    很多高手也位jquery写了专门的排序库,因为自己也想尝试一下, 当然运行速度实在不能接受,但是我会慢慢的把他改进的. 注:这里只是拿出了一部分代码来,查看演示demo 文档载入后给'th'添加click事件. 1. $('th').click(function(){ var date1=(new Date()).getTime() var dataType=$(this).attr('dataType'); 找到点击对象的自定义属性dataType,当然这个不符合W3C的标准是无法通过检验的,

  • 基于jquery的仿百度搜索框效果代码

    先看看整个的效果图:图一: 图二: 图三: 图四: 大概的效果图就这样,接下来直接看源码页面: 复制代码 代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="autoSearch._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DT

  • jQuery利用sort对DOM元素进行排序操作

    前言 排序对于我们是再熟悉不过了,在绝大数应用程序中都会有这样一个场景:当我们从服务器端获取一个列表时,在界面上进行渲染,我们可以会依赖于某一个规则来进行排序,当然此时绝大多数会再次与服务器进行交互来进行重新渲染列表到客户端,这样做未尝不可,但是在有些情况下,我们既不需要利用框架也不需要重新生成列表到客户端,明明可以在客户端进行,达到我们的目的,为何要再一次发送请求到服务器呢?下面我们来看看. 话题 我们首先看看在w3c中js的sort方法. <script type="text/java

  • jQuery+Ajax实现限制查询间隔的方法

    本文实例讲述了jQuery+Ajax实现限制查询间隔的方法.分享给大家供大家参考,具体如下: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Jquery20150305.aspx.cs" Inherits="Jquery20150305" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0

  • 基于jquery实现的类似百度搜索的输入框自动完成功能

    废话不多说,直观的看一下: 实现这个功能需要服务端配合.客户端通过脚本来展示从服务端取得的数据. 先看客户端的HTML: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  <html xmlns="http://www.w3.org/1999/x

  • jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)

    select2是一款jQuery插件,是普通form表单select组件的升级版. 可以定制搜索.远程数据集(Remote data,本篇主要介绍点).无限滚动(数据分页功能,这一点很妙).还有很多高端的参数设置(有需要的下次介绍). 内置了40种国际化语言,不过这里我们只需要用到中文. 同时支持现代和传统浏览器内置,甚至包括惹人不高兴的IE8. 那么,现在让我们开始一段select2的奇幻之旅吧! 一.惊艳的效果,来一睹为快吧 本地实战结果 二.导入css和js到网站上 1.使用CDN,节省自

  • jQuery实现模糊查询的方法分析

    本文实例讲述了jQuery实现模糊查询的方法.分享给大家供大家参考,具体如下: 需求:list列表内容很多,用户需要找出列表内容中的某些条目,只有当与用户输入值匹配的条目才显示出来.(后台无分页,直接异步接口返回数据添加形成的内容列表) 虽然可以通过传参再调用查询出来,但这里主要记录的是前端处理进行模糊查询而无需再次调用接口的实现方法. html部分: <div class="search-form"> <input type="text" pla

  • 基于jQuery实现页面搜索功能

    jQuery实现页面搜索,搜索筛选用户输入的内容! HTML: <div class="table"> <table> <tr id="theader"> <th>姓名</th> <th>性别</th> <th>联系方式</th> </tr> <tr> <td>客服</td> <td>女</td

  • jQuery实现条件搜索查询、实时取值及升降序排序的方法分析

    本文实例讲述了jQuery实现条件搜索查询.实时取值及升降序排序的方法.分享给大家供大家参考,具体如下: 一.鼠标点击获取搜索条件中的被选中的值 创建方法  getAttrValue() 方法,每次的 .click 都要调用  function  getAttrValue(){} 例如,把选中的值给到属性 data-value .只需要每次点击,获取 li.active 的子集  a 的 .attr("data-value")即可 eg: var pubTime = $(getArr[

  • Jquery实现搜索框提示功能示例代码

    博客的前某一篇文章中http://www.jb51.net/article/35175.htm写过一个用Ajax来实现一个文本框输入的提示功能.最近在一个管理项目的项目中,使用后发现,真的反应很慢,数据量很大的情况下使用Ajax去实现真的不合适,于是,我又写了一个使用Jquery来实现方法. 废话不多说,上图上代码:  引用方式: 复制代码 代码如下: <body style="background-color: White;"> <form id="for

随机推荐