zoukankan      html  css  js  c++  java
  • 读Ext之八(原生事件对象的修复及扩充)

    Ext库也对浏览器原生的事件对象做了包装,以保证兼容所有浏览器。
    这里
     列举了浏览器原生事件对象各浏览器中兼容性,这里 列出了各种情况下事件对象的获取。


    在Ext事件管理类 Ext.EventManager 中会悄悄的将浏览器原始事件对象进行转换

    e = Ext.EventObject.setEvent(e);
    

    Ext.EventObject 即为包装后的事件对象(暂称为Ext事件对象)。先从全局上看看该对象的实现,其中...省略了部分代码。

    Ext.EventObject = function(){
        var E = Ext.lib.Event,
    		...;
    
        Ext.EventObjectImpl = function(e){
            if(e){
                this.setEvent(e.browserEvent || e);
            }
        };
        Ext.EventObjectImpl.prototype = {
               /** @private */
            setEvent : function(e){
                var me = this;
    			...
            },
    		...
         };
    
        return new Ext.EventObjectImpl();
    }();
    

    可看到匿名函数执行后返回了Ext.EventObjectImpl的实例对象,该对象才是真正的Ext.EventObject。
    这一点和jQuery类似,jQuery中是new了一个Event类。

    第一句

    var E = Ext.lib.Event,
    

    变量E暂存了Ext.lib.Event对象,该对象在 读Ext之四 中已经介绍了。后面的很多方法都要用 E 来实现。

    第二个变量 safariKeys 为一个对象,

    // 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中keypress事件返回错误的键码。但我用Safari 5.0.3测试input,document.body 。
    回车键(enter)返回的是13,正确的。方向键(left等)和翻页键(page up等)则不会触发。

    测试代码如下

    var inp = document.getElementById('txt');	
    inp.onkeypress = function(e){
    	e = window.event || e;
    	alert(e.keyCode);
    }
    document.body.onkeypress = function(e){
    	e = window.event || e;
    	alert(e.keyCode);
    }
    

    之前已经提到过要获取按键值应该使用keydown或keyup事件。这里应该是为了兼容旧版本的Safari。

    第三个变量是btnMap

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

    用来统一鼠标按键值。这里 有详细分析,不重复了。经测试,webkit内核的Safari5和Chrome7在mousedown/mouseup事件中左,中,右键返回的是符合标准的0,1,2。因此这里对webkit的判断是可去掉的。

     

    接下来是 Ext.EventObjectImpl 类的定义

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

    如果传了浏览器原生事件对象,则调用this.setEvent,this.setEvent是挂在Ext.EventObjectImpl的原型上的。原型上还有很多其它方法,逐个看

    setEvent : function(e){
        var me = this;
        if(e == me || (e && e.browserEvent)){ // already wrapped
            return e;
        }
        me.browserEvent = e;
        if(e){
            // normalize buttons
            me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
            if(e.type == 'click' && 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;
            // 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
            me.target = E.getTarget(e);
            // same for XY
            me.xy = E.getXY(e);
        }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;
    },
    

     

    var me = this;

    将this暂存到me上。接着判断所传的是否就是本身,如果是则不再包装直接返回。仅当是浏览器原生事件对象才进行包装。

     

    me.browserEvent = e; 

    把浏览器原始事件对象挂在this上,即该类的字段browserEvent就是浏览器原始对象。因为有时会用到浏览器原始对象。


    me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);

    先从btnMap中取,上面已经提到了。e.which原本是键盘事件,jQuery中将鼠标按键也存在e.which中,Ext这里是为了兼容jQuery。

    if(e.type == 'click' && me.button == -1){
        me.button = 0;
    }
    

    建议获取判断鼠标按下哪个键应该使用mousedown/mouseup事件,这里是为了兼容click事件。但有点问题,IE6/7/8中左键单击(click)事件为0,但中键和右键单击(click)则无法触发该事件。这里的实现欠妥。

     

    me.type = e.type; 
    me.shiftKey = e.shiftKey;
    

    事件类型(如click)和shiftKey复制到this上。

    接着是ctrlKey,altKey,keyCode,charCode。

    接着是target,使用E.getTarget(e)获取。E.getTarget在第四篇提到了。

    接着是xy,xy不是事件对象原有的属性。而是Ext自定义的。

     

    setEvent说了,看stopEvent

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

    用来停止事件冒泡,阻止元素默认行为。
    有两点,其一对mousedown事件做了特殊处理Ext.EventManager.stoppedMouseDownEvent 实际是Ext.util.Event类的一个实例对象。如

    pub.stoppedMouseDownEvent = new Ext.util.Event();
    

    后续有一篇会读到该类。

    其二,调用了E.stopEvent(me.browserEvent),这里的E即为Ext.lib.Event对象,第四篇提到了。接着是preventDefault,stopPropagation等

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

    可看到都是调用E(Ext.lib.Event)来实现的,不再重复。


    getTarget 采用事件代理时会用到,实现上用到了Ext.fly等,后续提到。getWheelDelta 用来获取滚轮的速度

    getWheelDelta : function(){
        var e = this.browserEvent;
        var delta = 0;
        if(e.wheelDelta){ /* IE/Opera. */
            delta = e.wheelDelta/120;
        }else if(e.detail){ /* Mozilla case. */
            delta = -e.detail/3;
        }
        return delta;
    },
    

    IE/Safari/Chrome/Opera中使用事件对象的wheelDelta属性,Firefox则使用detail属性。
    属性的方向值也不一样,IE向前滚 > 0为120,相反在-120,Firefox向后滚 > 0为3,相反则-3。

    好了,整个Ext事件对象读完了。可以看到Ext为了保证兼容,统一对原生事件对象做了修复,扩充等。

     

    EventManager.js

     

  • 相关阅读:
    Integer类的parseInt和valueOf的区别
    华为实习小结
    程序员浪费生命的几种方式
    移动前端中viewport(视口) 转
    Console API 与命令行
    Ajax
    浏览器缓存机制
    mysql之各种命令总结
    jquery file upload 文件上传插件
    文件上传插件uploadify详解
  • 原文地址:https://www.cnblogs.com/snandy/p/2474183.html
Copyright © 2011-2022 走看看