jquery stop enfant déclenchant l'événement parent

208

J'ai une div à laquelle j'ai attaché un onclickévénement. dans cette div, il y a une balise avec un lien. Lorsque je clique sur le lien, l' onclickévénement du div est également déclenché. Comment puis-je désactiver cela afin que si le lien est cliqué sur le div onclickne soit pas tiré?

scénario:

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

Code HTML:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>
John
la source

Réponses:

412

Faites ceci:

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

Si vous souhaitez en savoir plus sur .stopPropagation (), regardez ici .

Nick Craver
la source
2
si cela aide quelqu'un, j'ai remplacé $(".header a")par $(".header *")et j'ai sélectionné un enfant (div, formulaires, entrée, etc.).
aldo.roman.nurena
1
e.stopPropagation (); doit être écrit en première ligne, sauf si cela ne fonctionne pas!
ehsan
2
malheureusement cette méthode empêchant la rellightbox configurée de fonctionner
eapo
5
La réponse ci-dessous par xr280xr est bien meilleure, car elle n'interfère pas avec les événements possibles des enfants.
Alexander Jank
1
Vous créez plus de problèmes que vous n'en résolvez. Imaginez des plugins tiers écoutant l'événement click sur l'élément du document. Ils ne sauront jamais ces clics. Voir le commentaire sur la lightbox.
Salman A
100

Ou, plutôt que d'avoir un gestionnaire d'événements supplémentaire pour empêcher un autre gestionnaire, vous pouvez utiliser l' argument Objet d'événement transmis à votre gestionnaire d'événements click pour déterminer si un enfant a été cliqué. targetsera l'élément cliqué et currentTargetsera le div .header:

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

     $(this).children(".children").toggle();
});
xr280xr
la source
8
Pour moi, c'est une solution plus élégante car vous n'avez pas besoin d'ajouter un preventDefault () explicite à chaque élément enfant.
Ryan Griggs
5
Et cela fonctionne si vous avez des événements indépendants sur l'enfant contrairement à la réponse acceptée. Solution
nettement
2
Dans la plupart des cas, vous ne vous en soucierez pascurrentTarget , mais si pour une raison quelconque vous devez prendre en charge IE6-8, ils ne l'ont pas . Une solution de contournement consiste à le remplacer par this, comme suggéré dans une autre réponse .
Alexander Jank
Il s'agit d'une solution plus propre que de configurer un écouteur supplémentaire pour simplement attraper les clics.
Micros
ce code a mieux fonctionné pour moi` var target = $ (e.target); if (! target.is ("span")) return; `
Cr1xus
17

Meilleur moyen en utilisant on () avec un chaînage comme,

$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});
Rohan Kumar
la source
4

Les réponses ici ont pris la question du PO trop littéralement. Comment ces réponses peuvent-elles être développées dans un scénario où il y a BEAUCOUP d'éléments enfants, pas seulement une seule <a>balise? Voici une façon.

Disons que vous avez une galerie de photos avec un arrière-plan noirci et les photos centrées dans le navigateur. Lorsque vous cliquez sur l'arrière-plan noir (mais pas sur rien à l'intérieur), vous souhaitez que la superposition se ferme.

Voici quelques HTML possibles:

<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>

Et voici comment le JavaScript fonctionnerait:

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

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

Cela arrêtera les événements de clic des éléments à l'intérieur .contentsde chaque recherche .galleryafin que la galerie se ferme uniquement lorsque vous cliquez dans la zone d'arrière-plan noir délavé, mais pas lorsque vous cliquez dans la zone de contenu. Cela peut être appliqué à de nombreux scénarios différents.

Gavin
la source
4

Je suis tombé sur cette question, à la recherche d'une autre réponse.

Je voulais empêcher tous les enfants de déclencher le 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();
});
Daan
la source
0

Ou ca:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});
user719004
la source
2
@ Halcyon991 e est transmis dans les deux sens par le biais d'arguments, e n'est qu'une référence
qodeninja
@qodeninja Oui, mais un ajout de caractère inutile s'il n'est pas utilisé.
Halcyon991
Inutile d'ajouter un return falselien, il doit être cliquable.
eapo
0

La solution la plus simple consiste à ajouter ce CSS aux enfants:

.your-child {
    pointer-events: none;
}
Jetée
la source
J'en avais besoin pour la balise de police indésirable ajoutée par Wordpress et cela a fonctionné pour moi
Ndm Gjr
-1

Un moyen plus court de le faire:

$('.header').on('click', function () {
    $(this).children('a').on('click', function(e) {
        e.stopPropagation();
        $(this).siblings('.children').toggle();
    });
});
Andreas 'aNdy' Berggreen
la source
Mais ... Cela ne fait rien en cliquant sur l'en-tête.
Liora Haydont
Chaque fois que vous cliquez sur l'en-tête, cela ajoute un nouvel événement de clic aux enfants («a»).
Frank Forte