jQuery: funkcja klikania wyklucz dzieci.

144

Próbuję owinąć głowę wokół funkcji jQuery „.not ()” i napotykam problem. Chciałbym, aby nadrzędny element DIV był „klikalny”, ale jeśli użytkownik kliknie element podrzędny, skrypt nie zostanie wywołany.

$(this).not(children()).click(function(){
   $(".example").fadeOut("fast");
});

html:

<div class="example">
   <div>
      <p>This content is not affected by clicks.</p>
   </div>
</div>
superUntitled
źródło

Odpowiedzi:

198

Aby to zrobić, zatrzymaj kliknięcie dziecka za pomocą .stopPropagation :

$(".example").click(function(){
  $(this).fadeOut("fast");
}).children().click(function(e) {
  return false;
});

Zapobiegnie to wzrostowi kliknięć dziecka powyżej ich poziomu, aby rodzic nie otrzymał kliknięcia.

.not() jest używany nieco inaczej, filtruje elementy poza twój selektor, na przykład:

<div class="bob" id="myID"></div>
<div class="bob"></div>

$(".bob").not("#myID"); //removes the element with myID

Jeśli chodzi o kliknięcie, Twoim problemem jest to, że kliknięcie dziecka przenosi się do rodzica , a nie to, że nieumyślnie dołączyłeś do niego moduł obsługi kliknięcia.

Nick Craver
źródło
dzięki nick, nie sądzę, że tego właśnie szukałem. Przykro mi, że nie wyraziłem się jasno w moim pytaniu. Chcę, aby cały div.example zniknął, tylko po kliknięciu elementu nadrzędnego, a nie po kliknięciu podrzędnego elementu div. Powodem tego jest to, że chciałbym, aby użytkownik mógł kliknąć tekst akapitu i nie powodować zanikania tekstu. Jeśli użytkownik kliknie zewnętrzny element div (nadrzędny element div), wszystko zniknie.
superUntitled
@superUntitled - Dzięki za wyjaśnienie ... odpowiedź została zaktualizowana, aby to zrobić, spróbuj.
Nick Craver
18
@Asaf - użyj e.stopPropagation();zamiast w return false;tym przypadku.
Nick Craver
2
Możesz także użyć }).find('.classes-to-ignore').click(function(e) {do wybrania określonych elementów podrzędnych
Paul Mason,
5
Nie rozumiem, dlaczego mówisz mu, żeby użył, e.stopPropagation()a potem użył return falsezamiast tego. return falsejest równoważne, e.preventDefault(); e.stopPropagation()więc może mieć nieoczekiwane skutki uboczne.
Steen Schütt
183

Używam następujących znaczników i napotkałem ten sam problem:

<ul class="nav">
    <li><a href="abc.html">abc</a></li>
    <li><a href="def.html">def</a></li>
</ul>

Tutaj użyłem następującej logiki:

$(".nav > li").click(function(e){
    if(e.target != this) return; // only continue if the target itself has been clicked
    // this section only processes if the .nav > li itself is clicked.
    alert("you clicked .nav > li, but not it's children");
});

Jeśli chodzi o dokładne pytanie, widzę, że działa w następujący sposób:

$(".example").click(function(e){
   if(e.target != this) return; // only continue if the target itself has been clicked
   $(".example").fadeOut("fast");
});

lub oczywiście na odwrót:

$(".example").click(function(e){
   if(e.target == this){ // only if the target itself has been clicked
       $(".example").fadeOut("fast");
   }
});

Mam nadzieję, że to pomoże.

MatCarey
źródło
28
Myślę, że to lepsze rozwiązanie. W żaden sposób nie przeszkadza dzieciom i powinien działać lepiej, ponieważ potencjalnie nie rejestruje tysięcy oddzwonień, jeśli są tysiące dzieci.
LucasB
4
@ l2aelba - powinieneś używać .on("click", ...)w najnowszych wersjach jQuery, ponieważ .live()jest ono przestarzałe od wersji 1.7. Zobacz api.jquery.com/live
Chris,
Tak, @Chris wysłałem 16 listopada '12 o 10:12
l2aelba,
Przepraszamy, prawdopodobnie nie musiałem odnosić się do twojego identyfikatora. Dodałem komentarz w dużej mierze dla każdego, kto czytał tę odpowiedź.
Chris,
1
Ta odpowiedź jest lepsza niż zaakceptowana odpowiedź, ponieważ nie przerywa żadnych kliknięć elementów podrzędnych
cameronjonesweb
24

Możesz też:

$('.example').on('click', function(e) { 
   if( e.target != this ) 
       return false;

   // ... //
});
dani24
źródło
Musisz zwrócić false, aby uniknąć zdarzenia kliknięcia w elementach podrzędnych. Rewizja była błędna
dani24
6

Moje rozwiązanie:

jQuery('.foo').on('click',function(event){
    if ( !jQuery(event.target).is('.foo *') ) {
        // code goes here
    } 
});
npl len
źródło
Podobne do rozwiązania powyżej twojego.
user460114
3

Osobiście dodałbym moduł obsługi kliknięcia do elementu podrzędnego, który nic nie robił, ale zatrzymywał propagację kliknięcia. Więc wyglądałoby to mniej więcej tak:

$('.example > div').click(function (e) {
    e.stopPropagation();
});
Noahone
źródło
Jaka jest różnica między stopPropagationi zwracaniem fałszu, jak sugerują inne odpowiedzi?
Crashalot
Wierzę, że w tym przypadku funkcjonowałyby tak samo, ale myślę, że zatrzymanie propagacji jest bardziej zrozumiałe dla celu tego, co się dzieje, i pozostawia większą szansę na zrozumienie, dlaczego robi się to później. Ale to dyskusyjne.
Noahone
Dziękuję za wyjaśnienie. wygląda na to, że stopPropagationmoże być czystszy, ponieważ nie powstrzyma zdarzeń na elementach podrzędnych, co może się zdarzyć w przypadku return false.
Crashalot
0

Oto przykład. Zielony kwadrat to element nadrzędny, a żółty to element podrzędny.

Mam nadzieję, że to pomoże.

var childElementClicked;

$("#parentElement").click(function(){

		$("#childElement").click(function(){
		   childElementClicked = true;
		});

		if( childElementClicked != true ) {

			// It is clicked on parent but not on child.
      // Now do some action that you want.
      alert('Clicked on parent');
			
		}else{
      alert('Clicked on child');
    }
    
    childElementClicked = false;
	
});
#parentElement{
width:200px;
height:200px;
background-color:green;
position:relative;
}

#childElement{
margin-top:50px;
margin-left:50px;
width:100px;
height:100px;
background-color:yellow;
position:absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="parentElement">
  <div id="childElement">
  </div>
</div>

Nole
źródło