马上篇开始读ext-base-event.js。该公文定义了Ext.lib.Event对象,Ext.lib这个命名空间在Ext
core的Ext.js中命名的。

Ext.ns("Ext.util", "Ext.lib", "Ext.data");

 

Ext.lib上的性能如下:

Ext.lib.Ajax
Ext.lib.Anim
Ext.lib.AnimMgr
Ext.lib.Bezier
Ext.lib.Dom
Ext.lib.Easing
Ext.lib.Event
Ext.lib.AnimBase
Ext.lib.ColorAnim
Ext.lib.Motion
Ext.lib.Scroll

Ext.lib.Event 是Ext中事件处理的轻封装,概览下

Ext.lib.Event = function() {
    var loadComplete = false,
    ...
    ...
    return pub;
}();

得发现依然是一个匿名函数执行,执行后返回对象pub,pub赋值为Ext.lib.Event。再拘留里面细节

var loadComplete = false,
    unloadListeners = {},
    retryCount = 0,
    onAvailStack = [],
    _interval,
    locked = false,
    win = window,
    doc = document,

    // constants
    POLL_RETRYS = 200,
    POLL_INTERVAL = 20,
    EL = 0,
    TYPE = 0,
    FN = 1,
    WFN = 2,
    OBJ = 2,
    ADJ_SCOPE = 3,
    SCROLLLEFT = 'scrollLeft',
    SCROLLTOP = 'scrollTop',
    UNLOAD = 'unload',
    MOUSEOVER = 'mouseover',
    MOUSEOUT = 'mouseout',

上述定义了平积变量。window,document对象分别赋值给了win,doc。这样做的利是减少了扳平重叠闭包。使用部分变量win,doc比直接利用window,document要赶早。因为她有让行函数的倒对象吃,解析标识符只需要寻找作用域链中的么对象。
比方读取变量值的耗时凡随着查找作用域链的逐层深入而频频加码。这点只是参看:《JS权威指南》第五本4.7节:深入理解变量作用域。

doc后是同等堆放常量定义,Ext的编码习惯也是常量全部行使大写,有多单单词时用生划线连接。接下来是千篇一律积聚私有方法/函数定义,即这些函数只能以上头提到的最外层的匿名函数内利用。

// private
doAdd = function() {
    var ret;
    if (win.addEventListener) {
        ret = function(el, eventName, fn, capture) {
            if (eventName == 'mouseenter') {
                fn = fn.createInterceptor(checkRelatedTarget);
                el.addEventListener(MOUSEOVER, fn, (capture));
            } else if (eventName == 'mouseleave') {
                fn = fn.createInterceptor(checkRelatedTarget);
                el.addEventListener(MOUSEOUT, fn, (capture));
            } else {
                el.addEventListener(eventName, fn, (capture));
            }
            return fn;
        };
    } else if (win.attachEvent) {
        ret = function(el, eventName, fn, capture) {
            el.attachEvent("on" + eventName, fn);
            return fn;
        };
    } else {
        ret = function(){};
    }
    return ret;
}(),

doAdd,亦是一个匿名函数执行后回新函数,用来吃html元素添加事件与波响应函数(handler)。这个函数和大多数底波续加函数差不多,用特色判断 。标准浏览器采用addEventListener添加,IE系列以attachEvent,都无支持则回一个空函数。这里产生几乎接触,
1,有的代码中使用特性判断时,先勾勒win.attachEvent,后是win.addEventListener。这是尴尬的,应该先行利用标准的addEventListener,而IE9同时支持即点儿栽艺术。
2,这里新增了mouseenter /mouseleave 事件,它们只是IE支持。mouseenter不同于mouseover,它是当率先糟鼠标上节点区域时点,以后在节点区域外(子节点间)移动时无沾。Goodbye
mouseover, hello
mouseenter 详细讲述了采取mouseenter的利益。此处有简言之的实现。

这边吧非IE浏览器间接实现了立片个事件,需要外两个函数的提携

function checkRelatedTarget(e) {
    return !elContains(e.currentTarget, pub.getRelatedTarget(e));
}
function elContains(parent, child) {
   if(parent && parent.firstChild){
     while(child) {
        if(child === parent) {
            return true;
        }
        child = child.parentNode;
        if(child && (child.nodeType != 1)) {
            child = null;
        }
      }
    }
    return false;
}

