日期:2014-05-16  浏览次数:20478 次

ExtJs源码分析与学习—ExtJs事件机制(五)

????? 最近一直忙着做产品,所以好久没有写文章了,下面接着把ExtJs事件机制最后一点内容写完。主要是介绍Ext提供的三个辅助实现事件类——快捷键、导航键和鼠标按键事件。

?

快捷键 Ext.KeyMap

??? 该功能的实现被封装在类Ext.KeyMap中

Ext.KeyMap = function(el, config, eventName){
    this.el  = Ext.get(el);
    this.eventName = eventName || "keydown";
    this.bindings = [];
    if(config){
        this.addBinding(config);
    }
    this.enable();
};

??? 该类实现分为三步,首先找到注册快捷键的元素el,然后把config参数转换为事件的监听函数this.addBinding(config),最后再注册该监听函数this.enable()。先看addBinding方法的实现

?

addBinding : function(config){
        if(Ext.isArray(config)){
            Ext.each(config, function(c){
                this.addBinding(c);
            }, this);
            return;
        }
        var keyCode = config.key,
            fn = config.fn || config.handler,
            scope = config.scope;

	if (config.stopEvent) {
	    this.stopEvent = config.stopEvent;    
	}	

        if(typeof keyCode == "string"){
            var ks = [];
            var keyString = keyCode.toUpperCase();
            for(var j = 0, len = keyString.length; j < len; j++){
                ks.push(keyString.charCodeAt(j));
            }
            keyCode = ks;
        }
        var keyArray = Ext.isArray(keyCode);
        
        //代理按键的监听处理函数,对配置对象中的fn/handle函数进行代理加工处理
        var handler = function(e){
        	//如果指定'shift', 'ctrl', 'alt',而事件对象没有按下指定的'shift', 'ctrl', 'alt',那么就不进行处理
            if(this.checkModifiers(config, e)){
                var k = e.getKey();
                if(keyArray){
                    for(var i = 0, len = keyCode.length; i < len; i++){
                        if(keyCode[i] == k){
                          if(this.stopEvent){
                              e.stopEvent();
                          }
                          fn.call(scope || window, k, e);
                          return;
                        }
                    }
                }else{
                    if(k == keyCode){
                        if(this.stopEvent){
                           e.stopEvent();
                        }
                        fn.call(scope || window, k, e);
                    }
                }
            }
        };
        this.bindings.push(handler);
	},

?

?config配置项支持以下属性

属性??? 类型???????????? 描述
----------? ---------------? ----------------------------------
key???????? String/Array????? 进行处理的单个keycode或keycodes组成的数组
shift?????? Boolean?????????? True:只有shift按下的的同时处理key (默认false)
ctrl??????? Boolean?????????? True:只有ctrl按下的的同时处理key (默认false)
handler???? Function????????? 当KeyMap找到预期的组合键时所执行的函数
alt???????? Boolean?????????? True:只有alt按下的的同时处理key (默认false)
fn????????? Function????????? 当组合键按下后回调函数
scope?????? Object??????????? 回调函数的作用域
stopEvent?? Boolean?????????? 用来停止事件冒泡,阻止元素默认行为。


再看enable方法,把事件注册到元素上

?

enable: function(){
		if(!this.enabled){
		    this.el.on(this.eventName, this.handleKeyDown, this);
		    this.enabled = true;
		}
	},

为指定的el元素注册事件

例子:常用复制、剪切、粘贴的实现

?

var config = [{//剪切
		key : 'x',
		ctrl : true,
		fn : function() {
			//cut
		},
		scope : this
	},{//复制
		key : 'c',
		ctrl : true,
		fn : function() {
			//copy
		},
		scope : this
	},{//粘贴
		key : 'v',
		ctrl : true,
		fn : function() {
			//paste
		},
		scope : this
	},{//编辑
		key : 'abcdefghigklmnopqrstuvwxyz0123456789',
		ctrl : false,
		shift : false,
		alt : false,
		fn : function(k, e) {
			alert(k);
		},
		scope : this
	}];

var map = new Ext.KeyMap("my-element", config);

?

导航键 Ext.KeyNav

?

??? 导航键的实现被封装在类Ext.KeyNav中,首先看其构造函数

?

?

Ext.KeyNav = function(el, config){