Skip navigation.

miscoded

the web is a hack

event capture explained

, , , , ,

What is event capture, and what are the implementation gotchas that cause problems for browsers and webmasters? Read on for details..

Occasionally I have been grumbling about un-intended event capture. Here is a more detailed explanation of the feature and the issues:

What is event capture?

If you call addEventListener with true as the third argument you create a capturing event. The difference from a normal event is that the capturing listener detects all events in the document before they are sent to the actual target of the event. So, for example if you have

  <body>
    <p onclick="alert('you clicked the p')">click to test</p>

and do
document.body.addEventListener('click', func, true)
the event listener on BODY will run before the onclick on the P tag. The event listener on BODY can choose to stop propagation so that the event will not actually be passed on to the P tag. For example,
document.body.addEventListener( 'click', function(e){ if(confirm('Stop event?'))e.stopPropagation(); }, true );

If the BODY event listener was not a capturing one, the P onclick would trigger first, then the BODY's listener would fire. So event capture is simply a way to change the order different elements will "see" the event.

Implementations
addEventListener and capturing events is part of the DOM2 Events standard, which is supported by Opera, Gecko/Firefox, and Safari. IE supports the slightly different attachEvent API.

Implementation differences: capture on target
The DOM spec states that capturing events should not fire on target, because the idea of a capturing event is to detect events before they reach their targets. Because of bugs in Gecko and Safari, web content that is tested mostly with Firefox or other Gecko-based browsers sometimes expects capturing listeners to fire on target. Such content will fail in Opera 7, 8 and current releases of 9 because of its correct implementation of the standard.

Implementation differences: capturing load events
document.addEventListener('load', func, true)
creates a capturing load event listener. Opera supports capture of load events. All items (images, style sheets, external scripts) loaded into a document has their own load event, and if you capture load events for the entire document your script is going to run for every such event.
Content that is tested with Gecko or older Safari versions tend to expect only one load event because these browsers do not support load event capture. Such content may fail in Opera because a script that expects to be run only once (for example to initialise the page) may be run hundreds of times.

Advisory

As browsers improve their DOM specification compatibility, a script that uses event capture without intending to do so will become incompatible with more and more browser versions. As a web developer, you can avoid the implementation gotchas in browsers and achieve cross-browser compatibility simply by avoiding capturing event listeners unless you know what you are doing. Make sure the third argument of your addEventListener calls defaults to false, not true.

spot a subtle JS error here..reload-mania from British Airways

Comments

dantesoft 12. October 2006, 07:13

This post is now also tagged with "abba, Cronic Fatigue Syndrom and Fybromyalgia, books, sonnenuntergang" (=sunset). OK, maybe the second is appropriate.

FataL 12. October 2006, 12:06

Nice and simple explanation! Thanks! :up:

hallvors 12. October 2006, 12:07

I know, My Opera was waaay more creative than me with tagging when I stored that post.

voituk 10. November 2006, 08:05

Thanks for a nice description!

lucke 25. January 2007, 11:41

Hi !

Is there a possibility to "catch" JavaScript "events" like : a JavaScript variable has been changed ?
Or, a property of an object etc.

As I saw, this function captures HTML events, but, can it be extended to JavaScript too ?

It may sound stupid, but it would be very usefull for me and others.

Kindly thanks in advance !

hallvors 29. January 2007, 11:57

A few browsers support DOM mutation events - see spec

DOM2 Events
http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mutationevents

DOM3 Events
http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-eventgroupings-mutationevents

but it sounds like you want a sort of "watch" construct. No, you can't do that with addEventListener..

alglog 1. February 2007, 22:53

Hi

In the following paragraphs you are talking about capturing phase of an event:
...
the event listener on BODY will run before the onclick on the P tag. The event listener on BODY can choose to stop propagation so that the event will not actually be passed on to the P tag. For example,

document.body.addEventListener( 'click', function(e){ if(confirm('Stop event?'))e.stopPropagation(); }, false );

If the BODY event listener was not a capturing one ...

but the last argument of addEventListener() method above is "false" so event listener is attached for bubbling phase instead of capturing one.

Alexei

hallvors 9. March 2007, 15:05

alexei: thanks for catching that. I've fixed it in the article on dev.opera.com too.

Anonymous 18. September 2009, 11:45

Ziyaretçi writes:

hello i need dragstart event but this not work from opera ?

How to use Quote function:

  1. Select some text
  2. Click on the Quote link

Write a comment

Comment
(BBcode and HTML is turned off for anonymous user comments.)

If you can't read the words, press the small reload icon.


Smilies