Unable to understand useCapture parameter in addEventListener

Unable to understand useCapture parameter in addEventListener

I have read article at https://developer.mozilla.org/en/DOM/element.addEventListener but unable to understand useCapture attribute. Definition there is:

If true, useCapture indicates that the user wishes to initiate capture. After initiating capture, all events of the specified type will be dispatched to the registered listener before being dispatched to any EventTargets beneath it in the DOM tree. Events which are bubbling upward through the tree will not trigger a listener designated to use capture.

In this code parent event triggers before child,so I am not able to understand its
behavior.Document object has usecapture true and child div has usecapture set false and document usecapture is followed.So why document property is preferred over child.

function load() {
document.addEventListener(“click”, function() {
alert(“parent event”);
}, true);

document.getElementById(“div1”).addEventListener(“click”, function() {
alert(“child event”);
}, false);
}

click me

Solutions/Answers:

Solution 1:

Events can be activated at two occasions: At the beginning (“capture”), and at the end (“bubble”).

Events are executed in the order of how they’re defined. Say, you define 4 event listeners:

window.addEventListener("click", function(){alert(1)}, false);
window.addEventListener("click", function(){alert(2)}, true);
window.addEventListener("click", function(){alert(3)}, false);
window.addEventListener("click", function(){alert(4)}, true);

The alert boxes will pop up in this order:

  • 2 (defined first, using capture=true)
  • 4 (defined second using capture=true)
  • 1 (first defined event with capture=false)
  • 3 (second defined event with capture=false)

Solution 2:

I find this diagram is very useful for understanding the capture/target/bubble phases:
http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases

Below, content extracted from the link.

Phases

The event is dispatched following a path from the root of the tree to this target node. It can then be handled locally at the target node level or from any target’s ancestors higher in the tree. The event dispatching (also called event propagation) occurs in three phases and the following order:

  1. The capture phase: the event is dispatched to the target’s ancestors
    from the root of the tree to the direct parent of the target node.
  2. The target phase: the event is dispatched to the target node.
  3. The bubbling phase: the event is dispatched to the target’s
    ancestors from the direct parent of the target node to the root of
    the tree.

graphical representation of an event dispatched in a DOM tree using the DOM event flow

The target’s ancestors are determined before the initial dispatch of the event. If the target node is removed during the dispatching, or a target’s ancestor is added or removed, the event propagation will always be based on the target node and the target’s ancestors determined before the dispatch.

Some events may not necessarily accomplish the three phases of the DOM event flow, e.g. the event could only be defined for one or two phases. As an example, events defined in this specification will always accomplish the capture and target phases but some will not accomplish the bubbling phase (“bubbling events” versus “non-bubbling events”, see also the Event.bubbles attribute).

Solution 3:

Capture Event (useCapture = true) vs Bubble Event (useCapture = false)

MDN Reference

  • Capture Event will be dispatch before Bubble Event
  • Event propagation order is
    1. Parent Capture
    2. Children Capture
    3. Target Capture and Target Bubble
      • In the order they were registered
      • When the element is the target of the event, useCapture parameter doesn’t matter (Thanks @bam and @legend80s)
    4. Children Bubble
    5. Parent Bubble
  • stopPropagation() will stop the flow

use Capture flow

Demo

Result:

  1. Parent Capture
  2. Children Bubble 1
  3. Children Capture

    (Because Children is target, so Capture and Bubble will trigger in the order they were registered)

  4. Children Bubble 2
  5. Parent Bubble
var parent = document.getElementById('parent'),
    children = document.getElementById('children');

children.addEventListener('click', function (e) { 
    alert('Children Bubble 1');
    // e.stopPropagation();
}, false);

children.addEventListener('click', function (e) { 
    alert('Children Capture');
    // e.stopPropagation();
}, true);

children.addEventListener('click', function (e) { 
    alert('Children Bubble 2');
    // e.stopPropagation();
}, false);

parent.addEventListener('click', function (e) { 
    alert('Parent Capture');
    // e.stopPropagation();
}, true);

parent.addEventListener('click', function (e) { 
    alert('Parent Bubble');
    // e.stopPropagation();
}, false);
<div id="parent">
    <div id="children">
        Click
    </div>
</div>

Solution 4:

When you say useCapture = true the Events execute top to down in the capture phase when false it does a bubble bottom to top.

Solution 5:

Code example:

<div id="div1" style="background:#9595FF">
  Outer Div<br />
  <div id="div2" style="background:#FFFFFF">
    Inner Div
  </div>
</div>

Javascript code:

d1 = document.getElementById("div1");
d2 = document.getElementById("div2");

if both are set to false

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);

Executes: Onclicking Inner Div, alerts are displayed as:
Div 2 > Div 1

Here the script is executed from the inner element: Event Bubbling (useCapture has been set to false)

div 1 is set to true and div 2 set to false

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);

Executes: Onclicking Inner Div, alerts are displayed as:
Div 1 > Div 2

Here the script is executed from the ancestor / outer element: Event Capturing (useCapture has been set to true)

div 1 is set to false and div 2 set to true

d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);

Executes: Onclicking Inner Div, alerts are displayed as:
Div 2 > Div 1

Here the script is executed from the inner element: Event Bubbling (useCapture has been set to false)

div 1 is set to true and div 2 set to true

d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);

Executes: Onclicking Inner Div, alerts are displayed as:
Div 1 > Div 2

Here the script is executed from the ancestor / outer element: Event Capturing since useCapture has been set to true

Solution 6:

It’s all about event models: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow
You can catch event in bubbling phase or in capturing phase. Your choice.
Take a look at http://www.quirksmode.org/js/events_order.html – you’ll find it very useful.