jQuery: fungsi klik mengecualikan anak-anak.

144

Mencoba membungkus kepala saya di sekitar fungsi jQuery ".not ()", dan mengalami masalah. Saya ingin agar div induk menjadi "dapat diklik" tetapi jika pengguna mengklik elemen anak, skrip tidak dipanggil.

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

html:

<div class="example">
   <div>
      <p>This content is not affected by clicks.</p>
   </div>
</div>
tanpa judul
sumber

Jawaban:

198

Untuk melakukan ini, hentikan klik pada anak menggunakan .stopPropagation :

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

Ini akan menghentikan klik anak menggelembung melewati level mereka sehingga orang tua tidak akan menerima klik.

.not() digunakan sedikit berbeda, itu menyaring elemen dari pemilih Anda, misalnya:

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

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

Untuk mengklik, masalah Anda adalah bahwa klik pada anak muncul hingga induknya , bukan karena Anda secara tidak sengaja telah melampirkan handler klik pada anak.

Nick Craver
sumber
terima kasih nick, saya tidak berpikir bahwa ini adalah apa yang saya cari. Saya minta maaf karena pertanyaan saya tidak jelas. Saya ingin seluruh div.example untuk fadeOut, hanya ketika elemen induk diklik, bukan ketika div anak diklik. Alasan untuk ini adalah saya ingin pengguna dapat mengklik teks paragraf dan tidak memiliki teks fadeOut. Jika pengguna mengklik div luar (induk div), maka semuanya akan pudar.
superUtitle
@superUntitle - Terima kasih atas klarifikasi ... jawabannya diperbarui untuk melakukan ini, cobalah.
Nick Craver
18
@ Asaf - gunakan e.stopPropagation();sebagai ganti return false;untuk kasus itu.
Nick Craver
2
Anda juga dapat menggunakan }).find('.classes-to-ignore').click(function(e) {untuk memilih elemen anak tertentu
Paul Mason
5
Saya tidak mengerti mengapa Anda memintanya untuk menggunakan e.stopPropagation()dan kemudian menggunakannya return false. return falsesetara dengan e.preventDefault(); e.stopPropagation()sehingga mungkin memiliki efek samping yang tidak diharapkan.
Steen Schütt
183

Saya menggunakan markup berikut dan mengalami masalah yang sama:

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

Di sini saya telah menggunakan logika berikut:

$(".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");
});

Dalam hal pertanyaan yang tepat, saya dapat melihat bahwa berfungsi sebagai berikut:

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

atau tentu saja sebaliknya:

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

Semoga itu bisa membantu.

MatCarey
sumber
28
Saya pikir ini adalah solusi yang lebih baik. Itu tidak mengganggu anak-anak dengan cara apa pun dan itu harus berkinerja lebih baik karena tidak berpotensi mendaftarkan ribuan panggilan balik jika ada ribuan anak-anak.
LucasB
4
@ l2aelba - Anda harus menggunakan .on("click", ...)dalam versi terbaru jQuery seperti yang .live()telah ditinggalkan sejak v1.7. Lihat api.jquery.com/live
Chris
Ya, @ Chris, saya memposting pada 16 November '12 pada 10:12
l2aelba
Maaf, mungkin tidak perlu referensi ID Anda. Saya menambahkan komentar sebagian besar untuk orang lain yang membaca jawaban ini.
Chris
1
Jawaban ini lebih baik daripada jawaban yang diterima karena tidak mengganggu acara klik pada elemen anak
cameronjonesweb
24

Atau Anda juga bisa:

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

   // ... //
});
dani24
sumber
Anda harus mengembalikan false, untuk menghindari peristiwa klik di elemen anak-anak. Revisi itu salah
dani24
6

Solusi saya:

jQuery('.foo').on('click',function(event){
    if ( !jQuery(event.target).is('.foo *') ) {
        // code goes here
    } 
});
npl len
sumber
Mirip dengan solusi di atas milik Anda.
user460114
3

Saya pribadi akan menambahkan handler klik ke elemen anak yang tidak melakukan apa pun selain menghentikan penyebaran klik tersebut. Jadi akan terlihat seperti:

$('.example > div').click(function (e) {
    e.stopPropagation();
});
Noahone
sumber
apa perbedaan antara stopPropagationdan mengembalikan false seperti yang disarankan jawaban lain?
Crashalot
Saya percaya dalam kasus ini mereka akan berfungsi sama, tetapi saya pikir berhenti propagasi lebih jelas dengan tujuan apa yang dilakukan dan meninggalkan peluang yang lebih baik untuk memahami mengapa hal itu dilakukan nanti. Tapi ini masih bisa diperdebatkan.
Noahone
terimakasih atas klarifikasinya. sepertinya stopPropagationmungkin lebih bersih karena tidak akan menghentikan peristiwa pada elemen anak terjadi, yang mungkin terjadi dengan return false.
Crashalot
0

Berikut ini sebuah contoh. Kotak hijau adalah induk dan kotak kuning adalah elemen anak.

Semoga ini bisa membantu.

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
sumber