elContains
两只参数parent,child判断有元素child是否是parent的子元素,是则回true,否则false。
checkRelatedTarget 会作为一个拦截器,这里e.currentTarget
IE6/7/8免支持。pub.getRelatedTarget(e)是下封装好的章程,IE中动用fromElement,toElement。

fn = fn.createInterceptor(checkRelatedTarget);

落实的基本思路:使用mouseover事件,即当给某个元素(parent)添加mouseenter事件时,鼠标移至parent时接触事件handler,但由其子元素上移动时连无接触。

 

附带提下,Ext这里的elContains方法的兑现明显不妥,实际上IE中得以下contains ,现代浏览器虽然可采用compareDocumentPosition ,谢谢天堂 提醒。John 写了个

function contains(a, b){
  return a.contains ?
    a != b && a.contains(b) :
    !!(a.compareDocumentPosition(b) & 16);
}

jQuery的精选器Sizzle.contains也是这么实现。

 

function getScroll() {
    var dd = doc.documentElement,
        db = doc.body;
    if(dd && (dd[SCROLLTOP] || dd[SCROLLLEFT])){
        return [dd[SCROLLLEFT], dd[SCROLLTOP]];
    }else if(db){
        return [db[SCROLLLEFT], db[SCROLLTOP]];
    }else{
        return [0, 0];
    }
}

村办的getScroll方法返回文档的scrollTop和scrollLeft值,由于浏览器差异,该兑现上先行打document.documentElement取,为0后再次起document.body上取。都未曾回到[0,0]。

 

function getPageCoord (ev, xy) {
    ev = ev.browserEvent || ev;
    var coord  = ev['page' + xy];
    if (!coord && coord !== 0) {
        coord = ev['client' + xy] || 0;
        if (Ext.isIE) {
            coord += getScroll()[xy == "X" ? 0 : 1];
        }
    }
    return coord;
} 

个人的getPageCoord方法用来收获鼠标事件频仍相对于文档的坐标(水平,垂直)。

Firefox引入了pageX / Y ,IE9/Safari/Chrome/Opera虽然支持但单单以文档(document)内如果不页面(page)。

Safari/Chrome/Opera可以利用规范的clientX/Y获取,IE下而透过clientX/Y与scrollLeft/scrollTop计算得到。
IE9实际上也可是通过clientX/Y获取,这里判断浏览器Ext.isIE在IE9正式版即将公布后显然不妥。

 

重复为生就算是一个目标pub,匿名函数执行后会回来该对象。猜测pub是public的简写,即匿名函数执行后对外公开的接口对象(pub)。pub有以下方式

addListener: function(el, eventName, fn) {
    el = Ext.getDom(el);
    if (el && fn) {
        if (eventName == UNLOAD) {
            if (unloadListeners[el.id] === undefined) {
                unloadListeners[el.id] = [];
            }
            unloadListeners[el.id].push([eventName, fn]);
            return fn;
        }
        return doAdd(el, eventName, fn, false);
    }
    return false;
},

否要素添加事件,el为抬高风波的元素,eventName也事件名称(如click),fn为响应函数(hanlder)。对“unload”事件召开了单独处理,内部调用私有的doAdd函数。

 

removeListener: function(el, eventName, fn) {
    el = Ext.getDom(el);
    var i, len, li, lis;
    if (el && fn) {
        if(eventName == UNLOAD){
            if((lis = unloadListeners[el.id]) !== undefined){
                for(i = 0, len = lis.length; i < len; i++){
                    if((li = lis[i]) && li[TYPE] == eventName && li[FN] == fn){
                        unloadListeners[id].splice(i, 1);
                    }
                }
            }
            return;
        }
        doRemove(el, eventName, fn, false);
    }
},

去除元素都报之轩然大波响应函数,参数同addListener。

眼看点儿单函数都产生个注释:This function should ALWAYS be called from
Ext.EventManager
好窥见,真正客户端程序员以使用Ext库时连无直接使用Ext.lib.Event.addListener
/ Ext.lib.Event.removeListener添加或删除事件。

而是使用Ext.EventManager.addListener /
Ext.EventManager.removeListener或者它们的缩写Ext.EventManager.on /
Ext.EventManager.un。
Ext.EventManager对事件管理提供了又强层次的包。后续会介绍。

 

