读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中获取出错代码所在文件及行数的代码
Sep 23 Javascript
dtree 网页树状菜单及传递对象集合到js内,动态生成节点
Apr 14 Javascript
JavaScript事件委托的技术原理探讨示例
Apr 17 Javascript
原生JavaScript+LESS实现瀑布流
Dec 12 Javascript
分享33个jQuery与CSS3实现的绚丽鼠标悬停效果
Dec 15 Javascript
CSS图片响应式 垂直水平居中
Aug 14 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
Jun 09 Javascript
js图片轮播手动切换特效
Jan 12 Javascript
基于zTree树形菜单的使用实例
Dec 25 Javascript
React教程之封装一个Portal可复用组件的方法
Jan 02 Javascript
微信小程序遍历Echarts图表实现多个饼图
Apr 25 Javascript
简单了解vue 插值表达式Mustache
Jul 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无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
PHP获取youku视频真实flv文件地址的方法
2014/12/23 PHP
PHP curl 或 file_get_contents 获取需要授权页面的方法
2017/05/05 PHP
PHP自动载入类文件函数__autoload的使用方法
2019/03/25 PHP
javascript call方法使用说明
2010/01/11 Javascript
JavaScript判断表单中多选框checkbox选中个数的方法
2015/08/17 Javascript
JS+CSS实现另类带提示效果的竖向导航菜单
2015/10/15 Javascript
js实现四舍五入完全保留两位小数的方法
2016/08/02 Javascript
jQuery Easyui Datagrid实现单行的上移下移及保存移动的结果
2016/08/15 Javascript
JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
2017/01/18 Javascript
原生js实现鼠标跟随效果
2017/02/28 Javascript
jQuery插件FusionCharts实现的2D饼状图效果【附demo源码下载】
2017/03/03 Javascript
javascript实现QQ空间相册展示源码
2017/12/12 Javascript
Node使用Sequlize连接Mysql报错:Access denied for user ‘xxx’@‘localhost’
2018/01/03 Javascript
JS实现的对象去重功能示例
2019/06/04 Javascript
从零撸一个pc端vue的ui组件库( 计数器组件 )
2019/08/08 Javascript
vue data有值,但是页面{{}} 取不到值的解决
2020/11/09 Javascript
JavaScript实现移动小精灵的案例代码
2020/12/12 Javascript
Vue实现图书管理案例
2021/01/20 Vue.js
Python3搜索及替换文件中文本的方法
2015/05/22 Python
Fiddler如何抓取手机APP数据包
2016/01/22 Python
实例讲解Python中SocketServer模块处理网络请求的用法
2016/06/28 Python
使用matplotlib画散点图的方法
2018/05/25 Python
Python检查ping终端的方法
2019/01/26 Python
基于python图像处理API的使用示例
2020/04/03 Python
使用before和:after伪类制作css3圆形按钮
2014/04/08 HTML / CSS
Sandro Paris美国官网:典雅别致的法国时尚服饰品牌
2017/12/26 全球购物
俄罗斯便宜的在线服装商店:GroupPrice
2020/04/10 全球购物
秘书行业自我鉴定范文
2013/12/30 职场文书
应届毕业生求职信范文
2014/05/08 职场文书
2014年秋季开学典礼致辞
2014/08/02 职场文书
员工生日活动方案
2014/08/24 职场文书
关于保护环境的建议书
2019/06/24 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
Vue3.0写自定义指令的简单步骤记录
2021/06/27 Vue.js
Win11无法访问设备和打印机 如何解决页面空白
2022/04/09 数码科技