EXTJS treecombox

今天写了一个后台的菜单管理页面,新增或修改树节点时,需要选择已经存在的节点作为父节点,于是想让一个combox作为载体显示一个树的widget,EXTJS并没有提供该控件,于是逛了逛一些论坛和网站,发现vifir的博客系统使用到了此控件,不过并没有提供源代码参考,没办法,自己写一个吧...

以下代码是扩展于combox的 DynamicTreeCombox,代码如下:
Java代码 复制代码
  1. Ext.ns("Ext.ux.form");   
  2. Ext.ux.form.DynamicTreeCombox= Ext.extend(Ext.form.ComboBox, {   
  3.     initComponent:function(){   
  4.         Ext.ux.form.DynamicTreeCombox.superclass.initComponent.call(this);   
  5.         this.addEvents('beforeClickNode','afterClickNode');   
  6.         if(!this.tree){   
  7.             this.tree=new Ext.tree.TreePanel({   
  8.                 containerScroll:true,   
  9.                 rootVisible:false,   
  10.                 root:new Ext.tree.AsyncTreeNode()   
  11.             });   
  12.             this.tree.loader=new Ext.tree.TreeLoader(this.loaderConfig||{dataUrl:"",baseAttrs:{}});   
  13.             this.tree.loader.addListener("beforeload",this.beforeLoad,this);   
  14.             this.tree.loader.addListener("load",this.onLoad,this);   
  15.             this.tree.addListener('collapsenode',this.onNodeCollapse,this);   
  16.             this.tree.addListener('expandnode',this.onNodeExpand,this);   
  17.         }   
  18.         var fieldMp={   
  19.             text:"text",   
  20.             qtip:"qtip",   
  21.             parentFuncId:"id",   
  22.             icon:"icon"  
  23.         };   
  24.         if(!this.fieldMapping){   
  25.             this.fieldMapping=fieldMp;   
  26.         }else{   
  27.             Ext.applyIf(this.fieldMapping,fieldMp);   
  28.         }   
  29.     },   
  30.        
  31.     initList:function(){   
  32.         if(!this.list){   
  33.             var cls = 'x-combo-list';   
  34.             this.list = new Ext.Layer({   
  35.                 shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false  
  36.             });   
  37.             var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);   
  38.             this.list.setWidth(lw);   
  39.             this.list.swallowEvent('mousewheel');   
  40.             this.innerList = this.list.createChild({cls:cls+'-inner'});   
  41.             this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));   
  42.             this.innerList.setHeight("100%");   
  43.         }   
  44.     },   
  45.        
  46.     doQuery:function(){   
  47.         if(this.expandAll){   
  48.             var loader=this.tree.loader;   
  49.             if(loader.baseAttrs){   
  50.                 Ext.apply(loader.baseAttrs,{expanded:this.expandAll});   
  51.             }else{   
  52.                 loader.baseAttrs={expanded:this.expandAll};   
  53.             }              
  54.         }   
  55.         if(!this.tree.rendered){   
  56.             this.tree.render(this.innerList);   
  57.             this.tree.addListener("click",this.clickNode,this);   
  58.         }   
  59.         this.expand();   
  60.     },   
  61.        
  62.     beforeLoad:function(loader,node){   
  63.         if(node!=node.getOwnerTree().root){                                                                                                                    
  64.             loader.baseParams.parentFuncId=node.attributes[this.fieldMapping.parentFuncId];                                                                                                                    
  65.         }   
  66.     },   
  67.        
  68.     onLoad:function(loader,node,res){   
  69.         var nodeArr=node.childNodes;   
  70.         for(var i=0,j=nodeArr.length;i<j;i++){   
  71.             if(nodeArr[i].attributes[this.fieldMapping.icon]){   
  72.                 nodeArr[i].getUI().getIconEl().src=nodeArr[i].attributes[this.fieldMapping.icon];   
  73.             }   
  74.             nodeArr[i].setText(nodeArr[i].attributes[this.fieldMapping.text]);   
  75.             nodeArr[i].ui.textNode.setAttribute("qtip", nodeArr[i].attributes[this.fieldMapping.qtip]);   
  76.         }      
  77.     },   
  78.        
  79.     clickNode:function(node){   
  80.         if(this.fireEvent('beforeClickNode',this,node)){   
  81.             this.setValue(node.attributes[this.displayField]);   
  82.         }   
  83.         this.fireEvent("afterClickNode",this,node);        
  84.         this.collapse();   
  85.     },   
  86.        
  87.     onNodeCollapse:function(node){   
  88.         this.list.setHeight(this.tree.getEl().getHeight()+2);   
  89.     },   
  90.        
  91.     onNodeExpand:function(node){   
  92.         this.list.setHeight(this.tree.getEl().getHeight()+2);   
  93.     },   
  94.        
  95.     onDestroy:function(){   
  96.         if(this.view){   
  97.             this.view.el.removeAllListeners();   
  98.             this.view.el.remove();   
  99.             this.view.purgeListeners();   
  100.         }   
  101.         if(this.tree.loader){   
  102.             this.tree.loader.purgeListeners();   
  103.         }   
  104.         if(this.tree){   
  105.             this.tree.el.removeAllListerers();   
  106.             this.tree.el.remove();   
  107.             this.tree.purgeListeners();   
  108.         }   
  109.         if(this.innerList){   
  110.             this.innerList.destroy();   
  111.         }   
  112.         if(this.list){   
  113.             this.list.destroy();   
  114.         }   
  115.         Ext.form.ComboBox.superclass.onDestroy.call(this);   
  116.     }   
  117. });   
  118.   
  119. Ext.reg("treecombox",Ext.ux.form.DynamicTreeCombox);  
