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.