读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 相关文章推荐
列表内容的选择
Jun 30 Javascript
点击广告后才能获得下载地址
Oct 26 Javascript
JQuery 实现的页面滚动时浮动窗口控件
Jul 10 Javascript
JavaScript DOM 学习第二章 编辑文本
Feb 19 Javascript
让js弹出窗口居前显示的实现方法
Jul 10 Javascript
Javascript字符串浏览器兼容问题分析
Dec 01 Javascript
javascript实现checkbox复选框实例代码
Jan 10 Javascript
初识简单却不失优雅的Vue.js
Sep 12 Javascript
JS闭包可被利用的常见场景小结
Apr 09 Javascript
jQuery实现新闻播报滚动及淡入淡出效果示例
Mar 23 jQuery
vue项目中使用百度地图的方法
Jun 08 Javascript
百度小程序之间的页面通信过程详解
Jul 18 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
zend api扩展的php对象的autoload工具
2011/04/18 PHP
php返回json数据函数实例
2014/10/09 PHP
php中实现用数组妩媚地生成要执行的sql语句
2015/07/10 PHP
PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】
2017/11/17 PHP
在laravel框架中实现封装公共方法全局调用
2019/10/14 PHP
远离JS灾难css灾难之 js私有函数和css选择器作为容器
2011/12/11 Javascript
一个页面放2段图片滚动代码出现冲突的问题如何解决
2012/12/21 Javascript
如何使用JS获取IE上传文件路径(IE7,8)
2013/07/08 Javascript
jquery遍历checkbox介绍
2014/02/21 Javascript
javascript对象的使用和属性操作示例详解
2014/03/02 Javascript
jquery操作select大全
2014/04/25 Javascript
jQuery中is()方法用法实例
2015/01/06 Javascript
jQuery实现跨域iframe接口方法调用
2015/03/14 Javascript
Jquery实现纵向横向菜单
2016/01/24 Javascript
JS插件clipboard.js实现一键复制粘贴功能
2020/12/04 Javascript
Python编程实战之Oracle数据库操作示例
2017/06/21 Python
Django处理文件上传File Uploads的实例
2018/05/28 Python
python 基本数据类型占用内存空间大小的实例
2018/06/12 Python
python的依赖管理的实现
2019/05/14 Python
Python八皇后问题解答过程详解
2019/07/29 Python
如何关掉pycharm中的python console(图解)
2019/10/31 Python
django 中使用DateTime常用的时间查询方式
2019/12/03 Python
Python configparser模块操作代码实例
2020/06/08 Python
html5实现多图片预览上传及点击可拖拽控件
2018/03/15 HTML / CSS
面向对象概念面试题(.NET)
2016/11/04 面试题
Linux管理员面试经常问道的相关命令
2014/12/12 面试题
参观监狱心得体会
2014/01/02 职场文书
公司年会演讲稿范文
2014/01/11 职场文书
奶茶店创业计划书范文
2014/01/17 职场文书
2014年大学生自我评价
2014/01/19 职场文书
物理教学随笔感言
2014/02/22 职场文书
保卫科工作岗位职责
2014/03/01 职场文书
护理专业自荐书
2014/06/04 职场文书
建筑节能汇报材料
2014/08/22 职场文书
2019年工作总结范文
2019/05/21 职场文书
MySQL数据库之存储过程 procedure
2022/06/16 MySQL