jquery stop potomek wyzwala zdarzenie nadrzędne

208

Mam div, do którego przypisałem onclickwydarzenie. w tym div znajduje się tag z linkiem. Kiedy kliknę link, onclickwywołane zostanie również zdarzenie z div. Jak mogę to wyłączyć, aby kliknięcie linku na div onclicknie było uruchamiane?

scenariusz:

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

Kod HTML:

<div class="header">
    <a href="link.html">some link</a>
    <ul class="children">
        <li>some list</li>
    </ul>
</div>
Jan
źródło

Odpowiedzi:

411

Zrób to:

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

Jeśli chcesz przeczytać więcej na temat .stopPropagation (), spójrz tutaj .

Nick Craver
źródło
2
czy to pomaga kogoś, wymieniłem $(".header a")z $(".header *")i dostał Każde dziecko wybiera (div, formularze, wejście, etc).
aldo.roman.nurena
1
e.stopPropagation (); musi być napisane w pierwszej linii, chyba że to nie działa!
ehsan
2
niestety ta metoda uniemożliwia działanie relskonfigurowanego
lightboksa
5
Poniższa odpowiedź autorstwa xr280xr jest znacznie lepsza, ponieważ nie koliduje z możliwymi zdarzeniami dzieci.
Alexander Jank
1
Tworzysz więcej problemów niż rozwiązujesz. Wyobraź sobie, że wtyczki innych firm nasłuchują zdarzenia kliknięcia na elemencie dokumentu. Nigdy nie dowiedzą się o tych kliknięciach. Zobacz komentarz na temat lightbox.
Salman A
100

Lub zamiast posiadania dodatkowej procedury obsługi zdarzeń w celu zapobieżenia innej procedurze obsługi, możesz użyć argumentu Obiekt zdarzenia przekazanego do procedury obsługi zdarzenia kliknięcia, aby ustalić, czy dziecko zostało kliknięte. targetbędzie klikniętym elementem i currentTargetbędzie 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
źródło
8
Dla mnie jest to bardziej eleganckie rozwiązanie, ponieważ nie musisz dodawać jawnego zapobieganiaDefault () do każdego elementu potomnego.
Ryan Griggs
5
I działa, jeśli masz niezależne wydarzenia na dziecku w przeciwieństwie do zaakceptowanej odpowiedzi. Zdecydowanie czystsze i lepsze rozwiązanie
BozanicJosip
2
W większości przypadków nie będziesz się tym przejmować, ale jeśli z jakiegoś powodu potrzebujesz obsługi IE6-8, nie mającurrentTarget . Obejściem tego problemu jest zastąpienie go this, jak sugerowano w innej odpowiedzi .
Alexander Jank
Jest to czystsze rozwiązanie niż ustawianie dodatkowego odbiornika, aby po prostu łapał kliknięcia.
Micros
ten kod działał dla mnie lepiej var var = $ (e.target); if (! target.is ("span")) return; `
Cr1xus
17

Lepszy sposób, używając on () z łańcuchami typu,

$(document).ready(function(){
    $(".header").on('click',function(){
        $(this).children(".children").toggle();
    }).on('click','a',function(e) {
        e.stopPropagation();
   });
});
Rohan Kumar
źródło
4

Odpowiedzi tutaj przyjęły pytanie OP zbyt dosłownie. Jak te odpowiedzi można rozwinąć w scenariusz, w którym WIELE elementów potomnych, a nie tylko jednego <a>znacznika? Oto jeden sposób.

Załóżmy, że masz galerię zdjęć z zaciemnionym tłem i zdjęciami wyśrodkowanymi w przeglądarce. Po kliknięciu czarnego tła (ale niczego w nim) nie chcesz, aby nakładka została zamknięta.

Oto kilka możliwych 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>

A oto jak działa JavaScript:

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

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

To zatrzyma zdarzenia kliknięcia z elementów wewnątrz .contentskażdego badania, .gallerywięc galeria zostanie zamknięta tylko po kliknięciu wyblakłego czarnego obszaru tła, ale nie po kliknięciu w obszarze zawartości. Można to zastosować do wielu różnych scenariuszy.

Gavin
źródło
4

Natknąłem się na to pytanie, szukając innej odpowiedzi.

Chciałem uniemożliwić wszystkim dzieciom wyzwolenie rodzica.

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
źródło
0

Albo to:

$(document).ready(function(){
    $(".header").click(function(){
        $(this).children(".children").toggle();
    });
   $(".header a").click(function(e) {
        return false;
   });
});
użytkownik719004
źródło
2
@ Halcyon991 e jest przekazywany w jakikolwiek sposób przez argumenty, e to tylko odniesienie
qodeninja
@qodeninja Tak, ale niepotrzebny dodatek postaci, jeśli nie jest używany.
Halcyon991
Nie ma sensu dodawać return falselinku, powinien być klikalny.
eapo
0

Najprostszym rozwiązaniem jest dodanie tego CSS do dzieci:

.your-child {
    pointer-events: none;
}
Molo
źródło
Potrzebowałem tego do niechcianego tagu czcionki dodanego przez Wordpress i zadziałało to dla mnie
Ndm Gjr
-1

Krótszy sposób, aby to zrobić:

$('.header').on('click', function () {
    $(this).children('a').on('click', function(e) {
        e.stopPropagation();
        $(this).siblings('.children').toggle();
    });
});
Andreas „aNdy” Berggreen
źródło
Ale ... To nic nie robi po kliknięciu nagłówka.
Liora Haydont,
Każde kliknięcie nagłówka powoduje dodanie nowego zdarzenia kliknięcia do dzieci („a”).
Frank Forte