读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 相关文章推荐
小议Function.apply() 之一------(函数的劫持与对象的复制)
Nov 30 Javascript
IE与Firefox在JavaScript上的7个不同写法小结
Sep 14 Javascript
Jquery中dialog属性小记
Sep 03 Javascript
javascript中style.left和offsetLeft的用法说明
Mar 07 Javascript
javascript制作的cookie封装及使用指南
Jan 02 Javascript
JavaScript删除数组元素的方法
Mar 20 Javascript
JQuery实现图片轮播效果
May 08 jQuery
JavaScript中splice与slice的区别
May 09 Javascript
bootstrap table服务端实现分页效果
Aug 10 Javascript
Vue 组件间的样式冲突污染
Aug 31 Javascript
基于vue cli重构多页面脚手架过程详解
Jan 23 Javascript
Webpack5正式发布,有哪些新特性
Oct 12 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中数据的批量导入(csv文件)
2006/10/09 PHP
CI框架中$this->load->library()用法分析
2016/05/18 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
JavaScript高级程序设计
2006/12/29 Javascript
js过滤HTML标签以及空格的思路及代码
2013/05/24 Javascript
JS中for循序中延迟加载动态效果的具体实现
2013/08/18 Javascript
jquery防止重复执行动画避免页面混乱
2014/04/22 Javascript
jQuery与getJson结合的用法实例
2015/08/07 Javascript
javascript中Array()数组函数详解
2015/08/23 Javascript
详解JavaScript的Date对象(制作简易钟表)
2020/04/07 Javascript
javascript实现不同颜色Tab标签切换效果
2016/04/27 Javascript
js获取指定时间的前几秒
2017/04/05 Javascript
Three.js 再探 - 写一个微信跳一跳极简版游戏
2018/01/04 Javascript
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
Python操作SQLite数据库的方法详解
2017/06/16 Python
JavaScript实现一维数组转化为二维数组
2018/04/17 Python
python PrettyTable模块的安装与简单应用
2019/01/11 Python
python try 异常处理(史上最全)
2019/03/07 Python
python实现翻转棋游戏(othello)
2019/07/29 Python
python查看数据类型的方法
2019/10/12 Python
python GUI库图形界面开发之PyQt5滑块条控件QSlider详细使用方法与实例
2020/02/28 Python
Django如何使用redis作为缓存
2020/05/21 Python
Python flask框架如何显示图像到web页面
2020/06/03 Python
购买一个高级域名:BuyDomains
2018/03/11 全球购物
乐高瑞士官方商店:LEGO CH
2020/08/16 全球购物
解释一下Windows的消息机制
2014/01/30 面试题
精彩的大学生自我评价
2013/11/17 职场文书
商场中秋节活动方案
2014/02/07 职场文书
产品生产计划书
2014/05/07 职场文书
暑假社会实践证明格式
2014/10/28 职场文书
计算机实训报告范文
2014/11/05 职场文书
2015小学教师德育工作总结
2015/05/12 职场文书
CSS3 制作精美的定价表
2021/04/06 HTML / CSS
MySQL 使用索引扫描进行排序
2021/06/20 MySQL
MySQL中varchar和char类型的区别
2021/11/17 MySQL
MySQL窗口函数的具体使用
2021/11/17 MySQL