getTarget : function(ev) {
    ev = ev.browserEvent || ev;
    return this.resolveTextNode(ev.target || ev.srcElement);
},

抱事件源对象。W3C标准以 target ,IE6/7/8运用了专有的 srcElement 。令人惊异的凡Safari/Chrome/Opera也支持IE6/7/8方,即以支持标准和IE专有方式。Firefox仅支持标准的target,IE9beta现都支持target。

 

getRelatedTarget : function(ev) {
    ev = ev.browserEvent || ev;
    return this.resolveTextNode(ev.relatedTarget ||
            (ev.type == MOUSEOUT ? ev.toElement :
             ev.type == MOUSEOVER ? ev.fromElement : null));
},

得事件有关的素。W3C标准下 relatedTarget ,IE6/7/8用到了专有的 fromElement.aspx) / toElement.aspx) 。同样Safari/Chrome/Opera也支撑IE6/7/8方法,即以支持标准与IE专有方式。Firefox仅支持标准的relatedTarget,IE9也一度支持relatedTarget。

 

getPageX : function(ev) {
    return getPageCoord(ev, "X");
},
getPageY : function(ev) {
    return getPageCoord(ev, "Y");
},
getXY : function(ev) {
    return [this.getPageX(ev), this.getPageY(ev)];
},

getPageX,getPageY调用私有的getPageCoord,getPageCoord介绍如齐。getXY调用getPageX,getPageY。

 

stopEvent : function(ev) {
    this.stopPropagation(ev);
    this.preventDefault(ev);
},
stopPropagation : function(ev) {
    ev = ev.browserEvent || ev;
    if (ev.stopPropagation) {
        ev.stopPropagation();
    } else {
        ev.cancelBubble = true;
    }
},
preventDefault : function(ev) {
    ev = ev.browserEvent || ev;
    if (ev.preventDefault) {
        ev.preventDefault();
    } else {
        ev.returnValue = false;
    }
},

当即三个章程反过来说,即先说preventDefault,阻止元素的默认行为。如链接A点击,默认会跳转;input[type=submit]点击,默认会提交表单。
W3C标准以 preventDefault 道,IE6/7/8尽管是安装 returnValue .aspx)为false。Safari/Chrome/Opera同时支持IE6/7/8主意。Firefox仅支持标准的preventDefault。IE9现就支持preventDefault。

stopPropagation 用来住事件冒泡。W3C标准以stopPropagation,IE6/7/8虽说是装 cancelBubble .aspx)为true。
Safari/Chrome/Opera/Firefox也支持IE方式收回冒泡。目前为止这是Firefox唯一的一个支持IE方式的性能。IE9beta现都支持stopPropagation。

stopEvent则同时阻止默认行为同波冒泡。

 

getEvent : function(e) {
    e = e || win.event;
    if (!e) {
        var c = this.getEvent.caller;
        while (c) {
            e = c.arguments[0];
            if (e && Event == e.constructor) {
                break;
            }
            c = c.caller;
        }
    }
    return e;
},

getEvent顾名思义获取事件目标。W3C标准下响应函数的率先单参数获取,IE6/7/8虽以window.event获取。
Safari/Chrome/Opera为支持IE6/7/8智得到,IE9beta已支持W3C标准措施得到。
至于各种状况下事件目标的博见jQuery:博事件目标的一家子。

 

getCharCode : function(ev) {
    ev = ev.browserEvent || ev;
    return ev.charCode || ev.keyCode || 0;
},

落按键码,注意在keypress 事件中行使。键盘事件DOM2遭压根没规则,见:Key
events 
据此各级浏览器自行实现,Firefox/Safari/Chrome/IE9beta支持charCode,IE6/7/8/Opera不支持可下keyCode替代。

 

getListeners : function(el, eventName) {
    Ext.EventManager.getListeners(el, eventName);
},

// deprecated, call from EventManager
purgeElement : function(el, recurse, eventName) {
    Ext.EventManager.purgeElement(el, recurse, eventName);
},

顿时半独方法以连续讲述。

重新下对load, unload做了单独处理。

Ext.lib.Event完毕。

 

ext-base-event.js

 

相关文章

网站地图xml地图