The issue
We currently lack effective methods to avoid collisions between different event behaviours.
If one module sets an onclick
behaviour for an element like this
elt.on click = function() { alert('hello');};
, it may be overwriting a behaviour added already by a different module, or may itself be overwridden.
Current approach
In our current drupal.js, we use workarounds for two specific cases of attaching events: the window.onload
event and the onsubmit
event of forms. Functions addSubmitEvent
and addLoadEvent
basically string together the new event with any existing event. They more or less work, but somewhat awkwardly, and of course only for load and submit events. They don't provide a way of removing events.
Options
The obvious solution is the standards-compliant addEventListener
method, which allows us to attach more than one behaviour to a given page element.
The problem is that IE doesn't support addEventListener
. Hence the common approach of substituting IE's (more limited) proprietary method, attachEvent
.
Draft solution
So here (in the attached patch) is a draft solution. I've added addEvent
and removeEvent
methods, using addEventListener
where available and attachEvent
where needed. I've removed addLoadEvent
and addSubmitEvent
and replaced their calls with calls to addEvent
. Some quick testing in IE and Firefox suggests this should work.
Issues
But there are remaining issues, mainly that IE loses the this
target element reference on behaviours attached with attachEvent
, see this contest.
The best solution may simply be to use event object target detection, so we explicitly fetch the target of events before acting on them. So I've included a returnTarget()
method.
I've adapted addEvent()
and returnTarget()
from another open source project I participate in, Community Mapbuilder, where they've been working away without issues.
Using this or a similar solution would help streamline our code and prevent collisions as different modules each attach behaviours.
Comment | File | Size | Author |
---|---|---|---|
js-event-listeners.patch | 4.42 KB | nedjo | |
Comments
Comment #1
Steven CreditAttribution: Steven commentedHow does addEventListener deal with events that need to return values (such as onSubmit)?
Comment #2
Thox CreditAttribution: Thox commentedPeter-Paul Koch (quirksmode.org) held a content to decide what was the best way to add events with cross browser compatibility, minimal code, and without memory leaks. Here's the "winner" - which was debated in the comments:
http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
Comment #3
nedjoThanks for these initial comments.
Steven, I'm thinking that addEventListener just attaches the events and so isn't directly involved in the returned values. Return values should come back just the same as when attaching through
elt.on-change = functionName
. Can you think of a specific example that maybe I could test?Thox, the main issue addressed by the quirksmode contest seemed to be the loss of an object reference in the IE
attachEvent
. I tend just to fetch the reference explicitly as the event target when I need one. So, using thereturnTarget()
function in the above patch, we might use something like:But maybe I'm just lazily trying not to have to follow the intricacies of the quirksmode debates :)
Comment #4
ChrisKennedy CreditAttribution: ChrisKennedy commentedNot an issue anymore now that jQuery is in core.
Comment #5
(not verified) CreditAttribution: commented