3

In the following code, I can't tell why my console prints 'hi' when I click on a button with the class 'edit-button' for the first time. The second time I'm expecting it to print the console because the 'update-now' class has been added to the button. Does anyone understand why this is? Thanks!

$(function() {
    $('.edit-button').on('click', function(e) {
      $( this ).addClass('update-now').html('Update');
    });
});



$(document).on('click', "div.update-now", function() {      
    console.log('hi');
});
Tom
  • 1,215
  • 3
  • 19
  • 30
  • 1
    Post a complete code example please, including your HTML. – j08691 Mar 16 '16 at 20:08
  • FWIW, I took the time to put together jsFiddle demonstrating the issue: https://jsfiddle.net/2v8bcqv4/ – BenM Mar 16 '16 at 20:09
  • Your first click event is bind to some button the second on the document. So at the time the document listener is called the button already has the class. – Roland Starke Mar 16 '16 at 20:10
  • 1
    @RolandStarke No, the second `click` event is delegated to `div.update-now` elements. – BenM Mar 16 '16 at 20:11
  • It's executing the first click event before the second one, therefore it's adding the class, and then checking the class on the second click handler, which is coming back true, obviously – mhodges Mar 16 '16 at 20:13
  • @RolandStarke I don't know what your point is? The event is delegated, and similarly from the jQuery docs: *The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector.* – BenM Mar 16 '16 at 20:55
  • @BenM take a look at http://stackoverflow.com/a/15112421/5378743 he explains in his first example the event is bound to the div. So in the code we have here it is bound to document. But you sad "No" to that claim. – Roland Starke Mar 16 '16 at 21:10

1 Answers1

4

This is happening because of event propagation. Basically event delegation works with the use of event bubbling. Now in your case, you bound an event to .update-now by using event delegation signature.

And you are adding a class update-now to another one button inside its click event, so that event propagates until it meets the document and after that it will investigate who raised the event. Here div with class update-now has started the propagation. So the event handler got triggered and prints hi in the console.

So if you stop the propagation after/before adding the class update-now, the hi message will not be printed,

$('.edit-button').on('click', function(e) {
  $( this ).addClass('update-now').html('Update');
  e.stopPropagation()
});

DEMO

A solution for your case that i would suggest,

$('.edit-button').on('click', function(e) {
  $( this ).addClass('update-now').html('Update');
  $(this).off("click");
  e.stopPropagation();
});

$('body').on('click', ".edit-button.update-now", function() {      
  alert('hi');
});

DEMO

Rajaprabhu Aravindasamy
  • 66,513
  • 17
  • 101
  • 130
  • Except the `alert` is never triggered now, since the event does not propagate to `body`. (Try clicking the same element after its innerHTML is updated. – BenM Mar 16 '16 at 20:16
  • Using stopPropagation() stops the alert from happening always. You need to check to see if $(this) contains the update-now class - if so, do not stop the propagation – mhodges Mar 16 '16 at 20:17
  • @mhodges I have given an explanation on why that `hi` was alerted. we can fix it in various ways. :) – Rajaprabhu Aravindasamy Mar 16 '16 at 20:18
  • @RajaprabhuAravindasamy Please try your code. Click the "Update" text afterwards and see what happens. The `alert()` does not trigger: https://jsfiddle.net/2v8bcqv4/2/ – BenM Mar 16 '16 at 20:20
  • @RajaprabhuAravindasamy Rather confusing to an OP to give an answer that breaks what they are trying to do, without proposing a solution. – mhodges Mar 16 '16 at 20:20
  • @RajaprabhuAravindasamy Perfectly valid as well, there are a million ways to skin this cat, I just wanted to make sure the OP got a solution ;) – mhodges Mar 16 '16 at 20:24
  • 1
    @mhodges And i saw your edit, Why do we need to pull that unnecessary event listener with us. Right? – Rajaprabhu Aravindasamy Mar 16 '16 at 20:25
  • If that is all the listener is doing, agreed 100%. Hard to tell what the OP's full code looks like with just a minimal code example demonstrating the issue. If the original listener does other things, it needs to stick around. – mhodges Mar 16 '16 at 20:27