Ext Tree 过滤 树 过滤 代码

来源:互联网 发布:mac制作手机铃声 编辑:程序博客网 时间:2024/05/21 14:41
 

 前言:在任何一个Tree树中,提供查找功能无疑会大大方便用户。不用睁大眼睛一级一级去展开,只要输入关键字,回车就能自动定位到节点,岂不快哉?这样的用户体验是相当完美的。但在动态异步加载 的Tree树中,客户端实现这样的功能就有点困难,因为节点是异步动态加载的。默认是没有全部从服务器端取回 的,通常的做法是默认加载第一级,其他级的节点都是惰性按需加载的,用户点了才会展开。而对于这个没有完全加载的树,用户希望搜索节点,怎么实现?笨办法是先展开树的所有节点,然后再在树中搜索 。这样的话在服务器数据量大的情况下会非常慢。所以在数据量大的情况下,是不采取这种实现方式的,这里的实现方法是在服务器端的Servlet中查找,通过AJAX返回第一个匹配节点的路径Path,然后展开这个路径,选中这个搜索到节点 



<html>  

<head>
        <meta http-equiv="Content-Type" content="text/html; charset=gbk">
        <title>05.tree</title>
        <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
        <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="../../ext-all-debug.js"></script>
        <script type="text/javascript" src="localXHR.js"></script>
        <script type="text/javascript">
Ext.onReady(function(){

    var tree = new Ext.tree.TreePanel({
        loader: new Ext.tree.TreeLoader({
            dataUrl: '10-01.txt'
        }),
        root: new Ext.tree.AsyncTreeNode({
            id: '0',
            text: '根'
        }),
        autoHeight: true,
        renderTo: 'tree'
    });

    tree.expandAll();

    var filter = new Ext.tree.TreeFilter(tree, {
        clearBlank: true,
        autoClear: true
    });

    // 保存上次隐藏的空节点
    var hiddenPkgs = [];
    var field = Ext.get('filter');

    // 按键后触发事件
    field.on('keyup', function(e) {
        var text = field.dom.value;

        // 先要显示上次隐藏掉的节点
        Ext.each(hiddenPkgs, function(n){
            n.ui.show();
        });

        // 如果输入的数据不存在,就执行clear()
        if(!text){
            filter.clear();
            return;
        }
        tree.expandAll();

        // 根据输入制作一个正则表达式,'i'代表不区分大小写
        var re = new RegExp(Ext.escapeRe(text), 'i');
        filter.filterBy(function(n){
            // 只过滤叶子节点,这样省去枝干被过滤的时候,底下的叶子都无法显示
            return !n.isLeaf() || re.test(n.text);
        });

        // 如果这个节点不是叶子,而且下面没有子节点,就应该隐藏掉
        hiddenPkgs = [];
        tree.root.cascade(function(n) {
            if(!n.isLeaf() && n.ui.ctNode.offsetHeight < 3){
                n.ui.hide();
                hiddenPkgs.push(n);
            }
        });

    })

});
        </script>
    </head>
    <body>
        <script type="text/javascript" src="../shared/examples.js"></script>
        <input id="filter" type="text" />
        <div id="tree" style="height:300px;"></div>
    </body>
</html>

二、 通过AJAX返回第一个匹配节点的路径Path,然后展开这个路径,选中这个搜索到节点

 

要实现此功能需解决三个问题:

1.  通过Ajax将节点id或text传回服务器。

2.  在服务器端查找到节点path,path由节点id号和“/”构成。注意path的格式,如:'/0/4/7'。此处0表示根节点id,7表示被查找的节点id。

3. 将path传回客服端,Extjs将通过Ext.tree.TreePanel expandPath 方法展开节点。

 

在ExtJS中,AsyncTreeNode是异步节点,TreeLoader实现对树结点的异步加载,即使服务器取到大量的数据,也没有问题,异步加载能保证性能和节点的按需加载。服务端需要生成指定格式的Json字符串。

 

