Event Flow: capture, target, and bubbling

An event has three phases to its life cycle: capture, target, and bubbling.

Capture Phase

The event capture phase is shown in the following image:

eventCapture.png

Bubble Phase

The event bubble phase is shown in the following image:

eventBubble.png

Target Phase

When the capture phase has finished, the browser triggers any listeners for the event type.

Calling the stopPropagation or stopImmediatePropagation functions during the target phase stops the flow of the event and the bubble phase won't be performed.

The following code shows the event capture phase:

 
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<style type="text/css">
p {
  background: gray;
  color: white;
  padding: 10px;
  margin: 5px;
  border: thin solid black
}

span {
  background: white;
  color: black;
  padding: 2px;
  cursor: default;
}
</style>
</head>
<body>
  <p id="block1">
    <span id="mySpan">This is a span. </span>
  </p>
  <script type="text/javascript">
    var mySpan = document.getElementById("mySpan");
    var textblock = document.getElementById("block1");
    mySpan.addEventListener("mouseover", handleMouseEvent);
    mySpan.addEventListener("mouseout", handleMouseEvent);
    textblock.addEventListener("mouseover", handleDescendantEvent, true);
    textblock.addEventListener("mouseout", handleDescendantEvent, true);

    function handleDescendantEvent(e) {
      if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.border = "thin solid red";
        e.currentTarget.style.border = "thick double black";
      } else if (e.type == "mouseout" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.removeProperty("border");
        e.currentTarget.style.removeProperty("border");
      }
    }
    function handleMouseEvent(e) {
      if (e.type == "mouseover") {
        e.target.style.background = 'white';
        e.target.style.color = 'black';
      } else {
        e.target.style.removeProperty('color');
        e.target.style.removeProperty('background');
      }
    }
  </script>
</body>
</html>
  
Click to view the demo

A parent element event handler can stop flow of the event down toward the target by calling the stopPropagation or stopImmediatePropagation.

stopPropagation ensures that all of the event listeners registered for the current element will be invoked. stopImmediatePropagation ignores any untriggered listeners.

 
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<style type="text/css">

span {
  background: white;
  color: black;
  padding: 2px;
  cursor: default;
}
</style>
</head>
<body>
  <p id="block1">
    <span id="mySpan">This is a span. </span>
  </p>
  <script type="text/javascript">
    var mySpan = document.getElementById("mySpan");
    var textblock = document.getElementById("block1");
    
    mySpan.addEventListener("mouseover", handleMouseEvent);
    mySpan.addEventListener("mouseout", handleMouseEvent);
    textblock.addEventListener("mouseover", handleDescendantEvent, true);
    textblock.addEventListener("mouseout", handleDescendantEvent, true);
    
    function handleDescendantEvent(e) {
      if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.border = "thick solid red";
        e.currentTarget.style.border = "thick double black";
      } else if (e.type == "mouseout" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.removeProperty("border");
        e.currentTarget.style.removeProperty("border");
      }
      e.stopPropagation(); 
    }
    function handleMouseEvent(e) {
      if (e.type == "mouseover") {
        e.target.style.background = 'white';
        e.target.style.color = 'black';
      } else {
        e.target.style.removeProperty('color');
        e.target.style.removeProperty('background');
      }
    }
  </script>
</body>
</html>
  
Click to view the demo

The following code shows the event bubble phase:

 
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<style type="text/css">
span {
  background: white;
  color: black;
  padding: 2px;
  cursor: default;
}
</style>
</head>
<body>
  <p id="block1">
    <span id="mySpan">This is a span. </span>
  </p>
  <script type="text/javascript">
    var mySpan = document.getElementById("mySpan");
    var textblock = document.getElementById("block1");
    mySpan.addEventListener("mouseover", handleMouseEvent);
    mySpan.addEventListener("mouseout", handleMouseEvent);
    textblock.addEventListener("mouseover", handleDescendantEvent, true);
    textblock.addEventListener("mouseout", handleDescendantEvent, true);
    textblock.addEventListener("mouseover", handleBubbleMouseEvent, false);
    textblock.addEventListener("mouseout", handleBubbleMouseEvent, false);
    function handleBubbleMouseEvent(e) {
      if (e.type == "mouseover" && e.eventPhase == Event.BUBBLING_PHASE) {
        e.target.style.textTransform = "uppercase";
      } else if (e.type == "mouseout"
          && e.eventPhase == Event.BUBBLING_PHASE) {
        e.target.style.textTransform = "none";
      }
    }
    function handleDescendantEvent(e) {
      if (e.type == "mouseover" && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.border = "thn solid red";
        e.currentTarget.style.background = "blue";
      } else if (e.type == "mouseout"
          && e.eventPhase == Event.CAPTURING_PHASE) {
        e.target.style.removeProperty("border");
        e.currentTarget.style.removeProperty("border");
      }
    }
    function handleMouseEvent(e) {
      if (e.type == "mouseover") {
        e.target.style.background = 'black';
        e.target.style.color = 'white';
      } else {
        e.target.style.removeProperty('color');
        e.target.style.removeProperty('background');
      }
    }
  </script>
</body>
</html>
  
Click to view the demo

Not all events support bubbling. Event bubbles property tells if the event supports bubble. It returns a true/false value.

 
<!DOCTYPE HTML>
<html>
<head>
<title>Example</title>
<style type="text/css">
span {
  background: white;
  color: black;
  padding: 2px;
  cursor: default;
}
</style>
</head>
<body>
  <p id="block1">
    <span id="mySpan">This is a span. </span>
  </p>
  <script type="text/javascript">
    var mySpan = document.getElementById("mySpan");
    var textblock = document.getElementById("block1");
    textblock.addEventListener("mouseover", handleBubbleMouseEvent, false);
    textblock.addEventListener("mouseout", handleBubbleMouseEvent, false);
    function handleBubbleMouseEvent(e) {
        document.writeln(e.bubbles);
    }
  </script>
</body>
</html>
  
Click to view the demo
Home 
  JavaScript Book 
    DOM  

DOM Event:
  1. The DOM Events
  2. Event Flow: capture, target, and bubbling
  3. eventPhase
  4. preventDefault: Cancellable Events
  5. Events Type
  6. Event Target