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

Extjs源码之--Ext.lib.Event(事件的简单封装)

这个对象是对事件的基础封装,在实际使用中,我们往往不从这里去引用,而更多的是从Ext.EventManager中引用,这个只是为Ext.EventManager的接口做准备,这里定义:添加监听,删除监听,取消冒泡,阻止事件默认行为,事件目标,事件类型,事件源,以及鼠标事件的客户区坐标位置,屏幕坐标位置,键码,字符编码等方面对浏览器兼容性进行了处理,事件是兼容性最差的一块,所以再写自己应用的时候一定要多查相关资料,还是Nicholas C. Zakas《javascript 高级程序设计》第二版 第12章,可以说EXT源码中涉及到的,这本书里面都有说到!所以我这里也没有每个方法都去解释一遍

Ext.lib.Event = function() {
//一堆的变量/常量的定义,有些我们可能觉得是没必要的,但Ext就是这么做,如SCROLLLEFT 这样的,但win和doc我是觉得完全有必要的,这样在压缩的时候能减少字节数,同时也能减少对象查找,这里定义后查找的函数内的局部变量,但不定义查询的是全局变量,所以EXT这么做都是又其道理的
    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',
        // private
        //事件监听的简单封装
        doAdd = function() {
            var ret;
            if (win.addEventListener) {
                ret = function(el, eventName, fn, capture) {
                    if (eventName == 'mouseenter') {//ie专有的事件,只有第一次才被激活,这里通过MOUSEOVER模拟mouseenter事件,这里的做法是通过拦截器实现
                        fn = fn.createInterceptor(checkRelatedTarget);
                        el.addEventListener(MOUSEOVER, fn, (capture));
                    } else if (eventName == 'mouseleave') {//ie专有的事件,只有第一次才被激活
                        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;
        }(),
        // private
        doRemove = function(){
            var ret;
            if (win.removeEventListener) {
                ret = function (el, eventName, fn, capture) {
                    if (eventName == 'mouseenter') {//因为添加是由MOUSEOVER模拟的所以这里删除就只要删除MOUSEOVER就行了
                        eventName = MOUSEOVER;
                    } else if (eventName == 'mouseleave') {
                        eventName = MOUSEOUT;
                    }
                    el.removeEventListener(eventName, fn, (capture));
                };
            } else if (win.detachEvent) {
                ret = function (el, eventName, fn) {
                    el.detachEvent("on" + eventName, fn);
                };
            } else {
                ret = function(){};
            }
            return ret;
        }();

    function checkRelatedTarget(e) {
        return !elContains(e.currentTarget, pub.getRelatedTarget(e));
    }
    //这里为什么这么写,我又点迷惑,为什么不像 Ext.lib.Dom 中 isAncestor一样写,估计是EXT开发人员自己忽视了
    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;
    }

    // private
    function _tryPreloadAttach() {
        var ret = false,
            notAvail = [],
            element, i, len, v,
            tryAgain = !loadComplete || (retryCount > 0);

        if (!locked) {
            locked = true;

            for (i