jQuery event 源码注释

xiaoxiao2022-06-12  66

/* * author:prk * date:2008-08-17 * comment:analyse of jquery event *   */ jQuery.event = {     // add 事件到一个元素上。     add : function(elem, types, handler, data) {         if (elem.nodeType == 3 || elem.nodeType == 8)// 空白节点或注释             return;         // IE不能传入window,先复制一下。         if (jQuery.browser.msie && elem.setInterval)             elem = window;         // 为handler分配一个全局唯一的Id         if (!handler.guid)             handler.guid = this.guid++;         // 把data附到handler.data中         if (data != undefined) {             var fn = handler;             handler = this.proxy(fn, function() {// 唯一Id,wrap原始handler Fn                         return fn.apply(this, arguments);                     });            handler.data = data;        }         // 初始化元素的events。如果没有取到events中值,就初始化data: {}         var events = jQuery.data(elem, "events")                 || jQuery.data(elem, "events", {}),         // 如果没有取到handle中值,就初始化data: function() {....}         handle = jQuery.data(elem, "handle")                 || jQuery.data(elem, "handle"function() {                     // 处理一个触发器的第二个事件和当page已经unload之后调用一个事件。                         if (typeof jQuery != "undefined"                                 && !jQuery.event.triggered)                             return jQuery.event.handle.apply(// arguments.callee.elem=handle.elem                                     arguments.callee.elem, arguments);                    });         // 增加elem做为handle属性,防止IE由于没有本地Event而内存泄露。         handle.elem = elem;         // 处理采用空格分隔多个事件名,如jQuery(...).bind("mouseover mouseout", fn);         jQuery.each(types.split(/\s+/), function(index, type) {             // 命名空间的事件,一般不会用到。                 var parts = type.split(".");                 type = parts[0];                handler.type = parts[1];                 // 捆绑到本元素type事件的所有处理函数                 var handlers = events[type];                 if (!handlers) {// 没有找到处理函数列表就初始化事件队列                     handlers = events[type] = {};                     // 如果type不是ready,或ready的setup执行返回false                     if (!jQuery.event.special[type]                             || jQuery.event.special[type].setup                                     .call(elem, data) === false) {                         // 调用系统的事件函数来注册事件                         if (elem.addEventListener)// FF                             elem.addEventListener(type, handle, false);                         else if (elem.attachEvent)// IE                             elem.attachEvent("on" + type, handle);                     }                }                 // 把处理器的id和handler形式属性对的形式保存在handlers列表中,                 // 也存在events[type][handler.guid]中。                 handlers[handler.guid] = handler;                 // 全局缓存这个事件的使用标识                 jQuery.event.global[type] = true;             });         // 防止IE内存泄露。         elem = null;     },    guid : 1,    global : {},     // 从元素中remove一个事件     remove : function(elem, types, handler) {         if (elem.nodeType == 3 || elem.nodeType == 8)             return;         // 取出元素的events中Fn列表         var events = jQuery.data(elem, "events"), ret, index;         if (events) {             // remove所有的该元素的事件 .是命名空间的处理             if (types == undefined                     || (typeof types == "string" && types.charAt(0) == "."))                 for (var type in events)                     this.remove(elem, type + (types || ""));             else {                 // types, handler参数采用{type:xxx,handler:yyy}形式                 if (types.type) {                     handler = types.handler;                    types = types.type;                }                 // 处理采用空格分隔多个事件名 jQuery(...).unbind("mouseover mouseout", fn);                 jQuery                         .each(types.split(/\s+/), function(index, type) {                             // 命名空间的事件,一般不会用到。                                 var parts = type.split(".");                                 type = parts[0];                                 if (events[type]) {// 事件名找到                                     if (handler)// handler传入,就remove事件名的这个处理函数                                         delete events[type][handler.guid];//guid的作用                                     else    // remove这个事件的所有处理函数,带有命名空间的处理                                         for (handler in events[type])                                             if (!parts[1]                                                     || events[type][handler].type == parts[1])                                                 delete events[type][handler];                                     // 如果没有该事件的处理函数存在,就remove事件名                                     for (ret in events[type])// 看看有没有?                                         break;                                     if (!ret) {// 没有                                         if (!jQuery.event.special[type]//不是ready                                                 || jQuery.event.special[type].teardown                                                         .call(elem) === false) {// type不等于ready                                             if (elem.removeEventListener)// 在浏览器中remove事件名                                                 elem.removeEventListener(type,                                                        jQuery.data(elem,                                                                 "handle"),                                                         false);                                             else if (elem.detachEvent)                                                 elem.detachEvent("on" + type,                                                         jQuery.data(elem,                                                                 "handle"));                                         }                                         ret = null;                                         delete events[type];// 在缓存中除去。                                     }                                }                            });            }             // 不再使用,除去expando             for (ret in events)                 break;             if (!ret) {                 var handle = jQuery.data(elem, "handle");                 if (handle)                     handle.elem = null;                 jQuery.removeData(elem, "events");                 jQuery.removeData(elem, "handle");             }        }    },     trigger : function(type, data, elem, donative, extra) {         data = jQuery.makeArray(data);         if (type.indexOf("!") >= 0) {// 支持!的not的操作如!click,除click之后的所有             type = type.slice(0, -1);// 除最后一个字符?             var exclusive = true;         }         if (!elem) {// 处理全局的fire事件             if (this.global[type])                 jQuery.each(jQuery.cache, function() {                     // 从cache中找到所有注册该事件的元素,触发改事件的处理函数                         if (this.events && this.events[type])                             jQuery.event.trigger(type, data, this.handle.elem);                     });         } else {// 处理单个元素事件的fire事件             if (elem.nodeType == 3 || elem.nodeType == 8)                 return undefined;             var val, ret, fn = jQuery.isFunction(elem[type] || null),             // 我们是否要提交一个伪造的事件?             event = !data[0] || !data[0].preventDefault;             // 构建伪造的事件。             if (event) {                 data.unshift( {//存到数组中的第一个                     type : type,                    target : elem,                     preventDefault : function() {                     },                     stopPropagation : function() {                     },                    timeStamp : now()                });                 data[0][expando] = true// 不需要修正伪造事件             }             //防止事件名出错             data[0].type = type;             if (exclusive)                 data[0].exclusive = true;             // 触发事件             var handle = jQuery.data(elem, "handle");             if (handle)                 val = handle.apply(elem, data);             // Handle triggering native .onfoo handlers (and on links since we             // don't call .click() for links)             //处理触发.onfoo这样的本地处理方法,但是是对于links 's .click()不触发             if ((!fn || (jQuery.nodeName(elem, 'a') && type == "click"))                     && elem["on" + type]&& elem["on" + type].apply(elem, data) === false)                 val = false;             // Extra functions don't get the custom event object             if (event)                 data.shift();             // 处理触发extra事件             if (extra && jQuery.isFunction(extra)) {                 //执行extra,同时把结果存到data中。                 ret = extra.apply(elem, val == null ? data : data.concat(val));                 // if anything is returned, give it precedence and have it                 // overwrite the previous value                 if (ret !== undefined)                     val = ret;            }             // 触发本地事件             if (fn && donative !== false && val !== false                     && !(jQuery.nodeName(elem, 'a') && type == "click")) {                 this.triggered = true;                 try {                     elem[type]();                     //对于一些hidden的元素,IE会报错                 } catch (e) {                 }            }             this.triggered = false;         }         return val;     },     handle : function(event) {         // 返回 undefined or false         var val, ret, namespace, all, handlers;         event = arguments[0] = jQuery.event.fix(event || window.event);         // 命名空间处理         namespace = event.type.split(".");         event.type = namespace[0];        namespace = namespace[1];         // all = true 表明任何 handler         all = !namespace && !event.exclusive;         // 找到元素的events中缓存的事件名的处理函数列表         handlers = (jQuery.data(this"events") || {})[event.type];         for (var j in handlers) {// 每个处理函数执行             var handler = handlers[j];             // Filter the functions by class             if (all || handler.type == namespace) {                 // 传入引用,为了之后删除它们                 event.handler = handler;                event.data = handler.data;                 ret = handler.apply(this, arguments);// 执行事件处理函数                 if (val !== false)                     val = ret;// 只要有一个处理函数返回false,本函数就返回false.                 if (ret === false) {// 不执行浏览器默认的动作                     event.preventDefault();                    event.stopPropagation();                }            }        }         return val;     },     props : "altKey attrChange attrName bubbles button cancelable charCode clientX "             + "clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode "             + "metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX "             + "screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which"                     .split(" "),     //对事件进行包裹。     fix : function(event) {         if (event[expando] == true)//表明事件已经包裹过             return event;         //保存原始event,同时clone一个。         var originalEvent = event;         event = {            originalEvent : originalEvent        };         for (var i = this.props.length, prop;i;) {             prop = this.props[--i];             event[prop] = originalEvent[prop];        }                 event[expando] = true;                  //加上preventDefault and stopPropagation,在clone不会运行         event.preventDefault = function() {             // 在原始事件上运行             if (originalEvent.preventDefault)                 originalEvent.preventDefault();                         originalEvent.returnValue = false;         };         event.stopPropagation = function() {             // 在原始事件上运行             if (originalEvent.stopPropagation)                 originalEvent.stopPropagation();                         originalEvent.cancelBubble = true;         };         // 修正 timeStamp         event.timeStamp = event.timeStamp || now();         // 修正target         if (!event.target)             event.target = event.srcElement || document;                     if (event.target.nodeType == 3)//文本节点是父节点。             event.target = event.target.parentNode;         // relatedTarget         if (!event.relatedTarget && event.fromElement)             event.relatedTarget = event.fromElement == event.target                    ? event.toElement                    : event.fromElement;         // Calculate pageX/Y if missing and clientX/Y available         if (event.pageX == null && event.clientX != null) {             var doc = document.documentElement, body = document.body;             event.pageX = event.clientX                    + (doc && doc.scrollLeft || body && body.scrollLeft || 0)                    - (doc.clientLeft || 0);            event.pageY = event.clientY                    + (doc && doc.scrollTop || body && body.scrollTop || 0)                    - (doc.clientTop || 0);        }         // Add which for key events         if (!event.which                 && ((event.charCode || event.charCode === 0)                        ? event.charCode                        : event.keyCode))            event.which = event.charCode || event.keyCode;         // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)         if (!event.metaKey && event.ctrlKey)             event.metaKey = event.ctrlKe 相关资源:敏捷开发V1.0.pptx
转载请注明原文地址: https://www.6miu.com/read-4933709.html

最新回复(0)