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

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

?????? 在ExtJs源码分析与学习—ExtJs事件机制(一)中分析了ExtJs对原生浏览器事件的封装。这篇进一步分析ExtJs对事件的封装和扩充。ExtJs会对浏览器本身的事件进行转换,是通过类Ext.EventObject来实现的,该类中通过自执行匿名函数返回Ext.EventObjectImpl对象,该对象用到了Ext.lib.Event(对原生浏览器事件的扩展)。

?

Ext.EventObject = function(){
    var E = Ext.lib.Event,
    …
    Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);
        }
    };

    Ext.EventObjectImpl.prototype = {
       …
};

    return new Ext.EventObjectImpl();
}();

?

下面看Ext.EventObject中代码的实现

?

// safari keypress events for special keys return bad keycodes
safariKeys = {
            3 : 13, // enter
            63234 : 37, // left
            63235 : 39, // right
            63232 : 38, // up
            63233 : 40, // down
            63276 : 33, // page up
            63277 : 34, // page down
            63272 : 46, // delete
            63273 : 36, // home
            63275 : 35  // end
        },

?该对象是为了兼容旧版本safari浏览器对部分键的按键事件返回值的处理,与其他浏览器的统一。

?

// normalize button clicks
 btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};

?由于IE浏览器与其他浏览器的按键值(e.button)不同,所以定义该对象是为了实现所有浏览器的兼容。兼容后,0为左键,1为中键,2为右键。

接下来是类Ext.EventObjectImpl的定义

?

Ext.EventObjectImpl = function(e){
        if(e){
            this.setEvent(e.browserEvent || e);
        }
};

?该类中对浏览器原生事件e进行了包装,调用了private method setEvent,setEvent是定义在Ext.EventObjectImpl.prototype下的

?

        /** @private */
        setEvent : function(e){
            var me = this;
            if(e == me || (e && e.browserEvent)){ // already wrapped
                return e;
            }
            me.browserEvent = e;//把浏览器的原始事件保存到browserEvent中,可以作为是否包装的标识
            if(e){
                // normalize buttons
            	//该段代码处理了不同按键返回的e.button
                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);//e.which原本是键盘事件
                if(clickRe.test(e.type) && me.button == -1){
                    me.button = 0;
                }
                me.type = e.type;//事件名
                //三个功能组合键
                me.shiftKey = e.shiftKey;
                // mac metaKey behaves like ctrlKey
                me.ctrlKey = e.ctrlKey || e.metaKey || false;
                me.altKey = e.altKey;
                
                //键盘事件的keywode,and charcode 
                // in getKey these will be normalized for the mac
                me.keyCode = e.keyCode;
                me.charCode = e.charCode;
                
                // cache the target for the delayed and or buffered events
                //事件目标,E.getTarget(e)处理了不同浏览器的返回结果
                me.target = E.getTarget(e);
                // same for XY
                me.xy = E.getXY(e);//Ext自定义的坐标属性
            }else{//如果没有传入事件,则恢复属性为原始值
                me.button = -1;
                me.shiftKey = false;
                me.ctrlKey = false;
                me.altKey = false;
                me.keyCode = 0;
                me.charCode = 0;
                me.target = null;
                me.xy = [0, 0];
            }
            return me;
        },

?该方法首先判断事件是否包装过,如已经包装了,则直接返回该包装的事件。
?me.browserEvent = e;//把浏览器的原始事件保存到browserEvent中
?me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);//e.which原本是键盘事件
???? if(clickRe.test(e.type) && me.button == -1){
???????? me.button = 0;
?}
该段代码处理了不同按键返回不同的e.button
其他代码的功能,可参见代码注释

?

?

接着看stopEvent方法

?

stopEvent : function(){
            var me = this;
            if(me.browserEvent){
                if(me.browserEvent.type == 'mousedown'){
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
                }
                E.stopEvent(me.browse