jQuery: klik api () sebelum acara blur ()

135

Saya memiliki kolom masukan, tempat saya mencoba membuat saran pelengkapan otomatis. Kode terlihat seperti

<input type="text" id="myinput">
<div id="myresults"></div>

Pada blur()acara masukan, saya ingin menyembunyikan div hasil:

$("#myinput").live('blur',function(){
     $("#myresults").hide();
});

Ketika saya menulis sesuatu ke input saya, saya mengirim permintaan ke server dan mendapatkan respons json, menguraikannya ke dalam struktur ul-> li dan meletakkan ul ini ke #myresultsdiv saya .

Ketika saya mengklik elemen li yang diuraikan ini, saya ingin mengatur nilai dari li ke input dan menyembunyikan #myresultsdiv

$("#myresults ul li").live('click',function(){
     $("#myinput").val($(this).html());
     $("#myresults").hide();
});

Semuanya berjalan baik, tetapi ketika saya mengklik ke blur()acara li saya aktif sebelumnya click()dan nilai input tidak mendapatkan html li.

Bagaimana saya bisa mengatur click()acara sebelumnya blur()?

Egor Sazanovich
sumber
Jadi mengapa Anda menggunakan fungsi blur? ketika kebutuhan Anda sudah terpenuhi dari fungsi klik.
Owais Iqbal
Ini mungkin tidak akan mengubah urutan yang diaktifkan peristiwa Anda, tetapi jika blurbenar-benar diaktifkan setelah Anda mengeklik li, Anda mungkin tidak perlu menjalankannya $("#myresults").hide()di penangan klik. Apa yang tampaknya terjadi $(this).html()adalah mengembalikan string kosong. Bisakah Anda logatau alert $(this).html()untuk memastikan?
veeTrain
@OwaisIqbal terkadang tidak ada hasil, terkadang pengguna tidak ingin memilih apa pun dari saran, terkadang pengguna tidak ingin menggunakan input ini lagi, tetapi saya harus menyembunyikan hasil yang tidak digunakan
Egor Sazanovich
@veeTrain ada banyak tindakan di penangan saya, saya baru saja meminimalkannya untuk memudahkan pemahaman masalah dalam pertanyaan saya. ps Saya sudah mencoba menambahkan watch-point di firebug on blur()dan click()handler, tidak ada tindakan setelah blur()berakhir
Egor Sazanovich
Sepertinya Anda perlu mengantrekan fungsi. Coba lihat halaman ini: stackoverflow.com/questions/1058158/… . Bagian First-In-First-Out (FIFO) mungkin berkaitan dengan Anda
Patriotec

Jawaban:

315

Solusi 1

Dengarkan, mousedownbukan click.

The mousedowndan blurperistiwa terjadi satu demi satu saat Anda menekan tombol mouse, tetapi clickhanya terjadi ketika Anda melepaskannya.

Solusi 2

Anda bisa preventDefault()masuk mousedownuntuk memblokir dropdown agar tidak mencuri fokus. Keuntungan kecilnya adalah bahwa nilainya akan dipilih ketika tombol mouse dilepaskan, yang merupakan cara kerja komponen pemilihan asli. JSFiddle

$('input').on('focus', function() {
    $('ul').show();
}).on('blur', function() {
    $('ul').hide();
});

$('ul').on('mousedown', function(event) {
    event.preventDefault();
}).on('click', 'li', function() {
    $('input').val(this.textContent).blur();
});
Alexey Lebedev
sumber
13
Solusi 1 berhasil untuk saya dalam situasi yang sama ini! Perubahan mudah! Terima kasih :)
Jon
Terima kasih :) Tapi bisakah Anda menjelaskan mengapa mendengarkan mousedown alih-alih klik berfungsi seperti pesona?
Mudassir Ali
3
@MudassirAli karena acara mousedown muncul sebelum blur, dan klik muncul setelahnya. jsfiddle.net/f3BKP
Alexey Lebedev
Solusi # 1 menurut saya adalah pilihan yang lebih baik. Sederhana dan efektif. Batas waktu akan berarti lebih banyak kode + lebih banyak ruang untuk perilaku tidak terduga (berapa lama waktu habis? Cukup lama untuk mendaftarkan klik, tetapi tidak terlalu lama untuk membingungkan penggunaan ...).
cw24
5
Solusi # 2 cerdik. Saya tidak akan pernah menyadarinya! Terima kasih
Tobia
2
$(document).on('blur', "#myinput", hideResult);

$(document).on('mousedown', "#myresults ul li", function(){
     $(document).off('blur', "#myinput", hideResult); //unbind the handler before updating value
     $("#myinput").val($(this).html()).blur(); //make sure it does not have focus anymore
     hideResult(); 
     $(document).on('blur', "#myinput", hideResult);  //rebind the handler if needed
});

function hideResult() {
     $("#myresults").hide();
}

BIOLA

adeneo
sumber
2

Saya menghadapi masalah ini dan menggunakan mousedownbukanlah pilihan bagi saya.

Saya menyelesaikan ini dengan menggunakan setTimeoutfungsi di handler

        elem1.on('blur',function(e) {

            var obj = $(this);

            // Delay to allow click to execute
            setTimeout(function () {
                if (e.type == 'blur') {

                  // Do stuff here

                }
            }, 250);
        });

        elem2.click( function() {
            console.log('Clicked');
        });
tokek
sumber
2

Saya baru saja menjawab pertanyaan serupa: https://stackoverflow.com/a/46676463/227578

Alternatif untuk solusi mousedown adalah membuatnya mengabaikan peristiwa blur yang disebabkan oleh mengklik elemen tertentu (misalnya, di blur handler Anda, lewati eksekusi jika itu adalah hasil dari mengklik elemen tertentu).

$("#myinput").live('blur',function(e){
     if (!e.relatedTarget || !$(e.relatedTarget).is("#myresults ul li")) {
         $("#myresults").hide();
     }
});
dule
sumber
dalam kasus saya, event.relatedTarget mengembalikan null, tahu mengapa bisa demikian?
gaurav5430
ok, dapatkan jawabannya di sini: stackoverflow.com/questions/42764494/…
gaurav5430
0

Solusi mousedown tidak berfungsi untuk saya, ketika saya mengklik elemen non tombol. Jadi inilah yang saya lakukan dengan fungsi blur di kode saya:

.on("blur",":text,:checkbox,:radio,select",function() {
/*
* el.container 
* container, you want detect click function on.
*/
            var outerDir = el.container.find(':hover').last();
            if (outerDir.length) {
                if ($.inArray(outerDir.prop('tagName'), ["A","SELECT"] ) != -1 || outerDir.prop('type') == 'button' || outerDir.prop('type') == 'submit') {
                    outerDir.click();
                }
                if (outerDir.prop('type') == 'checkbox') {
                    outerDir.change();
                }
                return false;
            }
/*          
* YOUR_BLUR_FUNCTION_HERE;
*/
});
Andriy
sumber