前言:在任何一个Tree树中,提供查找功能无疑会大大方便用户。不用睁大眼睛一级一级去展开,只要输入关键字,回车就能自动定位到节点,岂不快哉?这样的用户体验是相当完美的。但在动态异步加载
的Tree树中,客户端实现这样的功能就有点困难,因为节点是异步动态加载的。默认是没有全部从服务器端取回
的,通常的做法是默认加载第一级,其他级的节点都是惰性按需加载的,用户点了才会展开。而对于这个没有完全加载的树,用户希望搜索节点,怎么实现?笨办法是先展开树的所有节点,然后再在树中搜索
。这样的话在服务器数据量大的情况下会非常慢。所以在数据量大的情况下,是不采取这种实现方式的,这里的实现方法是在服务器端的Servlet中查找,通过AJAX返回第一个匹配节点的路径Path,然后展开这个路径,选中这个搜索到节点
。
效果图:
一、
先展开树的所有节点,然后再在树中搜索
Ext.onReady(function() {
Ext.QuickTips.init();
Ext.BLANK_IMAGE_URL = "../../resources/images/default/s.gif";
var mytree = new Ext.tree.TreePanel({
region: 'center',
title : "简单Extjs动态树",
//el : "container",
animate : true, //展开,收缩动画,false时,则没有动画效果
collapsible : true,
enableDD : true,//不仅可以拖动,还可以通过Drag改变节点的层次结构(drap和drop)
enableDrag : true,//仅仅drop
rootVisible : true,//false不显示根节点,默认为true
autoScroll : true,
autoHeight : true,
width : 150,
//tbar:new Ext.Toolbar(),
tbar:[' ',
new Ext.form.TextField({
width:150,
emptyText:'快速检索',
enableKeyEvents: true,
listeners:{
keyup:function(node, event) {
findByKeyWordFiler(node, event);
},
scope: this
}
})
],
root:new Ext.tree.AsyncTreeNode({
id:"root",
text:"树的根",
leaf:false,
//expanded:true,
children: [{
id: 'level',
text: '用户类型',
children: [{
id: 'allLevel',
text: '全部',
leaf: true
}, {
id: 'noSupport',
text: '无支持',
leaf: true
}, {
id: 'month',
text: '包月',
leaf: true
}, {
id: 'year',
text: '包年',
leaf: true
}, {
id: 'always',
text: '终身',
leaf: true
}]
}, {
id: 'outOfDate',
text: '是否过期',
children: [{
id: 'allOutOfDate',
text: '全部',
leaf: true
}, {
id: 'notOutOfDate',
text: '未过期',
leaf: true
}, {
id: 'alreadyOutOfDate',
text: '已过期',
leaf: true
}]
}, {
id: 'report',
text: '统计图表',
children: [{
id: 'levelReport',
text: '按用户类型',
leaf: true
}, {
id: 'outOfDateReport',
text: '按是否过期',
leaf: true
}]
}]
}),
lines : true//节点间的虚线条
});
//mytree.expandAll();
//mytree.render();
/*
var filterTreeFiled = new Ext.form.TextField({
width:150,
emptyText:'快速检索',
enableKeyEvents: true
});
var tbar = mytree.getTopToolbar();
tbar.add(filterTreeFiled);
tbar.doLayout();*/
var timeOutId = null;
var treeFilter = new Ext.tree.TreeFilter(mytree, {
clearBlank : true,
autoClear : true
});
// 保存上次隐藏的空节点
var hiddenPkgs = [];
var findByKeyWordFiler = function(node, event) {
clearTimeout(timeOutId);// 清除timeOutId
mytree.expandAll();// 展开树节点
// 为了避免重复的访问后台,给服务器造成的压力,采用timeOutId进行控制,如果采用treeFilter也可以造成重复的keyup
timeOutId = setTimeout(function() {
// 获取输入框的值
var text = node.getValue();
// 根据输入制作一个正则表达式,'i'代表不区分大小写
var re = new RegExp(Ext.escapeRe(text), 'i');
// 先要显示上次隐藏掉的节点
Ext.each(hiddenPkgs, function(n) {
n.ui.show();
});
hiddenPkgs = [];
if (text != "") {
treeFilter.filterBy(function(n) {
// 只过滤叶子节点,这样省去枝干被过滤的时候,底下的叶子都无法显示
return !n.isLeaf() || re.test(n.text);
});
// 如果这个节点不是叶子,而且下面没有子节点,就应该隐藏掉
mytree.root.cascade(function(n) {
if(n.id!='0'){
if(!n.isLeaf() &&judge(n,re)==false&& !re.test(n.text)){
hiddenPkgs.push(n);
n.ui.hide();
}
}
});
} else {
treeFilter.clear();
return;
}
}, 500);
}
// 过滤不匹配的非叶子节点或者是叶子节点
var judge =function(n,re){
var str=false;
n.cascade(function(n1){
if(n1.isLeaf()){
if(re.test(n1.text)){ str=true;return; }
} else {
if(re.test(n1.text)){ str=true;return; }
}
});
return str;
};
// 给输入框绑定keyup事件,需要加上enableKeyEvents:true才能让extjs的textfield代理鼠标事件
//filterTreeFiled.on("keyup", function(node, event) {
//findByKeyWordFiler(node, event);
//});
var eventPanel = new Ext.Panel({
width : 680,
height : 350,
renderTo : 'container',
layout: 'border',
items:[mytree]
});
});
注意ext-base.js和ext-all.js的引用顺序
,具体的可以查看INCLUDE_ORDER.txt
<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.js"></script>
<script type="text/javascript" src="treenode.js"></script>
<body>
<div id="container"></div>
</body>
二、
通过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字符串。
var eventTree = new Ext.tree.TreePanel({
region: 'center',
collapsible: false,
title: '导航',
xtype: 'treepanel',
id:'event-west-tree',
width: 180,
animate:false, //展开,收缩动画
autoScroll: true,
enableDD:true,
split: true,
loader: new Ext.tree.TreeLoader({
dataUrl:'ruleGroupTree.do?json=1'
}),
root: new Ext.tree.AsyncTreeNode({
text: '分类规则组',
draggable:false,
//expanded:true, //默认展开第一级
id:'0'
}),
tbar:[{
iconCls: 'icon-expand-all',
tooltip: '展开',
handler: function(){ eventTree.expandAll(); },
scope: this
}, '-', {
iconCls: 'icon-collapse-all',
tooltip: '收缩',
handler: function(){ eventTree.collapseAll(); },
scope: this
}, new Ext.form.TextField({
width: 115,
emptyText:'快速检索',
enableKeyEvents: true,//给输入框绑定keyup事件,需要加上enableKeyEvents:true才能让extjs的textfield代理鼠标事件
listeners:{
keyup:function(node, event) {
findByKeyWordFiler(node, event);
},
scope: this
}
})]
});
eventTree.expandAll();
var filterTreeFiled = new Ext.form.TextField({
width:115,
emptyText:'快速检索',
enableKeyEvents: true
});
var tbar = eventTree.getTopToolbar();
tbar.add(filterTreeFiled);
tbar.doLayout();
var selectNode = function(node) {
node.ensureVisible();
node.select();
node.fireEvent('click', node);
}
function onExpandPathComplete(bSuccess, oLastNode) {
if (!bSuccess)
return;
// focus 节点,并选中节点!
selectNode(oLastNode);
}
var findByKeyWordPath = function(node, event) {
clearTimeout(timeOutId);
timeOutId = setTimeout(function() {
var text = node.getValue().trim();
// 采用ajax获得需要展开的路径
if (text != "") {
Ext.Ajax.request({
params : {
keyWord : text
},
url : 'ruleGroupTree.do?json=1',
method : 'POST',
async : false,
success : function(response, opts) {
var obj = Ext.decode(response.responseText);
eventTree.expandPath('/0/101/10101','id',onExpandPathComplete);
eventTree.expandPath('/0/101/10101', 'id', function(bSucess,oLastNode){
eventTree.getSelectionModel().select(oLastNode);
});
if(obj.success){
var length = obj.length;
eventTree.root.reload();
//eventTree.expandAll();
for (var i = 0; i < length; i++) {
var path = obj[i].path;
eventTree.expandPath('/0/101/275','id',onExpandPathComplete);
}
},
failure : function(response, opts) {
Ext.Msg.alert("错误提示", "请求失败,请与开发人员联系。").setIcon(Ext.MessageBox.ERROR);
}
});
} else {
}
}, 500);
}
filterTreeFiled.on("keyup", function(node, event) {
findByKeyWordPath(node, event);
});
以下是具体实现:
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文档。
分享到:
相关推荐
extjs tree 异步加载树型完整的一个web工程,自已已经试过,可用。
区别在于,远程脚本调用方式加载树节点信息使用的是WebInvokeTreeLoader,需要通过fn属性来指定用于加载数据的远程方法,并在...而传统的树节点加载器是Ext.tree.TreeLoader,需要指定一个url来获得json数据。
ExtJs4 Checkbox tree
在家研究了一下extjs异步树,-每个节点都异步加载-前后台代码都有-附整个工程-运行通过-前台代码请看doctree.js,后台代码请看TreeService.java,运行环境:Myeclipse6.5+tomcat7.0.27
功能: 1.实现ExtJS tree 节点右键菜单 实现增删查. 2.实现针对实体数据的动态搜索. 3.代码命名规范,简单易懂. 4.支持IE 9,FF 19.0.2. 5.将文件解压至ext包example任意组件文件夹即可浏览效果.
Extjs 4.1 下拉框 Tree 的实现(mvc)
Extjs的tree Extjs的tree Extjs的tree Extjs的tree Extjs的tree
NULL 博文链接:https://lpcjrflsa.iteye.com/blog/1704537
extjs异步树,多选树,json数据机构,集成spring,struts例子,extjs异步树,多选树,json数据机构,集成spring,struts例子,extjs异步树,多选树,json数据机构,集成spring,struts例子,extjs异步树,多选树,json...
网上有些这样的例子,但是下了几个都没有跑起来,哎,希望那些发文章的人要发就发全的,别发个半生不熟的。... 现在自己整理了一个Struts2+ExtJS2实现文异步文件上传,没法上传图片无法看到效果,直接上源码吧。
extJs 2,异步树,ext2源程序,tree; 一个完整的extJs 2Tree 例子.
Extjs动态树的实现以及节点拖拽
extjs的tree的使用.doc
划词搜索Extjs实现方式 划词搜索Extjs实现方式 划词搜索Extjs实现方式 划词搜索Extjs实现方式
ExtJs 2.2.1 tree实例,内附mysql数据文件 1. 数据节点一次性加载 2. 节点分为两个类(项目和设备) 3. 右键菜单 4. 节点增、删、改操作 ....... 后台是java struts1。 本例旨在说明extjs的tree操作,后台操作很简陋...
Extjs的Tree和Pane配合使用使用json做tree数据交互,感谢csdn,所以我也得做些贡献,获得一些积分
AJAX: 以JSON数据格式,使用ExtJS构造动态异步加载的树。
说明:本例主要实现在树节点数据过多的情况下对数据进行异步请求,并且在请求数据返回前台的同时实现级联选择。使用ExtJs版本为4.1.1a,在struts2下测试通过。例子仅供提供思路,简单易懂,不负责代码优化,哈哈!
ExtJs Tree
extjs实现动态树