读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 捕获窗口关闭事件
Jul 26 Javascript
php中给js数组赋值方法
Mar 10 Javascript
JavaScript电子时钟倒计时
Jan 09 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
Jan 12 Javascript
Angular4 中常用的指令入门总结
Jun 12 Javascript
实现div滚动条默认最底部以及默认最右边的示例代码
Nov 15 Javascript
vue中实现methods一个方法调用另外一个方法
Feb 08 Javascript
详解原生JS回到顶部
Mar 25 Javascript
jQuery提示框插件SweetAlert用法分析
Aug 05 jQuery
Vue实现将数据库中带html标签的内容输出(原始HTML(Raw HTML))
Oct 28 Javascript
VUE.CLI4.0配置多页面入口的实现
Nov 25 Javascript
JavaScript cookie原理及使用实例
May 08 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
5.PHP的其他功能
2006/10/09 PHP
提升PHP执行速度全攻略(上)
2006/10/09 PHP
新浪微博API开发简介之用户授权(PHP基础篇)
2011/09/25 PHP
通过缓存数据库结果提高PHP性能的原理介绍
2012/09/05 PHP
popdiv
2006/07/14 Javascript
jquery.tmpl JQuery模板插件
2011/10/10 Javascript
JavaScript操作Oracle数据库示例
2015/03/06 Javascript
jQuery实现tab选项卡效果的方法
2015/07/08 Javascript
easyui Droppable组件实现放置特效
2015/08/19 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
微信企业号开发之微信考勤Cookies的使用
2015/09/11 Javascript
jQuery 获取遍历获取table中每一个tr中的第一个td的方法
2016/10/05 Javascript
JavaScript 计算笛卡尔积实例详解
2016/12/02 Javascript
jQuery 改变P标签文本值方法
2018/02/24 jQuery
JS实现自定义弹窗功能
2018/08/08 Javascript
JavaScript页面倒计时功能完整示例
2019/05/15 Javascript
搭建一个nodejs脚手架的方法步骤
2019/06/28 NodeJs
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
深入剖析Python的爬虫框架Scrapy的结构与运作流程
2016/01/20 Python
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
PyCharm永久激活方式(推荐)
2020/09/22 Python
Django怎么在admin后台注册数据库表
2020/11/14 Python
Agoda西班牙:全球特价酒店预订
2017/06/03 全球购物
英国发展最快的在线超市之一:Click Marketplace
2021/02/15 全球购物
thinkphp5 redis缓存新增方法实例讲解
2021/03/24 PHP
大班幼儿评语大全
2014/04/30 职场文书
经济贸易系毕业生求职信
2014/05/31 职场文书
品牌推广活动策划方案
2014/08/19 职场文书
学前班语言教学计划
2015/01/20 职场文书
六一儿童节开幕词
2015/01/29 职场文书
2015个人半年总结范文
2015/03/09 职场文书
运动会宣传稿50字
2015/07/23 职场文书
python爬取新闻门户网站的示例
2021/04/25 Python
原生Js 实现的简单无缝滚动轮播图的示例代码
2021/05/10 Javascript
Go微服务项目配置文件的定义和读取示例详解
2022/06/21 Golang
Win11怎么添加用户?Win11添加用户账户的方法
2022/07/15 数码科技