Javascript代码 复制代码
  1. Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {   
  2.     …   
  3.     initEvents : function(){   
  4.         Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);   
  5.         this.grid.on('render'function(){   
  6.             var view = this.grid.getView();   
  7.             view.mainBody.on('mousedown'this.onMouseDown, this);   
  8.             Ext.fly(view.innerHd).on('mousedown'this.onHdMouseDown, this);   
  9.   
  10.         }, this);   
  11.     },   
  12.   
  13.     // private   
  14.     onMouseDown : function(e, t){   
  15.         if(e.button === 0 && t.className == 'x-grid3-row-checker'){ // Only fire if left-click   
  16.             e.stopEvent();   
  17.             var row = e.getTarget('.x-grid3-row');   
  18.             if(row){   
  19.                 var index = row.rowIndex;   
  20.                 if(this.isSelected(index)){   
  21.                     this.deselectRow(index);   
  22.                 }else{   
  23.                     this.selectRow(index, true);   
  24.                 }   
  25.             }   
  26.         }   
  27.     },   
  28.   
  29.     // private   
  30.     onHdMouseDown : function(e, t){   
  31.         if(t.className == 'x-grid3-hd-checker'){   
  32.             e.stopEvent();   
  33.             var hd = Ext.fly(t.parentNode);   
  34.             var isChecked = hd.hasClass('x-grid3-hd-checker-on');   
  35.             if(isChecked){   
  36.                 hd.removeClass('x-grid3-hd-checker-on');   
  37.                 this.clearSelections();   
  38.             }else{   
  39.                 hd.addClass('x-grid3-hd-checker-on');   
  40.                 this.selectAll();   
  41.             }   
  42.         }   
  43. },   
  44. …   
  45. });  
Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
	…
    initEvents : function(){
        Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
        this.grid.on('render', function(){
            var view = this.grid.getView();
            view.mainBody.on('mousedown', this.onMouseDown, this);
            Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);

        }, this);
    },

    // private
    onMouseDown : function(e, t){
        if(e.button === 0 && t.className == 'x-grid3-row-checker'){ // Only fire if left-click
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            if(row){
                var index = row.rowIndex;
                if(this.isSelected(index)){
                    this.deselectRow(index);
                }else{
                    this.selectRow(index, true);
                }
            }
        }
    },

    // private
    onHdMouseDown : function(e, t){
        if(t.className == 'x-grid3-hd-checker'){
            e.stopEvent();
            var hd = Ext.fly(t.parentNode);
            var isChecked = hd.hasClass('x-grid3-hd-checker-on');
            if(isChecked){
                hd.removeClass('x-grid3-hd-checker-on');
                this.clearSelections();
            }else{
                hd.addClass('x-grid3-hd-checker-on');
                this.selectAll();
            }
        }
},
…
});


但是我们又不希望修改EXT的源代码,后来就想到可以扩展CheckboxSelectionModel这个类。实现如下:
ExtCheckboxSelectionModel.js
Javascript代码 复制代码
  1. Ext.grid.ExtCheckboxSelectionModel = Ext.extend(Ext.grid.CheckboxSelectionModel, {   
  2.     hd : null,   
  3.     onHdMouseDown : function(e, t){   
  4.         Ext.grid.ExtCheckboxSelectionModel.superclass.onHdMouseDown.call(this, e, t);   
  5.            
  6.         if (this.hd == null && t.className == 'x-grid3-hd-checker') {   
  7.             this.hd = t.parentNode;   
  8.                
  9.             this.on('rowdeselect'this.offHdChecker, this);   
  10.         }   
  11.     },   
  12.     offHdChecker : function() {   
  13.         if (this.hd == null)   
  14.             return;   
  15.                
  16.         var hd = Ext.fly(this.hd);   
  17.         var isChecked = hd.hasClass('x-grid3-hd-checker-on');   
  18.         if(isChecked)   
  19.             hd.removeClass('x-grid3-hd-checker-on');   
  20.     }   
  21.  });  
Ext.grid.ExtCheckboxSelectionModel = Ext.extend(Ext.grid.CheckboxSelectionModel, {
	hd : null,
	onHdMouseDown : function(e, t){
		Ext.grid.ExtCheckboxSelectionModel.superclass.onHdMouseDown.call(this, e, t);
		
		if (this.hd == null && t.className == 'x-grid3-hd-checker') {
			this.hd = t.parentNode;
			
			this.on('rowdeselect', this.offHdChecker, this);
		}
	},
	offHdChecker : function() {
		if (this.hd == null)
			return;
			
		var hd = Ext.fly(this.hd);
		var isChecked = hd.hasClass('x-grid3-hd-checker-on');
		if(isChecked)
			hd.removeClass('x-grid3-hd-checker-on');
	}
 });

