读jQuery之八 包装事件对象


Posted in Javascript onJune 21, 2011

比如,停止事件冒泡IE用 cancelBubble ,标准浏览器则用 stopPropagation 。
获取事件源对象,IE用 srcElement ,标准浏览器则用 target 诸如此类。
jQuery 对原生事件对象的修复和包装主要使用 jQuery.Event 类和 jQuery.event.fix 方法。

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 
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 
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方法 如下

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对象。
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之七 及 各浏览器中鼠标按键值的差异 做了详细分析。
最后,给zChain.js添加包装事件对象的相关代码。
zChain-0.7.1.js
Javascript 相关文章推荐
Firefox和IE浏览器兼容JS脚本写法小结
Jul 07 Javascript
jQuery+css+html实现页面遮罩弹出框
Mar 21 Javascript
JavaScript中为什么null==0为false而null大于=0为true(个人研究)
Sep 16 Javascript
js特殊字符转义介绍
Nov 05 Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 Javascript
微信公众平台开发教程(六)获取个性二维码的实例
Dec 02 Javascript
jQuery.Form上传文件操作
Feb 05 Javascript
微信小程序表单验证功能完整实例
Dec 01 Javascript
vue 实现类似淘宝星级评分的示例
Mar 01 Javascript
如何使node也支持从url加载一个module详解
Jun 05 Javascript
vue语法自动转typescript(解放双手)
Sep 18 Javascript
js实现简单贪吃蛇游戏
May 15 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
Jun 21 #Javascript
读jQuery之六 缓存数据功能介绍
Jun 21 #Javascript
将HTMLCollection/NodeList/伪数组转换成数组的实现方法
Jun 20 #Javascript
读jQuery之五(取DOM元素)
Jun 20 #Javascript
读jQuery之四(优雅的迭代)
Jun 20 #Javascript
火狐4、谷歌12不支持Jquery Validator的解决方法分享
Jun 20 #Javascript
合并table相同单元格的jquery插件分享(很精简)
Jun 20 #Javascript
You might like
PHP中trait使用方法详细介绍
2017/05/21 PHP
PHP实现的最大正向匹配算法示例
2017/12/19 PHP
TP5框架实现自定义分页样式的方法示例
2020/04/05 PHP
javascript得到当前页的来路即前一页地址的方法
2014/02/18 Javascript
javascript 实现 原路返回
2015/01/21 Javascript
jQuery找出网页上最高元素的方法
2015/03/20 Javascript
jquery分页插件jquery.pagination.js使用方法解析
2016/04/01 Javascript
JavaScript浮点数及运算精度调整详解
2016/10/21 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
详解VUE的状态控制与延时加载刷新
2017/03/27 Javascript
vue.js实现刷新当前页面的方法教程
2017/07/05 Javascript
Webpack 4.x搭建react开发环境的方法步骤
2018/08/15 Javascript
JavaScript实现与使用发布/订阅模式详解
2019/01/19 Javascript
详解vue中使用protobuf踩坑记
2019/05/07 Javascript
简单了解vue.js数组的常用操作
2019/06/17 Javascript
vue-router的钩子函数用法实例分析
2019/10/26 Javascript
jQuery操作元素的内容和样式完整实例分析
2020/01/10 jQuery
微信小程序实现点击页面出现文字
2020/09/21 Javascript
记录一次websocket封装的过程
2020/11/23 Javascript
python pickle 和 shelve模块的用法
2013/09/16 Python
深入解析Python编程中JSON模块的使用
2015/10/15 Python
python监控linux内存并写入mongodb(推荐)
2017/09/11 Python
Python实现矩阵转置的方法分析
2017/11/24 Python
利用Pandas读取文件路径或文件名称包含中文的csv文件方法
2018/07/04 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
2019/06/26 Python
python实现文件批量编码转换及注意事项
2019/10/14 Python
使用 Supervisor 监控 Python3 进程方式
2019/12/05 Python
Django之富文本(获取内容,设置内容方式)
2020/05/21 Python
Python中return函数返回值实例用法
2020/11/19 Python
Rosetta Stone官方网站:语言学习
2019/01/05 全球购物
后勤人员自我鉴定
2013/10/20 职场文书
运动会致辞稿50字
2014/02/04 职场文书
婚前协议书范本
2014/04/15 职场文书
廉洁自律演讲稿
2014/05/22 职场文书
事业单位鉴定材料
2014/05/25 职场文书
实习生矿工检讨书
2014/10/13 职场文书