Created
September 26, 2010 18:55
-
-
Save scottschiller/598208 to your computer and use it in GitHub Desktop.
Somewhat-normalized event listener handling (DOM2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Somewhat-normalized event add/remove</title> | |
<script> | |
var addEvent, removeEvent; | |
(function() { | |
/* | |
* Somewhat-normalized event add/remove (old IE/W3C) | |
* -------------------------------------------------- | |
* W3-style arguments, optional capture | |
* (default capture param if omitted: false, bubbling) | |
* | |
* addEvent(object, eventName, eventHandler, capture*) | |
* example: addEvent(window, 'load', didLoad); | |
* | |
* removeEvent(object, eventName, eventHandler, capture*) | |
* example: removeEvent(window, 'load', didLoad); | |
* | |
* add/remove arguments must be identical to work. | |
*/ | |
var old = (window.attachEvent), slice = Array.prototype.slice; | |
evt = { | |
add: (old?'attachEvent':'addEventListener'), | |
remove: (old?'detachEvent':'removeEventListener') | |
}; | |
function getArgs(oArgs) { | |
var args = slice.call(oArgs), len = args.length; | |
if (old) { | |
args[1] = 'on' + args[1]; // prefix | |
if (len > 3) { | |
args.pop(); // no capture | |
} | |
} else if (len === 3) { | |
args.push(false); | |
} | |
return args; | |
} | |
function apply(args, sType) { | |
var element = args.shift(), | |
method = [evt[sType]]; | |
if (old) { | |
element[method](args[0], args[1]); | |
} else { | |
element[method].apply(element, args); | |
} | |
} | |
addEvent = function() { | |
apply(getArgs(arguments), 'add'); | |
}; | |
removeEvent = function() { | |
apply(getArgs(arguments), 'remove'); | |
}; | |
}()); | |
// ****************************************************************** | |
// * now, assign some example handlers and trigger a bunch of stuff * | |
// ****************************************************************** | |
var isDown = false; | |
var counter = 0; | |
var obj = null; | |
// each mouse down/up will add and remove its opposite event. | |
function down() { | |
isDown = true; | |
document.getElementById('mouse').innerHTML = (counter++); | |
addEvent(obj, 'mouseup', up); // watch for release | |
removeEvent(obj, 'mousedown', down, true); | |
} | |
function up() { | |
isDown = false; | |
document.getElementById('mouse').innerHTML = (counter++); | |
addEvent(obj, 'mousedown', down, true); // capture, too | |
removeEvent(obj, 'mouseup', up); | |
} | |
function didLoad() { | |
obj = (navigator.userAgent.match(/msie/i)?document:window); // IE doesn't like attaching onmousedown/up to window, Safari doesn't like document - and/or I'm simply doing it wrong somehow. :D | |
if (typeof console != 'undefined' && typeof console.log != 'undefined') { | |
console.log('window load fired.'); | |
} | |
up(); // watch for first mousedown() event | |
} | |
function cleanup() { | |
removeEvent(window, 'load', didLoad); | |
removeEvent(window, 'unload', cleanup); | |
if (isDown) { | |
removeEvent(obj, 'mouseup', up); | |
} else { | |
removeEvent(obj, 'mousedown', down, true); | |
} | |
if (typeof console != 'undefined' && typeof console.log != 'undefined') { | |
console.log('window unload: events removed'); | |
} | |
} | |
addEvent(window, 'load', didLoad); // lazy/convenient: no bubble param, default = false | |
addEvent(window, 'unload', cleanup); | |
</script> | |
</head> | |
<body> | |
<div> | |
<p>Mousedown/mouseup events: <span id="mouse">0</span></p> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interestingly, I found that the apply(this, args) call did not get along with some browsers (IE 9, Safari and Firefox) in certain cases - the change of scope to "this" really seemed to bugger things up and create type errors. Perhaps that breaks assignment of the handler, which expects the scope to be the element the event is assigned from.