Bagaimana cara menonaktifkan peristiwa mouseout yang dipicu oleh elemen anak?

107

Izinkan saya menjelaskan masalah secara rinci:

Saya ingin menampilkan div posisi absolut saat mengarahkan kursor ke elemen. Itu sangat sederhana dengan jQuery dan berfungsi dengan baik. Tapi ketika mouse melewati salah satu elemen anak, itu memicu kejadian mouseout dari div yang memuat. Bagaimana cara menjaga javascript agar tidak memicu kejadian mouseout dari elemen yang mengandung saat mengarahkan sebuah elemen anak.

Apa cara terbaik dan terpendek untuk melakukannya dengan jQuery?

Berikut adalah contoh sederhana untuk menggambarkan apa yang saya maksud:

Html:

<a>Hover Me</a>
<div>
  <input>Test</input>
  <select>
    <option>Option 1</option>
    <option>Option 2</option>
  </select>
</div>

Javascript / jQuery:

$('a').hover( function() { $(this).next().show() }
              function() { $(this).next().hide() } );
Sander Versluys
sumber
1
Tanpa versi jQuery dari pertanyaan ini
Zach Saucier

Jawaban:

209

Pertanyaannya agak lama, tapi saya bertemu dengan ini beberapa hari yang lalu.

Cara paling mudah untuk melakukan hal ini dengan versi terbaru dari jQuery adalah dengan menggunakan mouseenterdan mouseleaveperistiwa daripada mouseoverdan mouseout.

Anda dapat menguji perilakunya dengan cepat dengan:

$(".myClass").on( {
   'mouseenter':function() { console.log("enter"); },
   'mouseleave':function() { console.log("leave"); }
});
bytebrite.dll
sumber
4
Membantu masalah terkait javascript non-jquery saya. Saya menggunakan mouseenter / mouseout dan bukannya mouseleave dengan pendengar acara saya!
Jo E.
1
Demi penelusuran, perilaku peristiwa mouse ini setara dengan ROLL_OVERdan ROLL_OUTdi AS3.
Jeff Ward
2
Membuatku sakit kepala. Anehnya bagaimana hovering pada elemen anak memicu acara induk mouseout, padahal sebenarnya masih di dalam elemen induk.
javiniar.leonard
18

Demi kesederhanaan, saya hanya akan mengatur ulang html sedikit untuk meletakkan konten yang baru ditampilkan di dalam elemen yang terikat pada peristiwa gerakan mouse:

<div id="hoverable">
  <a>Hover Me</a>
  <div style="display:none;">
    <input>Test</input>
    <select>
      <option>Option 1</option>
      <option>Option 2</option>
    </select>
  </div>
</div>

Kemudian, Anda dapat melakukan sesuatu seperti ini:

$('#hoverable').hover( function() { $(this).find("div").show(); },
                       function() { $(this).find("div").hide(); } );

Catatan: Saya tidak merekomendasikan inline css, tapi itu dilakukan untuk membuat contoh lebih mudah dicerna.

Ryan McGeary
sumber
Ini memang solusi yang sangat sederhana dan bersih. Terima kasih telah mengingatkan saya. Tetapi dalam situasi khusus saya, yang tidak persis seperti dalam pertanyaan, ini bukan pilihan. Terimakasih Meskipun!
Sander Versluys
Setelah mencoba metode yang berbeda seperti yang dijelaskan oleh orang lain di SO, saya kembali ke metode Anda dan berhasil dalam kasus saya. Yay! :-)
Sander Versluys
11

Ya, teman-teman, gunakan .mouseleavesebagai pengganti .mouseout:

$('div.sort-selector').mouseleave(function() {
    $(this).hide();
});

Atau bahkan gunakan dengan kombinasi live:

$('div.sort-selector').live('mouseleave', function() {
    $(this).hide();
});
Lord Nighton
sumber
8

Anda mencari jQuery yang setara dengan peristiwa pencegahan javascript yang menggelegak.

Lihat ini:

http://docs.jquery.com/Events/jQuery.Event#event.stopPropagation.28.29

