读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 相关文章推荐
JavaScript中的Window窗口对象
Jan 16 Javascript
javascript 函数速查表
Feb 07 Javascript
javascript循环变量注册dom事件 之强大的闭包
Sep 08 Javascript
js 剪切板的用法(clipboardData.setData)与js match函数介绍
Nov 19 Javascript
JavaScript中的关联数组问题
Mar 04 Javascript
javascript中的Function.prototye.bind
Jun 25 Javascript
Bootstrap Table使用方法详解
Aug 01 Javascript
BootStrap的table表头固定tbody滚动的实例代码
Aug 24 Javascript
JS实现的DOM插入节点操作示例
Apr 04 Javascript
Postman的下载及安装教程详解
Oct 16 Javascript
vue中的router-view组件的使用教程
Oct 23 Javascript
微信小程序入门之绘制时钟
Oct 22 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 date()日期时间函数详解
2010/05/16 PHP
window.location和document.location的区别分析
2008/12/23 Javascript
js 异步处理进度条
2010/04/01 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
JS+CSS 制作的超级简单的下拉菜单附图
2013/11/22 Javascript
浅谈JavaScript数据类型及转换
2015/02/28 Javascript
jQuery图片特效插件Revealing实现拉伸放大
2015/04/22 Javascript
javascript表单处理具体实现代码(表单、链接、按钮)
2016/05/07 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
html+js+highcharts绘制圆饼图表的简单实例
2016/08/04 Javascript
javascript 将共享属性迁移到原型中去的实现方法
2016/08/31 Javascript
CSS3 3D 技术手把手教你玩转
2016/09/02 Javascript
详解ES6之async+await 同步/异步方案
2017/09/19 Javascript
JS伪继承prototype实现方法示例
2018/06/20 Javascript
javascript中UMD规范的代码推演
2018/08/29 Javascript
jQuery实现动态生成年月日级联下拉列表示例
2019/05/11 jQuery
vue简单封装axios插件和接口的统一管理操作示例
2020/02/02 Javascript
vue npm install 安装某个指定的版本操作
2020/08/11 Javascript
python中使用序列的方法
2015/08/03 Python
Python 多线程不加锁分块读取文件的方法
2018/12/11 Python
Python Django框架防御CSRF攻击的方法分析
2019/10/18 Python
python调用HEG工具批量处理MODIS数据的方法及注意事项
2020/02/18 Python
css3 线性渐变和径向渐变示例附图
2014/04/08 HTML / CSS
css3 transform属性详解
2014/09/30 HTML / CSS
10分钟理解CSS3 FlexBox弹性布局
2018/12/20 HTML / CSS
canvas实现高阶贝塞尔曲线(N阶贝塞尔曲线生成器)
2018/01/10 HTML / CSS
Boom手表官网:瑞典手表品牌,设计你的手表
2019/03/11 全球购物
长曲棍球装备:Lacrosse Monkey
2020/12/02 全球购物
学校副校长四风对照检查材料整改措施
2014/09/25 职场文书
2014年自愿离婚协议书
2014/10/10 职场文书
承诺函范文
2015/01/21 职场文书
2015年度女工工作总结
2015/10/22 职场文书
小学音乐课教学反思
2016/02/18 职场文书
mysql 8.0.24 安装配置方法图文教程
2021/05/12 MySQL
Python快速实现一键抠图功能的全过程
2021/06/29 Python
Python 如何利用ffmpeg 处理视频素材
2021/11/27 Python