jquery stop child triggering parent event
Asked Answered
D

7

241

I have a div which I have attached an onclick event to. in this div there is a tag with a link. When I click the link the onclick event from the div is also triggered. How can i disable this so that if the link is clicked on the div onclick is not fired?

script:

$(document).ready(function(){
    $(".header").bind("click", function(){
         $(this).children(".children").toggle();
    });
})

html code:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>
Devalue answered 2/3, 2010 at 16:12 Comment(0)
R
448

Do this:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        e.stopPropagation();
   });
});

If you want to read more on .stopPropagation(), look here.

Ryon answered 2/3, 2010 at 16:13 Comment(7)
if it helps somebody, I replaced $(".header a") with $(".header *") and got any child selected (div, forms, input, etc).Taillight
e.stopPropagation(); must be written at first line, unless it doesn't work!Kries
That is no matter where is e.stopPropagation @ehsan. If you have to jscript click event it will work but e.stopPropagation not work when a link <a> is the parent of element that has click event. Just e.prevent default and return false are work.Scientist
sadly this method preventing the rel configured lightbox to functionLilylilyan
The answer below by xr280xr is much better, as it doesn't interfere with possible events of the children.Sherborne
You create more problems than you solve. Imagine third party plugins listening to click event on document element. They will never know about those clicks. See the comment about lightbox.Reflux
I need e.preventDefault(); too. So ended up with e.stopPropagation(); e.preventDefault();Drummond
E
127

Or, rather than having an extra event handler to prevent another handler, you can use the Event Object argument passed to your click event handler to determine whether a child was clicked. target will be the clicked element and currentTarget will be the .header div:

$(".header").click(function(e){
     //Do nothing if .header was not directly clicked
     if(e.target !== e.currentTarget) return;

     $(this).children(".children").toggle();
});
Essentialism answered 26/4, 2016 at 22:22 Comment(9)
To me this is a more elegant solution since you don't have to add an explicit preventDefault() to every child element.Karlmarxstadt
And it works if you have independent events on child unlike the accepted answer. Definitely cleaner and better solutionHomecoming
In most circumstances you will not care about this, but if for whatever reason you need to support IE6-8, they do not have currentTarget. A workaround is to replace it with this, as suggested in another answer.Sherborne
This is a cleaner solution than setting an extra listener to just catch clicks.Calculated
this code worked better for me` var target=$(e.target); if(!target.is("span")) return;`Progress
Brilliant! Live saver :-)Schwinn
This worked great for me. in my case, I had a menu that had 100% page height in mobile. view on the ul. I wanted to collapse my menu if someone tapped the ul, but it was also triggering the collapse when an li was tapped. This prevented that.Atwater
I used this target method on a mobile side nav to enable closing the menu when clicked outside of the nav. The problem I had was clicking inside the menu closed the nav. Oh no! This solved that too!Swingeing
This will not work if you have other elements inside of header that SHOULD be handled by the header click event. The event.target will be whatever element was directly under the cursor. Thus the event will not fire.Ailanthus
A
25

Better way by using on() with chaining like,

$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});
Anselmi answered 23/7, 2015 at 10:34 Comment(1)
@Essentialism - sorry, I confused it with .net, where returning false from an event handler is one way to terminate propagation. I've deleted my incorrect comment.Persona
E
7

I stumbled upon this question, looking for another answer.

I wanted to prevent all children from triggering the parent.

JavaScript:

document.getElementById("parent").addEventListener("click", function (e) {
    if (this !== event.target) return;
    // Do something
});

jQuery:

$("#parent").click(function () {
    // Do something
}).children().on("click", function (e) {
    e.stopPropagation();
});
Effulgence answered 20/2, 2018 at 22:9 Comment(1)
The first part is similar to [xr280xr's] earlier answer, but using plain javascript. The second code snippet has the same limitation/flaw as the accepted answer (see comments there) - instead use the technique shown in first code snippet - see xr280xr's answer for how that better technique looks with jquery.Persona
F
4

The answers here took the OP's question too literally. How can these answers be expanded into a scenario where there are MANY child elements, not just a single <a> tag? Here's one way.

Let's say you have a photo gallery with a blacked out background and the photos centered in the browser. When you click the black background (but not anything inside of it) you want the overlay to close.

Here's some possible HTML:

<div class="gallery" style="background: black">
    <div class="contents"> <!-- Let's say this div is 50% wide and centered -->
        <h1>Awesome Photos</h1>
        <img src="img1.jpg"><br>
        <img src="img2.jpg"><br>
        <img src="img3.jpg"><br>
        <img src="img4.jpg"><br>
        <img src="img5.jpg">
    </div>
</div>

And here's how the JavaScript would work:

$('.gallery').click(
    function()
    {
        $(this).hide();
    }
);

$('.gallery > .contents').click(
    function(e) {
        e.stopPropagation();
    }
);

This will stop the click events from elements inside .contents from every research .gallery so the gallery will close only when you click in the faded black background area, but not when you click in the content area. This can be applied to many different scenarios.

Foxy answered 15/10, 2015 at 1:59 Comment(0)
E
3

The simplest solution is to add this CSS to the children:

.your-child {
    pointer-events: none;
}
Epicycle answered 30/4, 2018 at 16:29 Comment(2)
I needed this for the unwanted font tag added by Wordpress and it worked for meHarl
This is easiest way I foundRetaretable
S
0

Or this:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});
Siberia answered 13/3, 2013 at 18:37 Comment(3)
@Halcyon991 e gets passed in either way through arguments, e is just a referenceInhabited
@Inhabited Yeah, but a needless character addition if it's not used.Lucialucian
No point adding return false to link, it should be clickable.Lilylilyan

© 2022 - 2024 — McMap. All rights reserved.