Home > Net >  Click Triggers Event Listener That It Creates
Click Triggers Event Listener That It Creates

Time:01-28

In the following example, why does a single click on the button not only trigger the event listener that is added to the button, but also the event listener that gets added to the body? In other words: Why does the color change to red instead of green? And how do you prevent this?

$("button").on("click", function() {
  // Change Color
  $("body").css({
    "background-color": "#3FE1B0"
  });
  // Add New Event Listener...
  $("body").on("click", function() {
    // ...Which Also Changes Color
    $(this).css({
      "background-color": "#FF4F5E"
    });
  });
});
/* Design Changes */
body {
  height: 100vh;
  margin: 0;
  
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

<button>Click Me!</button>

CodePudding user response:

You problem is event propagation. What happens when the user clicks the button with your original code is:

  • the event handler fires and changes the background color to the one you specify (#3FE1B0)
  • the event handler is also added to the body to change the color to #FF4F5E
  • the event propagates up to its parent elements, including, at the end of the chain, the body
  • so the event handler on the body runs (the fact that it was only just added makes no difference), so the color changes to the one you don't want yet

The solution is simple: use the event's stopPropagation method to stop it propagating upwards:

$("button").on("click", function(event) {
  // Change Color
  $("body").css({
    "background-color": "#3FE1B0"
  });
  // Add New Event Listener...
  $("body").on("click", function() {
    // ...Which Also Changes Color
    $(this).css({
      "background-color": "#FF4F5E"
    });
  });
  event.stopPropagation();
});
/* Design Changes */
body {
  height: 100vh;
  margin: 0;
  
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

<button>Click Me!</button>

CodePudding user response:

One source of the problem is that clicking the <button> inside the <body> fires the click event for both the <body> element and the <button> element. You need to use event.stopPropagation() to prevents the event from bubbling up the DOM tree.

$("button").on("click", function(e) {
  $("body").css({ "background-color": "#3FE1B0" });
  e.stopPropagation();
});

$("body").on("click", function(e) {
    $("body").css({ "background-color": "#FF4F5E" });
});
body {
  height: 100vh;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <title>Page Title</title>
</head>
<body>
  <button>Click Me!</button>
</body>
</html>

CodePudding user response:

First, you should rearrange your code.

Second, use stopPropagation to prevent both click handlers from being triggered.

Try the example below:

$("body").on("click", function(e) {
  $(this).css({
    "background-color": "#FF4F5E"
  });
});

$("button").on("click", function(e) {
  e.stopPropagation()
  $("body").css({
    "background-color": "#3FE1B0"
  });
});
/* Design Changes */

body {
  height: 100vh;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

<button>Click Me!</button>

  •  Tags:  
  • Related