jQuery: запустити натискання () перед подією blur ()


134

У мене є поле введення, де я намагаюся зробити пропозицію щодо автозаповнення. Код виглядає так

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

Під час blur()події я хочу приховати поділ результатів:

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

Коли я щось записую на свій вхід, я надсилаю запит на сервер і отримую json відповідь, розбираю його в ul-> li структуру і ставлю цей ul своєму #myresultsдиві.

Коли я натискаю на цей проаналізований елемент li, я хочу встановити значення від li на вхід та приховати #myresultsdiv

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

Все йде добре, але коли я натискаю на свою blur()подію li події, click()і значення вводу не отримує ht-код li.

Як я можу налаштувати click()подію раніше blur()?


так що в тому випадку, чому ви використовуєте функцію розмиття? коли Ваша потреба вже заповнена функцією клацання.
— Овайс Ікбал

Це, ймовірно, не змінить порядок запуску ваших подій, але якщо blurпісля натискання на нього дійсно запускається li, вам, ймовірно, не потрібно виконувати $("#myresults").hide()цей обробник кліків. Як здається, відбувається те, що $(this).html()повертає порожній рядок. Ви могли logчи alert $(this).html()переконаєтесь?
— veeTrain

@OwaisIqbal іноді немає результатів, іноді користувач не хоче нічого вибирати із пропозицій, іноді користувач більше не хоче використовувати цей вхід, але я повинен приховати невикористаний результат
— Єгор Сазанович,

@veeTrain У моїх обробниках є багато дій, я просто їх мінімізував, щоб легко зрозуміти проблему в моєму питанні. ps Я спробував додати точку спостереження у firebug на blur()та обробці click(), після blur()закінчення не буде дій
— Єгор Сазанович

Схоже, вам потрібно встановити чергу в функції. Спробуйте переглянути цю сторінку: stackoverflow.com/questions/1058158/… . Частина "Перший-Перший-Вихід" (FIFO) може стосуватись Вас
— Патріотек

Відповіді:


312

Рішення 1

Слухайте mousedownзамість click.

Події mousedownта blurподії відбуваються одна за одною, коли ви натискаєте кнопку миші, але clickвідбувається лише тоді, коли ви відпускаєте її.

Рішення 2

Ви можете preventDefault()в mousedownблокувати спадаюче меню від крадіжки фокусу. Невелика перевага полягає в тому, що значення буде вибиратися після відпуску кнопки миші, саме так працюють натільні компоненти вибору. 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();
});

12
Рішення 1 працювало для мене в цій самій ситуації! Легка зміна! Дякую :)
— Jon

Дякую :) Але ви можете пояснити, чому прослуховування Mousedown замість клацання працює як шарм?
— Мудассір Алі

3
@MudassirAli, тому що подія mousedown відбувається перед розмиттям, а натискання відбувається після. jsfiddle.net/f3BKP
— Олексій Лебедєв

Рішення №1 - на мій погляд, кращий вибір. Простий і ефективний. Час очікування означатиме більше коду + більше місця для несподіваної поведінки (як довго вичерпується? Достатньо довгий час для реєстрації натискання, але не надто довгий, щоб заплутати використання ...).
— cw24

5
Рішення №2 геніальне. Я б ніколи цього не зрозумів! Спасибі
— Тобія

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

ПІДМОГА


2

Я зіткнувся з цією проблемою, і використання mousedownдля мене не є варіантом.

Я вирішив це за допомогою setTimeoutфункції обробника

        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');
        });

2

Я щойно відповів на подібне запитання: https://stackoverflow.com/a/46676463/227578

Альтернативою рішенням для mousedown є те, щоб воно ігнорувало події розмиття, викликані клацанням конкретних елементів (тобто у вашому обробці розмиття, пропустіть виконання, якщо це результат натискання певного елемента).

$("#myinput").live('blur',function(e){
     if (!e.relatedTarget || !$(e.relatedTarget).is("#myresults ul li")) {
         $("#myresults").hide();
     }
});

у моєму випадку event.relatedTarget повертає нуль, будь-яка ідея, чому це могло бути?
— gaurav5430

ок, отримав відповідь тут: stackoverflow.com/questions/42764494 / ...
— gaurav5430

0

Рішення Mousedown не працює для мене, коли натискаю на елементи, які не є кнопками. Отже, ось що я зробив із функцією розмиття у своєму коді:

.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;
*/
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.