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的基本功能。

标签:跨浏览器,事件,javascript
0
投稿

猜你喜欢

  • Python数据可视化之绘制柱状图和条形图

    2022-10-19 21:51:46
  • MSSQL报错:参数数据类型 text 对于 replace 函数的参数 1 无效的解决办法

    2024-01-27 09:04:15
  • 把JS与CSS写在同一个文件里

    2007-12-16 15:29:00
  • javascript 版 Bad Apple 字符动画

    2010-01-28 12:19:00
  • django 连接数据库出现1045错误的解决方式

    2024-01-17 19:37:47
  • Django 设置admin后台表和App(应用)为中文名的操作方法

    2023-01-31 13:37:54
  • python实现文件批量重命名

    2022-06-28 15:29:28
  • python识别验证码的思路及解决方案

    2022-02-02 16:05:13
  • MSSQL中部分字段重复数据的删除方法

    2008-12-29 13:59:00
  • Python进程池Pool应用实例分析

    2022-02-22 16:46:01
  • Python+腾讯云服务器实现每日自动健康打卡

    2023-08-18 00:22:44
  • [CSS+JS]同一页面可以重复使用的选项卡

    2009-02-12 12:53:00
  • 从零学python系列之新版本导入httplib模块报ImportError解决方案

    2022-08-22 16:21:06
  • 利用Python编写简易的录制屏幕小工具

    2023-12-17 04:34:57
  • python爬虫学习笔记之Beautifulsoup模块用法详解

    2022-06-27 12:30:03
  • Mac上安装MySQL过程分享

    2024-01-22 16:03:34
  • python爬虫要用到的库总结

    2021-04-16 23:55:40
  • 浅谈Scrapy框架普通反爬虫机制的应对策略

    2023-07-14 17:11:40
  • 常用原生js自定义函数总结

    2024-04-16 09:05:57
  • Python3.9.1中使用match方法详解

    2023-09-14 09:51:21
  • asp之家 网络编程 m.aspxhome.com