读jQuery之八(包装事件对象)

http://www.cnblogs.com/snandy/archive/2011/06/17/2081213.html

由于各个浏览器中原生事件对象的 差异性 ,多数 JS库/框架 都或多或少的对原生事件对象进行了修复及包装。


比如,停止事件冒泡IE用 cancelBubble ,标准浏览器则用 stopPropagation 。

获取事件源对象,IE用 srcElement ,标准浏览器则用 target 诸如此类。

 jQuery 对原生事件对象的修复和包装主要使用 jQuery.Event 类和 jQuery.event.fix 方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
jQuery.Event = function ( src ) {
     // Allow instantiation without the 'new' keyword
     if  ( ! this .preventDefault ) {
         return  new  jQuery.Event( src );
     }
 
     // Event object
     if  ( src && src.type ) {
         this .originalEvent = src;
         this .type = src.type;
 
         // Events bubbling up the document may have been marked as prevented
         // by a handler lower down the tree; reflect the correct value.
         this .isDefaultPrevented = (src.defaultPrevented || src.returnValue === false  ||
             src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
 
     // Event type
     } else  {
         this .type = src;
     }
 
     // timeStamp is buggy for some events on Firefox(#3843)
     // So we won't rely on the native value
     this .timeStamp = jQuery.now();
 
     // Mark it as fixed
     this [ jQuery.expando ] = true ;
};
 
function  returnFalse() {
     return  false ;
}
function  returnTrue() {
     return  true ;
}
 
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
jQuery.Event.prototype = {
     preventDefault: function () {
         this .isDefaultPrevented = returnTrue;
 
         var  e = this .originalEvent;
         if  ( !e ) {
             return ;
         }
 
         // if preventDefault exists run it on the original event
         if  ( e.preventDefault ) {
             e.preventDefault();
 
         // otherwise set the returnValue property of the original event to false (IE)
         } else  {
             e.returnValue = false ;
         }
     },
     stopPropagation: function () {
         this .isPropagationStopped = returnTrue;
 
         var  e = this .originalEvent;
         if  ( !e ) {
             return ;
         }
         // if stopPropagation exists run it on the original event
         if  ( e.stopPropagation ) {
             e.stopPropagation();
         }
         // otherwise set the cancelBubble property of the original event to true (IE)
         e.cancelBubble = true ;
     },
     stopImmediatePropagation: function () {
         this .isImmediatePropagationStopped = returnTrue;
         this .stopPropagation();
     },
     isDefaultPrevented: returnFalse,
     isPropagationStopped: returnFalse,
     isImmediatePropagationStopped: returnFalse
};

 

jQuery.Event 类主要做了以下工作

  1. 扩充了 originalEvent 属性,该属性暂存了原生事件对象
  2. 修复了 timeStamp ,该属性IE6/7/8不支持,其它支持的各个浏览器中返回值也不同
  3. 阻止DOM元素默认行为统一采用 preventDefault
  4. 停止事件冒泡统一采用 stopPropagation
  5. 实现或扩充了 DOM3事件 的几个方法:stopImmediatePropagation、isDefaultPrevented、isPropagationStopped、isImmediatePropagationStopped


此外,jQuery.Event的 写类方式 也较独特。它 使用隐藏的new创建对象 。

 

jQuery.event.fix方法 如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
fix: function ( event ) {
     if  ( event[ jQuery.expando ] ) {
         return  event;
     }
 
     // store a copy of the original event object
     // and "clone" to set read-only properties
     var  originalEvent = event;
     event = jQuery.Event( originalEvent );
 
     for  ( var  i = this .props.length, prop; i; ) {
         prop = this .props[ --i ];
         event[ prop ] = originalEvent[ prop ];
     }
 
     // Fix target property, if necessary
     if  ( !event.target ) {
         // Fixes #1925 where srcElement might not be defined either
         event.target = event.srcElement || document;
     }
 
     // check if target is a textnode (safari)
     if  ( event.target.nodeType === 3 ) {
         event.target = event.target.parentNode;
     }
 
     // Add relatedTarget, if necessary
     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 && doc.clientLeft || body && body.clientLeft || 0);
         event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
     }
 
     // Add which for key events
     if  ( event.which == null  && (event.charCode != null  || event.keyCode != null ) ) {
         event.which = event.charCode != null  ? 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.ctrlKey;
     }
 
     // Add which for click: 1 === left; 2 === middle; 3 === right
     // Note: button is not normalized, so don't use it
     if  ( !event.which && event.button !== undefined ) {
         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
     }
 
     return  event;
},

 

它主要做了以下工作
1,event = jQuery.Event( originalEvent ); 该句创建了一个jQuery.Event类的实例对象,该对象修复及扩充上面刚刚提到了。
2, 一个循环将原生事件对象的所有属性拷贝给 1 中的event对象。

?
1
2
3
4
for  ( var  i = this .props.length, prop; i; ) {
     prop = this .props[ --i ];
     event[ prop ] = originalEvent[ prop ];
}

3, 统一事件源对象为 target 。
4, 统一事件相关对象为 relativeTarget 。
5, 扩充了pageX , pageY ,这两个属性首次在Firefox中引入的。不支持该属性的浏览器使用clientX/Y计算得到。
6, 扩充了 which ,使用它获取键盘按键值(keyCode)。这个属性也是在Firefox引入的。
7, 修复了metaKey。
8, 扩充了which,使用它获取鼠标按键值

细心的人可能注意到了,jQuery获取键盘按键值和鼠标按键值都是采用which。它没有向其它属性一样去兼容W3C已有标准 (button )。这一点我在 读jQuery之七 及 各浏览器中鼠标按键值的差异 做了详细分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值