Ext.ns("Ext.ux.form");
Ext.ux.form.DynamicTreeCombox= Ext.extend(Ext.form.ComboBox, {
	initComponent:function(){
		Ext.ux.form.DynamicTreeCombox.superclass.initComponent.call(this);
		this.addEvents('beforeClickNode','afterClickNode');
		if(!this.tree){
			this.tree=new Ext.tree.TreePanel({
				containerScroll:true,
				rootVisible:false,
				root:new Ext.tree.AsyncTreeNode()
			});
			this.tree.loader=new Ext.tree.TreeLoader(this.loaderConfig||{dataUrl:"",baseAttrs:{}});
			this.tree.loader.addListener("beforeload",this.beforeLoad,this);
			this.tree.loader.addListener("load",this.onLoad,this);
			this.tree.addListener('collapsenode',this.onNodeCollapse,this);
			this.tree.addListener('expandnode',this.onNodeExpand,this);
		}
		var fieldMp={
			text:"text",
			qtip:"qtip",
			parentFuncId:"id",
			icon:"icon"
		};
		if(!this.fieldMapping){
			this.fieldMapping=fieldMp;
		}else{
			Ext.applyIf(this.fieldMapping,fieldMp);
		}
	},
	
	initList:function(){
        if(!this.list){
            var cls = 'x-combo-list';
            this.list = new Ext.Layer({
                shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
            });
            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
            this.list.setWidth(lw);
            this.list.swallowEvent('mousewheel');
            this.innerList = this.list.createChild({cls:cls+'-inner'});
            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
            this.innerList.setHeight("100%");
        }
    },
	
	doQuery:function(){
		if(this.expandAll){
			var loader=this.tree.loader;
			if(loader.baseAttrs){
				Ext.apply(loader.baseAttrs,{expanded:this.expandAll});
			}else{
				loader.baseAttrs={expanded:this.expandAll};
			}			
		}
		if(!this.tree.rendered){
			this.tree.render(this.innerList);
			this.tree.addListener("click",this.clickNode,this);
		}
		this.expand();
    },
    
    beforeLoad:function(loader,node){
    	if(node!=node.getOwnerTree().root){																													
			loader.baseParams.parentFuncId=node.attributes[this.fieldMapping.parentFuncId];																													
		}
    },
    
    onLoad:function(loader,node,res){
    	var nodeArr=node.childNodes;
		for(var i=0,j=nodeArr.length;i<j;i++){
			if(nodeArr[i].attributes[this.fieldMapping.icon]){
				nodeArr[i].getUI().getIconEl().src=nodeArr[i].attributes[this.fieldMapping.icon];
			}
			nodeArr[i].setText(nodeArr[i].attributes[this.fieldMapping.text]);
			nodeArr[i].ui.textNode.setAttribute("qtip", nodeArr[i].attributes[this.fieldMapping.qtip]);
		}	
    },
    
    clickNode:function(node){
    	if(this.fireEvent('beforeClickNode',this,node)){
    		this.setValue(node.attributes[this.displayField]);
    	}
    	this.fireEvent("afterClickNode",this,node); 	
    	this.collapse();
    },
    
    onNodeCollapse:function(node){
    	this.list.setHeight(this.tree.getEl().getHeight()+2);
    },
    
    onNodeExpand:function(node){
    	this.list.setHeight(this.tree.getEl().getHeight()+2);
    },
    
    onDestroy:function(){
        if(this.view){
            this.view.el.removeAllListeners();
            this.view.el.remove();
            this.view.purgeListeners();
        }
        if(this.tree.loader){
        	this.tree.loader.purgeListeners();
        }
        if(this.tree){
        	this.tree.el.removeAllListerers();
        	this.tree.el.remove();
            this.tree.purgeListeners();
        }
        if(this.innerList){
            this.innerList.destroy();
        }
        if(this.list){
            this.list.destroy();
        }
        Ext.form.ComboBox.superclass.onDestroy.call(this);
    }
});

