开发者博客:www.developsearch.com
<!-- 区域树 -->
<ext:panel var="treePanel" region="west" layout="border" frame="false" width="260"> <ext:items> <ext:panel region="north" layout="column" frame="true" autoHeight="true" > <ext:items> <ext:button text="${app:i18n_menu('button.expand')}" var="btnExpandAll" handler="onExpandAll" /> <ext:button text="${app:i18n_menu('button.collapse')}" var="btnCollapseAll" handler="onCollapseAll" /> <ext:textField var="query_areaName" name="query_areaName" emptyText="${app:i18n('newRebateArea.blank.inputNodeName')}" allowBlank="true" maxLength="200" /> <ext:button cls="x-btn-icon" icon="${images}/search.gif" var="btnSearch" handler="onFindByKeyWordFiler" /> </ext:items> </ext:panel> <ext:treePanel var="areaTreePanel" region="center" autoScroll="true" rootVisible="false"> <ext:treeLoader var="areaLoader" url="findAreas.action" textField="areaName" idField="areaId" clsField="areaId" handler="onNoteClick"/> <ext:asyncTreeNode text="${app:i18n('newRebateArea.text.allArea')}" var="areaRoot" id="0" /> </ext:treePanel> </ext:items> </ext:panel>
// 存放选中的当前节点
var currentNode;
// 单击树根节点事件
function onRootNoteClick(node,event)
{
currentNode = node;
editForm.getForm().reset();
}
// 单击树节点事件
function onNoteClick(node,event) {
Ext.Ajax.request({
params: {areaId: node.attributes.id},
url: "findNewRebateAreaById.action",
success: function(response) {
var resp = Ext.util.JSON.decode(response.responseText);
view_areaId.setValue(resp.areaId);
view_parentId.setValue(resp.parentId);
view_areaCode.setValue(resp.areaCode);
view_areaName.setValue(resp.areaName);
view_areaDesc.setValue(resp.areaDesc);
view_parentName.setValue(node.parentNode.text);
if(resp.isDistrict=='1'){
btnEdit.hide();
btnAdd.hide();
}else{
btnEdit.show();
btnAdd.show();
}
}
});
currentNode = node;
}
// 查询树节点
function onFindByKeyWordFiler() {
var text = query_areaName.getValue();// 获取输入框的值
clearTimeout(timeOutId);// 清除timeOutId
areaTreePanel.expandAll();// 展开树节点
// 为了避免重复的访问后台,给服务器造成的压力,采用timeOutId进行控制,如果采用treeFilter也可以造成重复的keyup
timeOutId = setTimeout(function() {
// 根据输入制作一个正则表达式,'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);
});
// 如果这个节点不是叶子,而且下面没有子节点,就应该隐藏掉
areaTreePanel.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;
};
// 展开所有节点
function onExpandAll(){
areaTreePanel.expandAll();
}
// 收缩所有节点
function onCollapseAll(){
areaTreePanel.collapseAll();
}
// 刷新当前节点
function onRefresh() {
currentNode.reload();
}
// 增加右键点击事件
if(areaTreePanel){
areaTreePanel.on('contextmenu',function(node,e){//声明菜单类型
e.preventDefault();//阻止浏览器默认右键菜单
node.select();//是该节点被选中状态
rightClick.showAt(e.getXY());//获得鼠标的坐标
currentNode = node;
});
}
var rightClick = new Ext.menu.Menu({
id :'rightClickCont',
items : [{
id:'btnAdd',
text : '新增普通区域',
handler:function (){
onAdd();
}
},{
id:'btnAddDistrict',
text : '新增行政区域',
handler:function (){
onAddDistrict();
}
}, {
id:'btnDelete',
text : '删除',
handler:function (){
onDelete();
}
}, {
id:'btnRefresh',
text : '刷新',
handler:function (){
onRefresh();
}
}]
});
//删除操作
function onDelete() {
Ext.MessageBox.confirm('${app:i18n('prompt')}','${app:i18n('confirmDeleteData')}', deleteRecord);
}
function deleteRecord(result){
if (result == 'yes') {
Ext.Ajax.request({
url: 'deleteNewRebateArea.action?areaId='+currentNode.id,
waitMsg: "${app:i18n('saving')}",
success: function(response) {
var resp = Ext.util.JSON.decode(response.responseText);
if(resp.success==true){
currentNode.parentNode.reload();
editForm.getForm().reset();
Ext.MessageBox.alert('${app:i18n('prompt')}','${app:i18n('deleteSuccess')}');
}else{
if(resp.status==0){
Ext.MessageBox.alert('${app:i18n('prompt')}','${app:i18n('prompt.connection.exception')}');
} else {
Ext.MessageBox.alert('${app:i18n('prompt')}',resp.status);
}
}
}
});
}
}
树上加checkbox需要在返回的实体中加上 // 显示checkbox private boolean checked = false; // 判断树节点是否是叶子 private boolean leaf; public boolean isLeaf() { if (this.isDistrict == 1) { leaf = true; } else { leaf = false; } return leaf; } <ext:ui scripts="${scripts}/MapUtil.js"> <ext:formPanel var="queryView" region="north" autoHeight="true" frame="true"> <ext:items> <ext:fieldSet layout="column" title="${app:i18n('queryCondition')}"> <ext:items> <ext:panel width="235" layout="form"> <ext:items> <!-- 原寄地 --> <ext:panel var="query_srcAreaPanel" height="200" width="220" title="${app:i18n('newRebateSet.srcArea')}" region="center" frame="true" > <ext:items> <ext:treePanel var="query_srcAreaTreePanel" region="center" listeners="{checkchange:query_srcAreaTreeCheckChange,load:afterload}" frame="true" width="208" height="162" autoScroll="true" animate="true" rootVisible="false" checkModel="cascade" onlyLeafCheckable="false"> <ext:treeLoader var="query_srcAreaTreeLoader" url="findDistricts.action" textField="distName" idField="distId" clsField="0" baseAttrs="{uiProvider:Ext.tree.TreeCheckNodeUI}"/> <ext:asyncTreeNode text="" var="query_srcAreaTreeRoot" id="0" checked="false" /> </ext:treePanel> </ext:items> </ext:panel> </ext:items> </ext:panel> <ext:panel layout="form" width="235"> <ext:items> <!-- 目的地 --> <ext:panel var="query_distAreaPanel" height="200" width="220" title="${app:i18n('newRebateSet.distArea')}" region="center" frame="true" > <ext:items> <ext:treePanel var="query_distAreaTreePanel" region="center" listeners="{checkchange:query_distAreaTreeCheckChange,load:afterload}" frame="true" width="208" height="162" autoScroll="true" animate="true" rootVisible="false" checkModel="cascade" onlyLeafCheckable="false"> <ext:treeLoader var="query_distAreaTreeLoader" url="findDistricts.action" textField="distName" idField="distId" clsField="areaId" /> <ext:asyncTreeNode text="" var="query_distAreaTreeRoot" id="0" checked="false" /> </ext:treePanel> </ext:items> </ext:panel> </ext:items> </ext:panel> <ext:panel layout="form" width="50" buttonAlign="center" height="200" > <ext:items> <ext:panel layout="form" width="50" buttonAlign="center" height="40" ><ext:items></ext:items></ext:panel> <ext:panel layout="form" width="50" buttonAlign="center" height="60" ><ext:items> <ext:button text="${app:i18n_menu('button.addTo')}" var="query_btnSaveTo" handler="query_onAddArea"/> </ext:items></ext:panel> <ext:panel layout="form" width="50" buttonAlign="center" height="60" ><ext:items> <ext:button text="${app:i18n_menu('button.delete')}" var="query_btnDeleteTo" handler="query_onDeleteArea"/> </ext:items></ext:panel> <ext:panel layout="form" width="50" buttonAlign="center" height="40" ><ext:items></ext:items></ext:panel> </ext:items> </ext:panel> <ext:panel layout="form" width="260"> <ext:items> <!-- 流向结果 --> <ext:gridPanel var="query_dirResultView" region="center" height="200" width="250" frame="true"> <ext:store var="query_dirResultStore" url="findAvailableLeaves.action"> <ext:jsonReader> <ext:fields type="com.sf.module.cdhrebate.domain.NewRebateSetDir"/> </ext:jsonReader> </ext:store> <ext:checkboxSelectionModel/> <ext:columnModel> <ext:propertyColumnModel dataIndex="srcAreaId" id="dirResultGrid_srcAreaId" hidden="true"/> <ext:propertyColumnModel dataIndex="distAreaId" id="dirResultGrid_distAreaId" hidden="true"/> <ext:propertyColumnModel dataIndex="srcAreaName" id="dirResultGrid_srcAreaName" width="98" header="${app:i18n('newRebateSet.srcArea')}"/> <ext:propertyColumnModel dataIndex="distAreaName" id="dirResultGrid_distAreaName" width="98" header="${app:i18n('newRebateSet.distArea')}"/> </ext:columnModel> </ext:gridPanel> </ext:items> </ext:panel> <ext:panel width="250" layout="form" > <ext:store var="regionStore2" url="findAvailableLeaves.action?dimensionType=1" remoteSort="true"> <ext:jsonReader totalProperty="totalSize" root="rbtDimensionItems"> <ext:fields type="com.sf.module.cdhprotocol.domain.IRbtDimensionItem"/> </ext:jsonReader> </ext:store> <ext:items> <ext:hidden name="query.areaIdsJSONStr" var="query_areaIdsJSONStr"/> <ext:textField name="query.name" var="query_name" fieldLabel="${app:i18n('newRebateSet.name')}" width="125"/> <ext:textField name="query.alias" var="query_alias" fieldLabel="${app:i18n('newRebateSet.alias')}" width="125"/> <ext:comboBox name="query.regionType" var="query_regionType" fieldLabel="${app:i18n('newRebateSet.regionType')}<font color=red>*</font>" valueField="itemCode" displayField="itemName" hiddenName="query.regionType" triggerAction="all" editable="false" mode="remote" store="regionStore2" width="125" /> </ext:items> </ext:panel> </ext:items> </ext:fieldSet> </ext:items> </ext:formPanel> var query_srcMap = new MapUtil(); var query_distMap = new MapUtil(); // 单击原寄地树节点checkbox事件 function query_srcAreaTreeCheckChange(node,checked) { if(checked){ query_srcMap.put(node.attributes.id,node.attributes.text); disableTreeNoteForEach(node); }else{ query_srcMap.removeByKey(node.attributes.id); enableTreeNoteForEach(node); } } // 单击目的地树节点checkbox事件 function query_distAreaTreeCheckChange(node,checked) { if(checked){ query_distMap.put(node.attributes.id,node.attributes.text); disableTreeNoteForEach(node); }else{ query_distMap.removeByKey(node.attributes.id); enableTreeNoteForEach(node); } } //将当前节点下的所有子节点变为不可选 function disableTreeNoteForEach(currentNote){ if (currentNote.hasChildNodes()) { currentNote.eachChild(function(child) { child.disable(); if(child.attributes.checked==true){ child.attributes.checked = false; } disableTreeNoteForEach(child); }); } } //将当前节点下的所有子节点变为可选 function enableTreeNoteForEach(currentNote){ if (currentNote.hasChildNodes()) { currentNote.eachChild(function(child) { child.enable(); enableTreeNoteForEach(child); }); } } //点击树节点加载子节点后触发的事件 function afterload(node){ if(node.attributes.checked || node.disabled == true){ disableTreeNoteForEach(node); }else{ enableTreeNoteForEach(node); } } // 添加流向 function query_onAddArea(){ for (i = 0; i < query_srcMap.elements.length; i++) { var srcAreaId = query_srcMap.elements[i].key; var srcAreaName = query_srcMap.elements[i].value; for (j = 0; j < query_distMap.elements.length; j++) { var distAreaId = query_distMap.elements[j].key; var distAreaName = query_distMap.elements[j].value; var record = new Ext.data.Record({ srcAreaId:srcAreaId, srcAreaName:srcAreaName, distAreaId:distAreaId, distAreaName:distAreaName }); //判断结果表中是否存在 if(query_isResultExist(srcAreaId,distAreaId)) { query_dirResultStore.insert(query_dirResultStore.getCount(),record);//store.getCount()表示插入到最后一行 } } } } /** *判断结果表中是否存在 *false表示已存在,不插入 *true表示不存在,允许插入 */ function query_isResultExist(srcAreaId,distAreaId){ var newRecd = query_dirResultStore.getRange(); var findResult = query_dirResultStore.findBy(function(newRecd, id) { var isExist = false; if((newRecd.get('srcAreaId') == srcAreaId) && (newRecd.get('distAreaId') == distAreaId)){ isExist = true; } return isExist; }) == -1; return findResult; } //删除流向 function query_onDeleteArea(){ var recs = query_dirResultView.getSelectionModel().getSelections(); for(var i = recs.length -1; i >= 0; i--){ query_dirResultStore.remove(recs[i]); } } // 将已选择的流向记录封装成json function query_setAreaStoreData(){ var areaIds = []; for(var i=0; i< query_dirResultStore.getCount(); i++){ var obj = {}; obj.srcAreaId = query_dirResultStore.getAt(i).data.srcAreaId; obj.distAreaId = query_dirResultStore.getAt(i).data.distAreaId; areaIds.push(obj); } query_areaIdsJSONStr.setValue(Ext.util.JSON.encode(areaIds)); }
//重新加载树
srcAreaTreePanel.root.reload();
多个root的写法
原理:ExtJs 的树并不支持多个根节点,但它提供了一个隐藏根节点的属性.
其实就是相当于新建一个虚拟的根节点,然后把多个节点挂到该节点上,然后再把虚拟的根节点隐藏.
我们看到所有二级节点都变成了根节点,变相实现了多个根节点的功能.
<script type="text/javascript"> Ext.onReady(function(){ // shorthand var Tree = Ext.tree; var tree = new Tree.TreePanel({ el:'tree-div', useArrows:true, autoScroll:true, animate:true, enableDD:true, rootVisible : false, containerScroll: true, loader: new Tree.TreeLoader({ dataUrl:'../../examples/tree/get-nodes.php' }) }); var root = new Ext.tree.TreeNode({ text : 'extjs.org.cn', draggable : false, id : 'extjs.org.cn' }); tree.setRootNode(root); // set the root node var root1 = new Tree.AsyncTreeNode({ text: 'Ext JS', draggable:false, id:'source' }); root.appendChild(root1); // set the root node var root2 = new Tree.AsyncTreeNode({ text: 'Ext Plugins', draggable:false, id:'plugins' }); root.appendChild(root2); // render the tree tree.render(); root.expand(); }); </script>
禁用/启用树(兼容IE)
function EnableTree(ctl) { if(ctl.value=="enable"){ tree.maskDisabled = true; tree.enable(); }else{ tree.disable(); tree.maskDisabled = false; tree.enable(); } } <input type="radio" name="radio" id="enable" value="enable" onclick="EnableTree(this);" checked> 启用 <input type="radio" name="radio" id="disable" value="disable" onclick="EnableTree(this);"> 禁用