206

I have a checkbox that I want to perform some Ajax action on the click event, however the checkbox is also inside a container with its own click behaviour that I don't want to run when the checkbox is clicked. This sample illustrates what I want to do:

$(document).ready(function() {
  $('#container').addClass('hidden');
  $('#header').click(function() {
    if ($('#container').hasClass('hidden')) {
      $('#container').removeClass('hidden');
    } else {
      $('#container').addClass('hidden');
    }
  });
  $('#header input[type=checkbox]').click(function(event) {
    // Do something
  });
});
#container.hidden #body {
  display: none;
}
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<div id="container">
  <div id="header">
    <h1>Title</h1>
    <input type="checkbox" name="test" />
  </div>
  <div id="body">
    <p>Some content</p>
  </div>
</div>

However, I can't figure out how to stop the event bubbling without causing the default click behaviour (checkbox becoming checked/unchecked) to not run.

Both of the following stop the event bubbling but also don't change the checkbox state:

event.preventDefault();
return false;
danronmoon
  • 3,814
  • 5
  • 34
  • 56
roryf
  • 29,592
  • 16
  • 81
  • 103
  • 2
    I found an article on this matter that might be helpful to other Stack Overflowers. [Quick Tip: Click Table Row to Trigger a Checkbox Click](http://www.learningjquery.com/2008/12/quick-tip-click-table-row-to-trigger-a-checkbox-click) – Peder Rice Jan 19 '10 at 21:17

9 Answers9

378

replace

event.preventDefault();
return false;

with

event.stopPropagation();

event.stopPropagation()

Stops the bubbling of an event to parent elements, preventing any parent handlers from being notified of the event.

event.preventDefault()

Prevents the browser from executing the default action. Use the method isDefaultPrevented to know whether this method was ever called (on that event object).

rahul
  • 184,426
  • 49
  • 232
  • 263
  • 6
    for some reason this doesn't work for me, but return false did. – Randy L Nov 15 '10 at 09:01
  • 3
    If you are binding the event using `.live()` method then this will not work. You will have to use `return false;` itself. – rahul Nov 15 '10 at 09:07
  • 2
    This works using jQuery's `.on()` method (live is now deprecated). I could not figure out why return false wasn't working. – styfle Feb 17 '12 at 20:46
  • i spent quite a while to figure out that event.preventDefault() was not showing the check mark in IE8, but worked well in other browsers. I found this answer after I fixed and then googling with preventDefault,IE8, checkbox as keyword, brought me here. – signonsridhar Mar 22 '13 at 18:58
  • did'nt work for.. but this two line did(without return false) --> event.preventDefault(); event.stopPropagation(); – Kugan Kumar May 22 '17 at 09:04
  • keeping event.preventDefault() along with event.stopPropagation() is what fixed it for me. Otherwise I was getting two click events each time. I'm using materializecss in Rails 5 which may be effecting things – Randall Coding Dec 03 '19 at 17:45
33

Use the stopPropagation method:

event.stopPropagation();
Patrice Neff
  • 1,444
  • 11
  • 13
30

Don't forget IE:

if (event.stopPropagation) {    // standard
        event.stopPropagation();
    } else {    // IE6-8
        event.cancelBubble = true;
}
Faraz Kelhini
  • 3,925
  • 32
  • 38
6

As others have mentioned, try stopPropagation().

And there is a second handler to try: event.cancelBubble = true; It's a IE specific handler, but it is supported in at least FF. Don't really know much about it, as I haven't used it myself, but it might be worth a shot, if all else fails.

peirix
  • 36,512
  • 23
  • 96
  • 126
6

When using jQuery you do not need to call a stop function separate.

You can just return false in the event handler

This will stop the event and cancel bubbling..

Also see event.preventDefault() vs. return false

From the jQuery docs:

These handlers, therefore, may prevent the delegated handler from triggering by calling event.stopPropagation() or returning false.

Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
DutchKevv
  • 1,659
  • 2
  • 22
  • 39
5

This is an excellent example for understanding event bubbling concept. Based on the above answers, the final code will look like as mentioned below. Where the user Clicks on checkbox the event propagation to its parent element 'header' will be stopped using event.stopPropagation();.

$(document).ready(function() {
            $('#container').addClass('hidden');
            $('#header').click(function() {
                if($('#container').hasClass('hidden')) {
                    $('#container').removeClass('hidden');
                } else {
                    $('#container').addClass('hidden');
                }
            });
          $('#header input[type=checkbox]').click(function(event) {
              if (event.stopPropagation) {    // standard
                   event.stopPropagation();
               } else {    // IE6-8
                    event.cancelBubble = true;
               }
          });     
  });
mehras
  • 51
  • 1
  • 4
2

Credit to @mehras for the code. I just created a snippet to demonstrate it because I thought that would be appreciated and I wanted an excuse to try that feature.

$(document).ready(function() {
  $('#container').addClass('hidden');
  $('#header').click(function() {
    if ($('#container').hasClass('hidden')) {
      $('#container').removeClass('hidden');
    } else {
      $('#container').addClass('hidden');
    }
  });
  $('#header input[type=checkbox]').click(function(event) {
    if (event.stopPropagation) { // standard
      event.stopPropagation();
    } else { // IE6-8
      event.cancelBubble = true;
    }
  });
});
div {
  text-align: center;
  padding: 2em;
  font-size: 1.2em
}

.hidden {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="header"><input type="checkbox" />Checkbox won't bubble the event, but this text will.</div>
<div id="container">click() bubbled up!</div>
Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
user2503764
  • 121
  • 1
  • 3
2

Here's a trick that worked for me:

handleClick = e => {
    if (e.target === e.currentTarget) {
        // do something
    } else {
        // do something else
    }
}

Explanation: I attached handleClick to a backdrop of a modal window, but it also fired on every click inside of a modal window (because it was IN the backdrop div). So I added the condition (e.target === e.currentTarget), which is only fulfilled when a backdrop is clicked.

1

In angularjs this should works:

event.preventDefault(); 
event.stopPropagation();
Kugan Kumar
  • 423
  • 1
  • 8
  • 14