这里讨论的是含复选框的树中,当选中某节点时时,向上和向下的选中情况处理。下面为新建TreePanel实例。
情况一:当选中某节点时,展开并选中所有子孙节点;当取消选中某节点时,级联取消选中所有已加载子孙节点。复选框状态改变时都实现与上级节点关联。
var tree = new Ext.tree.TreePanel({
id:'itree',
loader: new Ext.tree.TreeLoader({dataUrl:'findTreeNode.action',baseParams:{}}),
//是否显示线
lines:true,
autoScroll:true,
root: new Ext.tree.AsyncTreeNode({
text: '根节点',
draggable: false,
id: '0'
}),
//不显示根节点
rootVisible:false,
listeners:{
'checkchange':function(node,checked){
if(checked){//当选中当前节点时,展开并选中所有子孙节点
expandInherit(node);
}else{
checkChilds(node);
}
checkParent(this,node);
}
}
})
情况二:
1、当前节点子孙节点已加载,若单击选中本节点,则级联选中其已加载子孙节点,展开本节点时再次确认将本节点选中状态应用于已加载子孙节点;若单击取消选中本节点,则级联取消选中所有已加载子孙节点,此时展开本节点不会影响子孙节点选中情况。
2、当前节点子节点未子节点加载,若单击选中本节点,则在首次展开加载节点数据后将当前节点选中状态应用于子节点;若当前节点未选中,展开不会影响子节点选中状态。
3、复选框状态改变时都实现与上级节点关联。
var tree = new Ext.tree.TreePanel({
id:'itree',
loader: new Ext.tree.TreeLoader({dataUrl:'findTreeNode.action',baseParams:{}}),
//是否显示线
lines:true,
autoScroll:true,
root: new Ext.tree.AsyncTreeNode({
text: '根节点',
draggable: false,
id: '0'
}),
//不显示根节点
rootVisible:false,
listeners:{
'checkchange':function(node,checked){
if(node.loaded) checkChilds(node);//当本节点子节点已加载,则调用checkChilds方法
checkParent(this,node);
},
//展开节点后触发
'expandnode':function(node){
/**
*功能:若展开节点为已选中,则将本节点选中状态应用于所有子孙节点
*描述:实现处理选中节点未加载子孙节点,在首次展开加载子节点时对子节点选中状态进行处理
*/
if(node.attributes.checked){
checkChilds(node);
}
}
}
})
从上面TreePanel实例中可以看出,在选择某个节点复选框或展开某个节点时都有监听处理,其作用是同时向上和向下对节点进行选中状况处理。这里用到了四个递归的辅助方法,其代码如下:
//展开当前节点下所有子孙节点
expandChilds = function(node){
if(node.isExpanded()){
node.eachChild(function(child){
expandChilds(child);
});
}else{
var customfun = null;
node.on("expand",customfun = function(){
node.eachChild(function(child){
expandChilds(child);
});
node.removeListener("expand",customfun,this);
});
node.expand();//展开当前节点子节点
}
};
//展开当前节点下所有子孙节点,并将当前节点选中状态应用于子孙节点
expandInherit = function(node){
if(node.isExpanded()){//若该节点已展开,则将当前节点选中状态应用于该节点下所有子孙节点
checkChilds(node);
node.eachChild(function(child){
expandInherit(child);
});
}else{
var customfun = null;
node.on("expand",customfun = function(){
checkChilds(node);
node.eachChild(function(child){
expandChilds(child);
});
node.removeListener("expand",customfun,this);
});
node.expand();//展开当前节点子节点
}
};
//将当前节点的选中状态应用于向下的所有(已加载)子孙节点
checkChilds = function(node){
var checked = node.attributes.checked;
node.eachChild(function(child){
child.attributes.checked = checked;
child.ui.checkbox.checked = checked;
checkChilds(child);
});
};
//选中当前节点时,对向上的父节点选中状态进行处理
checkParent = function(tree,node){
var parentNode = node.parentNode;
//由于根节点隐藏且没有复选框,所以当当前节点父节点为根节点时不再对父节点(根节点)进行选中状态处理
if(tree.root.attributes.id != parentNode.attributes.id){
//父节点中子节点选中个数计数
var checkedCount = 0;
//父节点中子节点数
var childCount = parentNode.childNodes.length;
parentNode.eachChild(function(child){
if(child.attributes.checked){
checkedCount++;
}
});
if(checkedCount == childCount){//若父节点中子节点已被全选,则选中父节点
parentNode.attributes.checked = true;
parentNode.ui.checkbox.checked = true;
}else{//若父节点中子节点未被全选,则将父节点置为不选中
parentNode.attributes.checked = false;
parentNode.ui.checkbox.checked = false;
}
checkParent(tree,parentNode);
}
};
这样,当树中某节点被选中时,向上和向下的节点处理就完成了。
PS:以上不含半选的CheckBox树适用于初始化时不含选中节点的树,若用于含选中树时,需做适当修改。