javascript 跨浏览器的事件系统
作者:wxnet 来源:51js 发布时间:2010-07-28 19:34:00
在ie7发布之前,Dean的addEvent/removeEvent可以称的上是完美了。IE7发布后,引入新的内存泄漏(这个我不是很确定,忘各位前辈们指教。),决心实现一套相对完美的事件系统。
1、正确的this指向。
2、统一了不同浏览器的事件源调用方式。
/**
* @fileoverview javascript事件系统
* @author wangxiang | [email]wxnet2013@gmail.com[/email]
*/
var elements = {};
var eventFns = {};
function addEvent(ele, evt, fn) {
if (ele.addEventListener) {
addEvent = function(ele, evt, fn) {
ele.addEventListener(evt, fn, false);
};
} else {
addEvent = function(ele, evt, fn) {
var uid = "";
var eleid = ele.evtid;
var list = [];
if (!eleid) {
uid = 'element_uid_' + Math.floor(Math.random() * 2147483648).toString(36);
ele.evtid = uid;
elements[uid] = ele;
eventFns[uid] = eventFns[uid] || {};
eventFns[uid]["" + evt] = [];
// 将之前注册过的事件,添加到事件系统中
if (ele["on" + evt]) {
eventFns[uid]["" + evt][0] = ele["on" + evt];
}
eventFns[uid]["" + evt].push(fn);
ele["on" + evt] = function(event) {
list = eventFns[uid]["" + evt];
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
for (var i = 0, len = list.length; i < len; i++) {
list[i].call(this, event);
}
};
} else {
//其它事件
if (!eventFns[eleid]["" + evt]) {
list = eventFns[eleid]["" + evt] = [];
// 将之前注册过的事件,添加到事件系统中
if (ele["on" + evt]) {
eventFns[eleid]["" + evt][0] = ele["on" + evt];
}
ele["on" + evt] = function(event) {
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
for (var i = 0, len = list.length; i < len; i++) {
list[i].call(this, event);
}
};
}
eventFns[eleid]["" + evt].push(fn);
}
}
}
return addEvent(ele, evt, fn);
}
function removeEvent(ele, evt, fn) {
if (ele.removeEventListener) {
removeEvent = function(ele, evt, fn) {
ele.removeEventListener(evt, fn, false);
}
} else {
removeEvent = function(ele, evt, fn) {
var eleid = ele.evtid;
if (!eleid) return;
var list = eventFns[eleid]["" + evt];
for (var i = 0, len = list.length; i < len; i++) {
if (fn === list[i]) {
list.splice(i, 1);
}
}
};
}
return removeEvent(ele, evt, fn);
}
// fixEvent written by Dean Edwards, 2005
//http://dean.edwards.name/my/events.js
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
//73到110行,取自jquery事件系统
// Fix target property, if necessary
if (!event.target) {
event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
}
// 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 && ((event.charCode || event.charCode === 0) ? event.charCode: event.keyCode)) {
event.which = 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;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};
参考了Dean Edwards的addEvent和jquery的fix机制,目前实现了addEvent/removeEvent的基本功能。


猜你喜欢
- 一下demo演示2.0中的vue-router是如何获取到不同参数的,并在地址栏中匹配不同的信息 <!DOCTYPE html>
- 简单总结:1、与类和实例无绑定关系的function都属于函数(function);2、与类和实例有绑定关系的function都属于方法(m
- 本文实例讲述了Python3实现的Mysql数据库操作封装类。分享给大家供大家参考,具体如下:#encoding:utf-8#name:mo
- 1. 项目背景视频传输: 在一台电脑上播放视频(捕捉摄像头画面),同局域网内另一台电脑上实时播放,尽量不卡顿。先放最后的照片,和用gif展示
- 引言https://github.com/go-chassis/go-chassis是一个微服务开发框架,而微服务开发框架带来的其中一个课题
- 网页版面布局的方法及技巧,版面指的是浏览器看到的完整的一个页面(可以包含框架和层)。因为每个人的显示器分辨率不同,所以同一个页面的大小可能出
- Mac下mysql安装配置方法图文教程记录如下使用安装包安装mysql双击pkg文件安装一路向下,记得保存最后弹出框中的密码(它是你mysq
- 先来聊一聊Top K算法,具体内容如下应用场景: 搜索引
- 开发环境与配置win_x64Ubuntu14.04Python3.xpip安装pymysql模块直接使用pip安装 pip install
- SQL Server所谓的分布式查询(Distributed Query)是能够访问存放在同一部计算机或不同计算机上的SQL Server或
- 需求分析背景:1.数据列表页,滚动加载数据;2.多条数据情况下,点击某一条,进入详细页进行编辑(修改,删除)操作;3.保存返回上一页;在上面
- 前言我们编写的Web项目部署之后,经常会因为需要进行配置变更或功能迭代而重启服务,单纯的kill -9 pid的方式会强制关闭进程,这样就会
- 如果不小心按到键盘上的Insert键的话,光标显示的就不是一条竖线,而是一个类似方块的阴影区域,比如插入一下insert键的介绍:它叫插入键
- 下面代码写的是js验证检查输入的字符是否是全角的函数:效果演示:<script> function i
- Microsoft建立了一种既灵活又强大的安全管理机制,它能够对用户访问SQL Server服务器系统和数据库的安全进行全面地管理。按照本文
- 需求:启动程序后,让用户输入工资,然后打印商品列表允许用户根据商品编号购买商品用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒可随时
- 本人就职于一个本地门户网站,每天网站上的天气都得更新。久而久之感到相当麻烦,于是写了一个定时的新闻小偷,帖出来大家参考一下系统
- 像素误差看自己设计好上线的网站,偶尔会发觉像素行间出现了弹性空间,总在不经意间蹦出一定的差距。有些页面很难发现,比如活动类页面,这类页面多呈
- pickle的作用:1:pickle.dump(dict,file)把字典转为二进制存入文件.2:pickle.load(file)把文件二
- 创建测试表-- ------------------------------ Table structure for check_test-