Js代码  收藏代码
  1. var eventTree = new Ext.tree.TreePanel({  
  2.           region: 'center',  
  3.           collapsible: false,  
  4.           title: '导航',  
  5.           xtype: 'treepanel',  
  6.           id:'event-west-tree',  
  7.           width: 180,  
  8.           animate:false//展开,收缩动画  
  9.           autoScroll: true,  
  10.           enableDD:true,  
  11.           split: true,  
  12.           loader: new Ext.tree.TreeLoader({  
  13.             dataUrl:'ruleGroupTree.do?json=1'  
  14.           }),  
  15.           root: new Ext.tree.AsyncTreeNode({  
  16.             text: '分类规则组',  
  17.             draggable:false,  
  18.             //expanded:true, //默认展开第一级  
  19.             id:'0'  
  20.           }),  
  21.           tbar:[{  
  22.             iconCls: 'icon-expand-all',  
  23.             tooltip: '展开',  
  24.             handler: function(){ eventTree.expandAll(); },  
  25.             scope: this  
  26.           }, '-', {  
  27.             iconCls: 'icon-collapse-all',  
  28.             tooltip: '收缩',  
  29.             handler: function(){ eventTree.collapseAll(); },  
  30.             scope: this  
  31.           }, new Ext.form.TextField({  
  32.                 width: 115,  
  33.                 emptyText:'快速检索',  
  34.                 enableKeyEvents: true,//给输入框绑定keyup事件,需要加上enableKeyEvents:true才能让extjs的textfield代理鼠标事件  
  35.                 listeners:{  
  36.                     keyup:function(node, event) {  
  37.                         findByKeyWordFiler(node, event);  
  38.                     },  
  39.                     scope: this  
  40.                 }  
  41.             })]  
  42. });  
  43.   
  44. eventTree.expandAll();  
  45.   
  46. var filterTreeFiled = new Ext.form.TextField({  
  47.     width:115,  
  48.     emptyText:'快速检索',  
  49.     enableKeyEvents: true  
  50. });  
  51. var tbar = eventTree.getTopToolbar();  
  52. <span style="color: #ff0000;">tbar.add(filterTreeFiled);  
  53. tbar.doLayout();</span>  
  54.   
  55.   
  56.   
  57. var selectNode = function(node) {  
  58.     node.ensureVisible();  
  59.     node.select();  
  60.     node.fireEvent('click', node);  
  61. }  
  62.   
  63. function onExpandPathComplete(bSuccess, oLastNode) {  
  64.     if (!bSuccess)  
  65.         return;  
  66.     // focus 节点,并选中节点!  
  67.     selectNode(oLastNode);  
  68. }  
  69.   
  70. var findByKeyWordPath = function(node, event) {  
  71.     clearTimeout(timeOutId);  
  72.     timeOutId = setTimeout(function() {  
  73.                 var text = node.getValue().trim();  
  74.                 // 采用ajax获得需要展开的路径  
  75.                 if (text != "") {  
  76.                     Ext.Ajax.request({  
  77.                                 params : {  
  78.                                     keyWord : text  
  79.                                 },  
  80.                                 url : 'ruleGroupTree.do?json=1',  
  81.                                 method : 'POST',  
  82.                                 async : false,  
  83.                                 success : function(response, opts) {  
  84.                                     var obj = Ext.decode(response.responseText);  
  85.                                     <span style="color: #ff0000;">eventTree.expandPath('/0/101/10101','id',onExpandPathComplete);</span>  
  86.   
  87.   
  88.                                     eventTree.expandPath('/0/101/10101''id'function(bSucess,oLastNode){  
  89.                                       eventTree.getSelectionModel().select(oLastNode);  
  90.                                     });  
  91.                                     if(obj.success){  
  92.                                         var length = obj.length;  
  93.                                         eventTree.root.reload();  
  94.                                         //eventTree.expandAll();  
  95.                                         for (var i = 0; i < length; i++) {  
  96.                                             var path = obj[i].path;  
  97.                                             eventTree.expandPath('/0/101/275','id',onExpandPathComplete);  
  98.                                         }  
  99.   
  100.                                 },  
  101.                                 failure : function(response, opts) {  
  102.                                     Ext.Msg.alert("错误提示""请求失败,请与开发人员联系。").setIcon(Ext.MessageBox.ERROR);  
  103.                                 }  
  104.                             });  
  105.                 } else {  
  106.                 }  
  107.             }, 500);  
  108. }  
  109. filterTreeFiled.on("keyup"function(node, event) {  
  110.     findByKeyWordPath(node, event);  
  111. });  
 

 

以下是具体实现:

1. servlet端要实现的功能就是封装path,将path发送到客服端即可,格式如上。代码省略。

2. 客户端代码:

// 查找树节点
 searchNode : function() {
      var searchForm = Ext.getCmp("searchForm").getForm();
      var param = searchForm.getValues();
      if(searchForm.isValid()){
          Ext.Ajax.request({
               url: 'dept!search.action',
               params:{formData:Ext.encode(param)},
               success:function(response){
                   var o = Ext.decode(response.responseText);
                   if(o.success){
                       var tree = Ext.getCmp('sysOrgs');
                       path=o.message;
                       tree.expandPath(path, 'id', this.onExpandPathComplete );
                   }
               },
               failure:function(response){
               },
               scope:this
         });
      }
 },
 onExpandPathComplete: function(bSuccess, oLastNode) { 
  if(!bSuccess) 
   return;
  //focus 节点,并选中节点!,以下代码不可少 
  oLastNode.ensureVisible();
  oLastNode.select();
  oLastNode.fireEvent('click', oLastNode);
  
 }

关于tree.expandPath方法的使用具体参照API文档。


0 0
原创粉丝点击