skip to Main Content

Please tell me why the e.stopPropagation() function does not work?

$(document).ready(function() {
  var el = '<div class="el" onclick="alert(1);"><div class="stop">X</div>Click</div>';
  $("body").append(el);
})
$(document).on("click", ".stop", function(e) {
  e.stopPropagation();
  e.preventDefault();
  alert(2);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
</body>

2

Answers


  1. why the e.stopPropagation() function does not work?

    It does work. Observe:

    $(document).on("click", ".outer", function(e) {
      alert(3);
    });
    
    $(document).on("click", ".el", function(e) {
      e.stopPropagation();
      alert(2);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="outer">
      <div class="el" onclick="alert(1)";>Click</div>
    </div>

    In your code the event propagation is indeed being stopped. However, there are no further event handlers up the DOM tree so there’s no propagation to observe in the first place. What you have are two separate click handling events on the same element, both of which are being processed independently.

    In the example shown here, a parent element (div.outer) does have an event handler, and the propagation stops before it reaches that handler. Without stopping propagation, you’d see that event handler invoked:

    $(document).on("click", ".outer", function(e) {
      alert(3);
    });
    
    $(document).on("click", ".el", function(e) {
      alert(2);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="outer">
      <div class="el" onclick="alert(1)";>Click</div>
    </div>

    You might be looking for stopImmediatePropagation() instead? This will prevent further event handlers from being invoked on the same element. For example:

    $(document).on("click", ".el", function(e) {
      e.stopImmediatePropagation();
      alert(2);
    });
    
    $(document).on("click", ".el", function(e) {
      e.stopImmediatePropagation();
      alert(3);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="el" onclick="alert(1)";>Click</div>

    In this case The second click handler on the target element stopped further click handlers on that same element from being processed. Note that this has no effect on the first click handler, which was already invoked by then.


    Edit: Your updated code demonstrates a slightly different problem. (Which was being obscured in the original code by the original problem addressed above.)

    Notice how you are attaching your jQuery event handler. Which DOM object are you attaching it to?… document. Which is much further up the DOM hierarchy and isn’t reached until after the parent element has already processed its inline click handler.

    If you attach a click handler directly to the element, you can see the difference:

    $(".stop").on("click", function(e) {
      e.stopPropagation();
      alert(2);
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="el" onclick="alert(1)">
      <div class="stop">X</div>
      Click
    </div>

    Another edit for the ongoing moving target…

    You’re still essentially running into the same issue. One click handler is on the element itself, another is on the document object. The latter won’t be processed before the former.

    Appending the elements to the DOM after the fact may indeed complicate things a little in this case, and you may need to attach the click handler to the element(s) themselves after appending them. For example, this stops the propagation:

    $(document).ready(function() {
      var el = '<div class="el" onclick="alert(1);"><div class="stop">X</div>Click</div>';
      $("body").append(el);
      
      $(".stop").on("click", function(e) {
        e.stopPropagation();
        alert(2);
      });
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <body>
    </body>

    The key difference here is that the jQuery click handler isn’t being attached to the document or relying on event delegation/propagation in the first place. It’s being attached directly to the target element, and as such needed to be attached after the element is added to the DOM.

    Login or Signup to reply.
  2. First, you made a typo. class only has 2 ss in it.

    That aside, the event starts on the div that you click. It then propagates to the div with the onclick attribute (triggering that), then continues up the DOM until it hits the document object and triggers the event handler bound with jQuery at which point stopPropagation is called and it stops.

    If you want to prevent the onclick attribute triggering then you need to handle the event in the capture phase. I don’t think jQuery supports that so you’ll need to use native DOM instead.

    document.addEventListener("click", function(e) {
      if (!e.target.closest(".stop")) return;
      e.stopPropagation();
      alert(2);
    }, {
      capture: true
    });
    <div class="el" onclick="alert(1)" ;>
      <div class="stop">X</div>
      Click
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search