看了网上的一些资料,发现有一下几种比较牛的:
john resig的 <!---->Flexible Javascript Events(The code, itself, is very short and simple - only 15 lines long:
)
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
function removeEvent( obj, type, fn ) {
if ( obj.detachEvent ) {
obj.detachEvent( 'on'+type, obj[type+fn] );
obj[type+fn] = null;
} else
obj.removeEventListener( type, fn, false );
}
dean.edwards 发表了自己的意见:
<!---->My solution is very different.
- it performs no object detection
- it does not use the addeventListener/attachEvent methods
- it keeps the correct scope (the this keyword)
- it passes the event object correctly
- it is entirely cross-browser (it will probably work on IE4 and NS4)
- and from what I can tell it does not leak memory
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini
// http://dean.edwards.name/weblog/2005/10/add-event/
function addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
}
};
// a counter used to create unique IDs
addEvent.guid = 1;
function removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
}
};
function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};
最后 dean.edwards 推荐了一种:
/**
* Crossbrowser event handling functions.
*
* A set of functions to easily attach and detach event handlers to HTML elements.
* These functions work around the shortcomings of the traditional method ( element.onevent = function; )
* where only 1 handler could be attached for a certain event on the object, and mimic the DOM level 2
* event methods addEventListener and removeEventListener for browsers that do not support these
* methods (e.g. Internet Explorer) without resorting to propriety methods such as attachEvent and detachEvent
* that have a whole set of their own shortcomings.
* Created as an entry for the 'contest' at quirksmode.org: http://www.quirksmode.org/blog/archives/2005/09/addevent_recodi.html
*
* @author Tino Zijdel ( crisp@xs4all.nl )
* @version 1.2
* @date 2005-10-21
*/
/**
* addEvent
*
* Generic function to attach event listeners to HTML elements.
* This function does NOT use attachEvent but creates an own stack of function references
* in the DOM space of the element. This prevents closures and therefor possible memory leaks.
* Also because of the way the function references are stored they will get executed in the
* same order as they where attached - matching the behavior of addEventListener.
*
* @param obj The object to which the event should be attached.
* @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
* @param fn The function to be executed when the event fires.
* @param useCapture (optional) Whether to use event capturing, or event bubbling (default).
*/
function addEvent(obj, evType, fn, useCapture)
{
//-- Default to event bubbling
if (!useCapture) useCapture = false;
//-- DOM level 2 method
if (obj.addEventListener)
{
obj.addEventListener(evType, fn, useCapture);
}
else
{
//-- event capturing not supported
if (useCapture)
{
alert('This browser does not support event capturing!');
}
else
{
var evTypeRef = '__' + evType;
//-- create function stack in the DOM space of the element; seperate stacks for each event type
if (obj[evTypeRef])
{
//-- check if handler is not already attached, don't attach the same function twice to match behavior of addEventListener
if (array_search(fn, obj[evTypeRef]) > -1) return;
}
else
{
//-- create the stack if it doesn't exist yet
obj[evTypeRef] = [];
//-- if there is an inline event defined store it in the stack
if (obj['on'+evType]) obj[evTypeRef][0] = obj['on'+evType];
//-- attach helper function using the DOM level 0 method
obj['on'+evType] = IEEventHandler;
}
//-- add reference to the function to the stack
obj[evTypeRef][obj[evTypeRef].length] = fn;
}
}
}
/**
* removeEvent
*
* Generic function to remove previously attached event listeners.
*
* @param obj The object to which the event listener was attached.
* @param evType The eventtype, eg. 'click', 'mousemove' etcetera.
* @param fn The listener function.
* @param useCapture (optional) Whether event capturing, or event bubbling (default) was used.
*/
function removeEvent(obj, evType, fn, useCapture)
{
//-- Default to event bubbling
if (!useCapture) useCapture = false;
//-- DOM level 2 method
if (obj.removeEventListener)
{
obj.removeEventListener(evType, fn, useCapture);
}
else
{
var evTypeRef = '__' + evType;
//-- Check if there is a stack of function references for this event type on the object
if (obj[evTypeRef])
{
//-- check if function is present in the stack
var i = array_search(fn, obj[evTypeRef]);
if (i > -1)
{
try
{
delete obj[evTypeRef][i];
}
catch(e)
{
obj[evTypeRef][i] = null;
}
}
}
}
}
/**
* IEEventHandler
*
* IE helper function to execute the attached handlers for events.
* Because of the way this helperfunction is attached to the object (using the DOM level 0 method)
* the 'this' keyword will correctely point to the element that the handler was defined on.
*
* @param e (optional) Event object, defaults to window.event object when not passed as argument (IE).
*/
function IEEventHandler(e)
{
e = e || window.event;
var evTypeRef = '__' + e.type, retValue = true;
//-- iterate through the stack and execute each function in the scope of the object by using function.call
for (var i = 0, j = this[evTypeRef].length; i < j; i++)
{
if (this[evTypeRef][i])
{
if (Function.call)
{
retValue = this[evTypeRef][i].call(this, e) && retValue;
}
else
{
//-- IE 5.0 doesn't support call or apply, so use this
this.__fn = this[evTypeRef][i];
retValue = this.__fn(e) && retValue;
}
}
}
if (this.__fn) try { delete this.__fn; } catch(e) { this.__fn = null; }
return retValue;
}
/**
* array_search
*
* Searches the array for a given value and returns the (highest) corresponding key if successful, -1 if not found.
*
* @param val The value to search for.
* @param arr The array to search in.
*/
function array_search(val, arr)
{
var i = arr.length;
while (i--)
if (arr[i] && arr[i] === val) break;
return i;
}
短的版本:
/**
* Generic add/removeEvent functionality
*
* @author Tino Zijdel ( crisp@xs4all.nl )
* @version 1.2 (short version)
* @date 2005-10-21
*/
function addEvent(obj, evType, fn)
{
var evTypeRef = '__' + evType;
if (obj[evTypeRef])
{
if (array_search(fn, obj[evTypeRef]) > -1) return;
}
else
{
obj[evTypeRef] = [];
if (obj['on'+evType]) obj[evTypeRef][0] = obj['on'+evType];
obj['on'+evType] = handleEvent;
}
obj[evTypeRef][obj[evTypeRef].length] = fn;
}
function removeEvent(obj, evType, fn)
{
var evTypeRef = '__' + evType;
if (obj[evTypeRef])
{
var i = array_search(fn, obj[evTypeRef]);
if (i > -1) delete obj[evTypeRef][i];
}
}
function handleEvent(e)
{
e = e || window.event;
var evTypeRef = '__' + e.type, retValue = true;
for (var i = 0, j = this[evTypeRef].length; i < j; i++)
{
if (this[evTypeRef][i])
{
this.__fn = this[evTypeRef][i];
retValue = this.__fn(e) && retValue;
}
}
if (this.__fn) try { delete this.__fn; } catch(e) { this.__fn = null; }
return retValue;
}
function array_search(val, arr)
{
var i = arr.length;
while (i--)
if (arr[i] && arr[i] === val) break;
return i;
}
不过我还是用了john resig 的。。。
本文介绍了几种实现跨浏览器事件处理的方法,包括johnresig和dean.edwards提出的解决方案,并提供了一个简洁版本的实现。
121

被折叠的 条评论
为什么被折叠?