Ext.reg("treecombox",Ext.ux.form.DynamicTreeCombox);


下面是调用的代码,已经加上了注释:
Java代码 复制代码
  1. Ext.QuickTips.init();   
  2. Ext.onReady(function(){   
  3.     var mycbo=new Ext.ux.form.DynamicTreeCombox({   
  4.         expandAll:false,//是否在点击combox时将树全部展开   
  5.         displayField:"nameLabelCode",//点击树节点时,将节点的哪个字段设置为combox的值   
  6.         fieldLabel:"Dynamic Tree Combo",   
  7.         readOnly:true,   
  8.         width:180,   
  9.         loaderConfig:{   
  10.             dataUrl:sys.Constants.ROOTPATH+"/sysmgr/SysMenu_list.do",//加载树的URL   
  11.             baseParams:{parentFuncId:""}//传递给后台的参数,其中parentFuncId是必须的,而且初始化为第一次加载时parentFuncId为空,即加载的是后台数据库的根节点   
  12.         },   
  13.         fieldMapping:{//因为我的后台程序返回的没有text qtip字段,故加上fieldMapping进行映射,如果后台返回的json有这几个字段,此属性可省略   
  14.             text:"nameLabelCode",//映射node的text字段   
  15.             qtip:"descriptionLabelCode",//映射node的qtip字段   
  16.             parentFuncId:"funcId"//映射动态请求后台时使用node的funcId字段作为请求参数   
  17.         }   
  18.     });   
  19.        
  20.     var myform=new Ext.form.FormPanel({   
  21.         renderTo:Ext.getBody(),   
  22.         width:350,   
  23.         height:100,   
  24.         frame:true,   
  25.         labelWidth:150,   
  26.         items:[mycbo]   
  27.     });   
  28. });  
Ext.QuickTips.init();
Ext.onReady(function(){
	var mycbo=new Ext.ux.form.DynamicTreeCombox({
		expandAll:false,//是否在点击combox时将树全部展开
		displayField:"nameLabelCode",//点击树节点时,将节点的哪个字段设置为combox的值
		fieldLabel:"Dynamic Tree Combo",
		readOnly:true,
		width:180,
		loaderConfig:{
			dataUrl:sys.Constants.ROOTPATH+"/sysmgr/SysMenu_list.do",//加载树的URL
			baseParams:{parentFuncId:""}//传递给后台的参数,其中parentFuncId是必须的,而且初始化为第一次加载时parentFuncId为空,即加载的是后台数据库的根节点
		},
		fieldMapping:{//因为我的后台程序返回的没有text qtip字段,故加上fieldMapping进行映射,如果后台返回的json有这几个字段,此属性可省略
			text:"nameLabelCode",//映射node的text字段
			qtip:"descriptionLabelCode",//映射node的qtip字段
			parentFuncId:"funcId"//映射动态请求后台时使用node的funcId字段作为请求参数
		}
	});
	
	var myform=new Ext.form.FormPanel({
		renderTo:Ext.getBody(),
		width:350,
		height:100,
		frame:true,
		labelWidth:150,
		items:[mycbo]
	});
});


贴上效果图:
[img]
http://www.iteye.com/upload/attachment/41240/4848558b-3532-38b7-9650-b32fc214bc73.jpg[/img]
  • 4848558b-3532-38b7-9650-b32fc214bc73-thumb
  • 大小: 27.8 KB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值