在这个扩展类中,我们继承了基类的onHdMouseDown方法(虽然Ext已经把这个类声明成私有变量,并且也不希望用户重写,但是在有些情况下我们也只能通过Ext不推荐的方式来实现了),这个方法是在用户点击标题栏的全选复选框时执行,我们先维护一个hd属性,这个属性存放标题栏的全选复选框的父节点,扩展方法onHdMouseDown先执行父类的onHdMouseDown方法,然后检查是否已经设置了hd属性的值,如果没有设置,则设置hd属性的值为标题栏的全选复选框的父节点,并且添加rowdeselect事件(行取消选中)的处理函数。
在rowdeselect事件处理函数中,首先检查是否设置类hd属性,如果设置了hd属性,表示标题栏的全选复选框曾经点击过,然后判断全选复选框是否为选中状态,如果是,则设置全选复选框是否为非选中状态。
在使用时,我们只要把原来new Ext.grid.CheckboxSelectionModel()的地方改成new Ext.grid.ExtCheckboxSelectionModel()即可实现客户要求的功能。

在使用过程中,发现已经有很多地方用了new Ext.grid.CheckboxSelectionModel(),我们不希望每个地方都要修改一次,工作量太大,还可能有遗漏,我们希望有个地方修改一下,就可以实现所有的地方都调整,但是又不希望修改源代码,通过查资料,想到了一种办法:
ext-extends.js
Javascript代码 复制代码
  1. if (Ext.grid.CheckboxSelectionModel) {   
  2.     var interceptOnHdMouseDown = Ext.grid.CheckboxSelectionModel.prototype.onHdMouseDown.createInterceptor(function(e, t){   
  3.         if (this.hd == null && t.className == 'x-grid3-hd-checker') {   
  4.             this.hd = t.parentNode;   
  5.                
  6.             this.on('rowdeselect'this.offHdChecker, this);   
  7.         }   
  8.     });   
  9.        
  10.     Ext.override(Ext.grid.CheckboxSelectionModel, {   
  11.         hd : null,   
  12.         onHdMouseDown : interceptOnHdMouseDown,   
  13.         offHdChecker : function() {   
  14.             if (this.hd == null)   
  15.                 return;   
  16.                    
  17.             var hd = Ext.fly(this.hd);   
  18.             var isChecked = hd.hasClass('x-grid3-hd-checker-on');   
  19.             if(isChecked)   
  20.                 hd.removeClass('x-grid3-hd-checker-on');   
  21.         }   
  22.     });   
  23. }  
if (Ext.grid.CheckboxSelectionModel) {
	var interceptOnHdMouseDown = Ext.grid.CheckboxSelectionModel.prototype.onHdMouseDown.createInterceptor(function(e, t){
		if (this.hd == null && t.className == 'x-grid3-hd-checker') {
			this.hd = t.parentNode;
			
			this.on('rowdeselect', this.offHdChecker, this);
		}
	});
	
	Ext.override(Ext.grid.CheckboxSelectionModel, {
		hd : null,
		onHdMouseDown : interceptOnHdMouseDown,
		offHdChecker : function() {
			if (this.hd == null)
				return;
				
			var hd = Ext.fly(this.hd);
			var isChecked = hd.hasClass('x-grid3-hd-checker-on');
			if(isChecked)
				hd.removeClass('x-grid3-hd-checker-on');
		}
	});
}

在上面的实现方法中,先判断当前是否有Ext.grid.CheckboxSelectionModel的定义(有可能我们通过定制js,没有使用这个功能),然后创建针对CheckboxSelectionModel的onHdMouseDown方法的拦截器函数,这个函数会在执行CheckboxSelectionModel的onHdMouseDown方法以前执行我们自己的拦截方法,拦截方法的检查是否已经设置了hd属性的值,如果没有设置,则设置hd属性的值为标题栏的全选复选框的父节点,并且添加rowdeselect事件(行取消选中)的处理函数。
然后我们通过调用Ext.override函数给Ext.grid.CheckboxSelectionModel类添加hd属性和offHdChecker方法,并用拦截器函数替换原有的onHdMouseDown方法,使用时,在加载了ext-all.js后,再加载ext-extends.js,由此,实现了在不修改源代码的情况下,修改Ext.grid.CheckboxSelectionModel类功能的机制
在这里的关键是:通过生成一个原有类方法的拦截器方法,并重载这个方法,可以实现在不修改源代码、以及不生成扩展类的情况下,扩展原有类的方法和功能。