Saya memiliki kolom input yang menampilkan menu drop-down kustom. Saya ingin fungsi berikut:
- Saat pengguna mengklik di mana saja di luar bidang input, menu harus dihapus.
- Jika, lebih khusus lagi, pengguna mengklik div di dalam menu, menu tersebut harus dihapus, dan pemrosesan khusus akan terjadi berdasarkan div mana yang diklik.
Inilah implementasi saya:
Bidang masukan memiliki onblur()
peristiwa yang menghapus menu (dengan menyetel induknya innerHTML
ke string kosong) setiap kali pengguna mengklik di luar bidang masukan. Div di dalam menu juga memiliki onclick()
event yang menjalankan pemrosesan khusus.
Masalahnya adalah bahwa onclick()
kejadian tidak pernah menyala saat menu diklik, karena bidang masukan onblur()
diaktifkan terlebih dahulu dan menghapus menu, termasukonclick()
s!
Saya memecahkan masalah dengan membagi menu divs ' onclick()
menjadi onmousedown()
dan onmouseup()
event dan mengatur bendera global pada mouse ke bawah yang dihapus pada mouse ke atas, mirip dengan yang disarankan dalam jawaban ini . Karena onmousedown()
diaktifkan sebelumnya onblur()
, flag akan disetel onblur()
jika salah satu div menu diklik, tetapi tidak jika di tempat lain di layar ada. Jika menu itu diklik, saya langsung kembali dari onblur()
tanpa menghapus menu, lalu menunggu onclick()
hingga menyala, pada titik mana saya dapat menghapus menu dengan aman.
Apakah ada solusi yang lebih elegan?
Kode tersebut terlihat seperti ini:
<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />
var mouseflag;
function setFlag() {
mouseflag = true;
}
function removeMenu() {
if (!mouseflag) {
document.getElementById('menu').innerHTML = '';
}
}
function doProcessing(id, name) {
mouseflag = false;
...
}
sumber
onmousedown
dijalankan sebelumonblur
Diuji di Firefox, Chrome dan Internet Explorer.onMouseDown
denganevent.preventDefault()
danonClick
dengan tindakan yang Anda inginkan.onClick
tidak boleh diganti denganonMouseDown
.Meskipun pendekatan ini berhasil , keduanya adalah peristiwa yang pada dasarnya berbeda yang memiliki harapan berbeda di mata pengguna. Menggunakan,
onMouseDown
bukanonClick
akan merusak prediktabilitas perangkat lunak Anda dalam kasus ini. Jadi, kedua peristiwa itu tidak dapat dipertukarkan.Sebagai ilustrasi: ketika mengklik tombol secara tidak sengaja, pengguna berharap dapat menahan klik mouse, menyeret kursor ke luar elemen, dan melepaskan tombol mouse, yang pada akhirnya tidak menghasilkan tindakan apa pun.
onClick
Melakukan hal ini.onMouseDown
tidak mengizinkan pengguna untuk menahan mouse, dan sebaliknya akan segera memicu tindakan, tanpa bantuan apa pun bagi pengguna.onClick
adalah standar yang kami harapkan untuk memicu tindakan di komputer.Dalam situasi ini, sebut
event.preventDefault()
padaonMouseDown
acara.onMouseDown
akan menyebabkan acara buram secara default, dan tidak akan melakukannya saatpreventDefault
dipanggil. Kemudian,onClick
akan memiliki kesempatan untuk dipanggil. Peristiwa kabur masih akan terjadi, hanya setelahnyaonClick
.Bagaimanapun,
onClick
peristiwa tersebut adalah kombinasi darionMouseDown
danonMouseUp
, jika dan hanya jika keduanya terjadi dalam elemen yang sama.sumber
event.preventDefault()
dionMouseDown
acara, acara sayaonFocus
tidak disebutGanti
onmousedown
denganonfocus
. Jadi acara ini akan dipicu saat fokus ada di dalam kotak teks.Ganti
onmouseup
denganonblur
. Saat Anda mengalihkan fokus dari kotak teks, onblur akan dijalankan.Saya rasa inilah yang mungkin Anda butuhkan.
MEMPERBARUI :
ketika Anda menjalankan fungsi Anda onfocus -> hapus kelas yang akan Anda terapkan di onblur dan tambahkan kelas yang ingin Anda jalankan onfocus
dan
ketika Anda menjalankan fungsi Anda onblur -> hapus kelas yang akan Anda terapkan di onfocus dan tambahkan kelas yang ingin Anda jalankan onblur
Saya tidak melihat adanya kebutuhan akan variabel bendera.
UPDATE 2:
Anda dapat menggunakan acara onmouseout dan onmouseover
onmouseover -Mendeteksi saat kursor berada di atasnya.
onmouseout -Mendeteksi saat kursor pergi.
sumber
onmousedown()
danonmouseup()
pada menu, bukan kotak teks / kolom input.Solusi yang lebih elegan (tapi mungkin kurang berkinerja):
Daripada menggunakan onblur input untuk menghapus menu, gunakan
document.onclick
, yang diaktifkan setelahnyaonblur
.Namun, ini juga berarti bahwa menu tersebut dihapus saat input itu sendiri diklik, yang merupakan perilaku yang tidak diinginkan. Setel
input.onclick
denganevent.stopPropagation()
untuk menghindari penyebaran klik ke acara klik dokumen.sumber
ubah onclick dengan onfocus
bahkan jika onblur dan onclick tidak rukun, tapi jelas onfocus dan onblur ya. karena bahkan setelah menu ditutup, onfokus masih berlaku untuk elemen yang diklik di dalam.
Saya melakukannya dan berhasil.
sumber
Anda dapat menggunakan
setInterval
fungsi di dalamonBlur
handler Anda , seperti ini:yang
setInterval
fungsi akan menghapus AndaonBlur
fungsi keluar dari tumpukan panggilan, tambahkan karena Anda set waktu untuk 0, fungsi ini akan segera dipanggil setelah event lainnya selesaisumber
setInterval
Itu ide yang buruk, Anda tidak pernah membatalkannya sehingga itu akan terus menjalankan fungsi Anda dan kemungkinan besar menyebabkan situs Anda menggunakan max cpu. GunakansetTimeout
sebagai gantinya jika Anda akan menggunakan teknik ini (yang tidak saya rekomendasikan). Membuat aplikasi Anda bergantung pada waktu peristiwa tertentu adalah bisnis yang berisiko.setTimeout
tidaksetInterval
) tetapi saya harus meningkatkannya hingga250
ms sebelum waktunya terjadi dalam urutan yang benar. Bug ini mungkin akan tetap ada di perangkat yang lebih lambat dan juga membuat penundaan terlihat. Saya mencobaonMouseDown
dan berfungsi dengan baik. Saya ingin tahu apakah itu membutuhkan acara sentuh juga.