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.

Advertisements

9 thoughts on “event capture explained

  1. 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 !

  2. HiIn 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s