JQuery: огонь click () перед событием blur ()


134

У меня есть поле ввода, где я пытаюсь сделать предложение автозаполнения. Код выглядит так

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

На входном blur()событии я хочу скрыть результаты div:

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

Когда я что-то записываю в свой ввод, я отправляю запрос на сервер и получаю ответ json, разбираю его в структуре ul-> li и помещаю этот ul в мой #myresultsdiv.

Когда я нажимаю на этот разобранный элемент li, я хочу установить значение от li до input и скрыть #myresultsdiv

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

Все идет хорошо, но когда я нажимаю на blur()событие li, которое запускается раньше, click()и значение input не получает html li.

Как я могу настроить click()событие раньше blur()?


В таком случае, почему вы используете функцию размытия? когда ваша потребность уже заполнена от функции щелчка.
— Оваис Икбал

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

@OwaisIqbal иногда нет результатов, иногда пользователь не хочет ничего выбирать из предложений, иногда пользователь больше не хочет использовать этот ввод, но я должен скрыть неиспользованный результат
— Егор Сазанович

@veeTrain, в моих обработчиках много действий, я просто свел их к минимуму, чтобы было проще понять проблему в моем вопросе. ps Я пытался добавить точку наблюдения в firebug on blur()и handlers click(), после blur()конца никаких действий нет
— Егор Сазанович

Похоже, вам нужно поставить в очередь функции. Попробуйте взглянуть на эту страницу: stackoverflow.com/questions/1058158/… . Часть «первым пришел - первым обслужен» (FIFO) может принадлежать вам
— Patriotec

Ответы:


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 сработало для меня в этой же ситуации! Легкая смена! Спасибо :)
— Джон

Спасибо :) Но можете ли вы объяснить, почему прослушивание 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();
}

FIDDLE


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 solutions не работает для меня, когда я нажимаю на не кнопочные элементы. Итак, вот что я сделал с функцией размытия в моем коде:

.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.