2
votes

When using the Javascript method addEventListener(type, listener[, useCapture]) I'm able to set the useCapture flag to true.

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 EventTarget beneath it in the DOM tree.

Is the HTML attribute like onclick="listener();" capturing by default?

1

1 Answers

1
votes

If true, useCapture indicates that the user wishes to initiate capture.

No, it means the event handler is called during the capture (or target) phase of the event cycle rather than the bubbling (or target) phase. This diagram from the UI events spec does a great job of conveying the three phases of an event:

enter image description here

Event attribute vs. addEventListener - is the attribute capturing?

No, when you use the old DOM0 onxyz-attribute-style or property-style event handling, it's like using false for that addEventListener parameter: You're setting a handler for the bubbling (or target) phase, not the capture phase.

Example:

var outer = document.getElementById("outer");
var middle = document.getElementById("middle");
var inner = document.getElementById("inner");
hook(outer, false);
hook(outer, true);
outer.onclick = function() {
  console.log("outer: DOM0");
};
hook(middle, false);
hook(middle, true);
middle.onclick = function() {
  console.log("middle: DOM0");
};
hook(inner, false);
hook(inner, true);
inner.onclick = function() {
  console.log("inner: DOM0");
};

function hook(element, useCapture) {
  element.addEventListener("click", function(e) {
    var type;
    if (this === e.target) {
      type = "target (" + (useCapture ? "capture" : "bubbling") + " handler)";
    } else {
      type = useCapture ? "capture" : "bubbling";
    }
    console.log(this.id + ": " + type);
  }, useCapture);
}
.as-console-wrapper {
  max-height: 100% !important;
}
<div id="outer">
  <div id="middle">
    <div id="inner">
      Click Me
    </div>
  </div>
</div>

That gives us the output:

outer: capture
middle: capture
inner: target (bubbling handler)
inner: target (capture handler)
inner: DOM0
middle: bubbling
middle: DOM0
outer: bubbling
outer: DOM0

Note: The order in which the DOM0 handlers are run relative to the addEventListener(..., ..., false) handlers is not defined. Some browsers run them before, others after.

Output explained:

  1. Capture phase:
    • The event passes through outer, so outer's capture handler is run.
    • It passes through middle, so middle's capture handler is run.
  2. Target phase:
    • The event arrives at inner, so all of inner's target handlers run, in the order in which they were attached. So we see inner: target (bubbling handler) then inner: target (capture handler) because we hoooked the bubbling handler before hooking the capture handler. (I did that to emphasize that the target phase is neither bubbling nor capturing, but its own thing, and fires both capture and bubbling handlers.)
    • The DOM0 handler for inner is run (some browsers would do this before the handlers above).
  3. Bubbling phase
    • The event bubbles to middle, so middle's bubbling handler is run, and then its DOM0 handler (some browsers would fire the DOM0 handler first)
    • The event bubbles to outer, to outer's bubbling handler is run, and then its DOM0 handler (again, the order varies by browser).