Pada dasarnya Anda perlu menangkap kejadian di simpul DOM turunan, dan di sana menghentikan penyebarannya ke pohon DOM. Cara lain, meskipun sebenarnya tidak disarankan (karena dapat sangat mengacaukan peristiwa yang ada di halaman Anda), adalah dengan menyetel pengambilan peristiwa ke elemen tertentu di halaman, dan itu akan menerima semua peristiwa. Ini berguna untuk perilaku DnD dan semacamnya, tetapi jelas tidak untuk kasus Anda.

Yuval Adam
sumber
ini berfungsi sebagaimana mestinya, tidak tahu mengapa Anda tidak bisa membuatnya berfungsi .. hanya sebuah info, tautan ke dokumen telah berubah, tautan baru adalah docs.jquery.com/Events/jQuery.Event#event.stopPropagation. 28.29
zappan
3

Saya hanya memeriksa apakah koordinat mouse berada di luar elemen dalam peristiwa mouseout.

Ini berfungsi tetapi banyak kode untuk hal yang sesederhana itu :(

function mouseOut(e)
{
    var pos = GetMousePositionInElement(e, element);
    if (pos.x < 0 || pos.x >= element.size.X || pos.y < 0 || pos.y >= element.size.Y)
    {
        RealMouseOut();
    }
    else
    {
         //Hit a child-element
    }
}

Kode dipotong agar mudah dibaca, tidak akan berfungsi di luar kotak.


sumber
1

Saya setuju dengan Ryan.

Masalah Anda adalah bahwa div "berikutnya" bukanlah "anak" dari A. Tidak ada cara bagi HTML atau jQuery untuk mengetahui bahwa elemen "a" Anda terkait dengan div turunan di DOM. Membungkusnya dan mengarahkan kursor ke pembungkus berarti mereka terkait.

Harap perhatikan bahwa kodenya tidak sejalan dengan praktik terbaik. Jangan setel gaya tersembunyi sebaris pada elemen; jika pengguna memiliki CSS tetapi bukan javascript, elemen tersebut akan bersembunyi dan tidak akan dapat ditampilkan. Praktik yang lebih baik adalah meletakkan deklarasi itu di acara document.ready.

pengguna37731
sumber
Saya sangat setuju dengan menyembunyikan acara document.ready. CSS sebaris hanya untuk menyampaikan contoh kerja lengkap dengan cara sesederhana mungkin. Saya akan mengedit tanggapan saya untuk memperjelasnya.
Ryan McGeary
1

Saya menyelesaikan masalah ini dengan menambahkan pointer-events: none;elemen anak saya css

Antoine
sumber
Ini sangat membantu saat memperbaiki beberapa kode lama yang membuat popoversnya sendiri dengan acara gerakan mouse dan mouseleave
CM
0

Cara saya biasanya melihat ini ditangani adalah memiliki jeda sekitar 1/2 detik antara memindahkan mouse dari elemen HoverMe. Saat menggerakkan mouse ke elemen yang di-hover, Anda ingin menyetel beberapa variabel yang menandakan bahwa Anda sedang mengarahkan kursor ke elemen, dan kemudian pada dasarnya menghentikan bagian yang di-hover dari persembunyian jika variabel ini disetel. Anda kemudian harus menambahkan fungsi sembunyi OnMouseOut yang serupa dari elemen yang di-hover untuk membuatnya menghilang saat Anda melepas mouse. Maaf, saya tidak bisa memberikan kode apa pun, atau sesuatu yang lebih konkret, tapi saya harap ini mengarahkan Anda ke arah yang benar.

Kibbee
sumber
Ya idd Saya baru saja menerapkan solusi seperti itu. Ini masalah yang sangat umum. Saya sangat penasaran ada solusi lain apa ... Terima kasih atas jawabannya!
Sander Versluys
0

Ini pertanyaan lama, tapi tidak pernah menjadi usang. Jawaban yang benar haruslah yang diberikan oleh bytebrite .

Saya hanya ingin menunjukkan perbedaan antara gerakan mouse / mouseout dan mouseenter / mouseleave. Anda dapat membaca penjelasan yang bagus dan bermanfaat di sini (pergi ke bagian paling bawah halaman untuk demo yang berfungsi). Saat Anda menggunakan mouseout, peristiwa berhenti saat mouse memasuki elemen lain, meskipun itu adalah elemen anak. Di sisi lain, saat Anda menggunakan mouseleave, acara tidak dipicu saat mouse melewati elemen anak, dan ini adalah perilaku yang ingin dicapai OP.

Erenor Paz
sumber