JavaScript click() function and propagation

174 Views Asked by At

I'm curious why this simple code does not run indefinitely. After reading Eloquent JavaScript, it says that the immediate nodes will execute first, and then the outer nodes will, in turn, execute their click event listeners. However, the code below only gives these 7 lines as output. It seems as if lines 5 and 6 would fire the click listener on the container again. Perhaps I am not understanding something about propagation. I've tried debugging using Visual Studio and it does not enter the function, but I cannot find a way to determine why this is using the debugger. Thanks for the help.

  1. "body clicked"
  2. "container clicked"
  3. "item clicked"
  4. "container clicked"
  5. "body clicked"
  6. "body clicked"

const container = document.getElementById("container");
const item = document.getElementById("item");
const body = document.getElementById("body");

item.addEventListener("click", function () {
  console.log("item clicked");
});

container.addEventListener("click", function () {
  console.log("container clicked");
  item.click();
});

body.addEventListener("click", function () {
  console.log("body clicked");
  container.click();
});
body {
  background: yellow;
}

div.container {
  width: 200px;
  height: 200px;
  background: aqua;
  border: 1px solid black;
}

 div.item {
  width: 100px;
  height: 100px;
  background: gray;
  border: 1px solid red;
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>My website</title>
        <link rel="stylesheet" href="site.css">
    </head>
    <body id="body">body
        <div class="container" id="container">container
            <div class="item" id="item">item</div>
        </div>
        <script src="site.js"></script>
    </body>
</html>

1

There are 1 best solutions below

0
Scott Marcus On

As @pilchard pointed out in the comments, calling the click() method of an element will only invoke that element's click event handling function (no different than directly calling the function by its name), but it won't trigger an actual click event.

Below, I've commented out those calls and you are left with being able to clearly see that a mouse click does trigger the event and how that event will bubble up through the clicked element's ancestor elements.

const container = document.getElementById("container");
const item = document.getElementById("item");
const body = document.getElementById("body");

item.addEventListener("click", function () {
  console.log("item clicked");
});

container.addEventListener("click", function () {
  console.log("container clicked");
  //item.click();
});

body.addEventListener("click", function () {
  console.log("body clicked");
  //container.click();
});
body {
  background: yellow;
}

div.container {
  width: 200px;
  height: 200px;
  background: aqua;
  border: 1px solid black;
}

 div.item {
  width: 100px;
  height: 100px;
  background: gray;
  border: 1px solid red;
}
<body id="body">body
  <div class="container" id="container">container
     <div class="item" id="item">item</div>
  </div>
</body>