jQuery: fire click () przed zdarzeniem blur ()


134

Mam pole wprowadzania, w którym próbuję zasugerować autouzupełnianie. Wygląda na to kod

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

W blur()przypadku zdarzenia input chcę ukryć div wyników:

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

Kiedy piszę coś do swojego wejścia, wysyłam żądanie do serwera i otrzymuję odpowiedź json, parsuję ją do struktury ul-> li i umieszczam ten ul w moim #myresultsdiv.

Kiedy klikam na ten przeanalizowany element li, chcę ustawić wartość z li na wejście i ukryć #myresultsdiv

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

Wszystko idzie dobrze, ale kiedy klikam, aby blur()zdarzenie li było uruchamiane wcześniej, click()a wartość danych wejściowych nie otrzymuje kodu HTML li.

Jak mogę wcześniej ustawić click()wydarzenie blur()?


więc w takim razie dlaczego używasz funkcji rozmycia? gdy Twoje potrzeby są już spełnione dzięki funkcji kliknięcia.
— Owais Iqbal

Prawdopodobnie nie zmieni to kolejności uruchamiania zdarzeń, ale jeśli blurnaprawdę uruchamia się po kliknięciu na li, prawdopodobnie nie musisz wykonywać $("#myresults").hide()w module obsługi kliknięcia. Wydaje się, że dzieje się to, że $(this).html()zwraca pusty ciąg. Mógłbyś loglub alert $(this).html()żeby się upewnić?
— veeTrain

@OwaisIqbal czasami nie ma wyników, czasami użytkownik nie chce niczego wybierać z sugestii, czasami użytkownik nie chce już używać tego wejścia, ale muszę ukryć niewykorzystany wynik
— Egor Sazanovich

@veeTrain w moich programach obsługi jest wiele działań, po prostu je zminimalizowałem, aby łatwo zrozumieć problem w moim pytaniu. ps Próbowałem dodać zegarek punkt w Firebug na blur()i click()ładowarki, nie ma akcji po blur()końce
— Egor Sazanovich

Wygląda na to, że musisz ustawić w kolejce funkcje. Zajrzyj na tę stronę: stackoverflow.com/questions/1058158/… . Część First-In-First-Out (FIFO) może dotyczyć Ciebie
— Patriotec

Odpowiedzi:


312

Rozwiązanie 1

Słuchaj mousedownzamiast click.

mousedownI blurzdarzenia jeden po drugim po naciśnięciu przycisku myszy, ale clicktylko wtedy, kiedy zwolnić.

Rozwiązanie 2

Można preventDefault()w mousedowncelu zablokowania rozwijaną od kradzieży ostrość. Niewielką zaletą jest to, że wartość zostanie wybrana po zwolnieniu przycisku myszy, tak działają komponenty natywne. 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
Rozwiązanie 1 zadziałało dla mnie w tej samej sytuacji! Łatwa zmiana! Dziękuję :)
— Jon

Dziękuję :) Ale czy możesz wyjaśnić, dlaczego słuchanie wyciszania myszy zamiast klikania działa jak urok?
— Mudassir Ali

3
@MudassirAli, ponieważ zdarzenie mousedown następuje przed rozmyciem, a kliknięcie następuje po. jsfiddle.net/f3BKP
— Alexey Lebedev

Rozwiązanie nr 1 jest moim zdaniem lepszym wyborem. Proste i skuteczne. Limit czasu oznaczałby więcej kodu + więcej miejsca na nieoczekiwane zachowanie (jak długi czas? Wystarczająco długi, aby zarejestrować kliknięcie, ale nie za długi, aby zmylić użycie ...).
— cw24

5
Rozwiązanie nr 2 jest genialne. Nigdy bym tego nie rozgryzł! Dzięki
— 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();
}

SKRZYPCE


2

Miałem do czynienia z tym problemem i używanie mousedownnie jest dla mnie opcją.

Rozwiązałem to za pomocą setTimeoutfunkcji obsługi

        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

Właśnie odpowiedziałem na podobne pytanie: https://stackoverflow.com/a/46676463/227578

Alternatywą dla rozwiązań wyciszania kursora jest ignorowanie zdarzeń rozmycia spowodowanych kliknięciem określonych elementów (tj. W module obsługi rozmycia pomiń wykonanie, jeśli jest to wynikiem kliknięcia określonego elementu).

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

w moim przypadku event.relatedTarget zwraca null, jakikolwiek pomysł, dlaczego tak się dzieje?
— gaurav5430,

ok, otrzymałem odpowiedź tutaj: stackoverflow.com/questions/42764494/…
— gaurav5430

0

Rozwiązania Mousedown nie działają dla mnie, gdy klikam elementy niebędące przyciskami. Oto, co zrobiłem z funkcją rozmycia w moim kodzie:

.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;
*/
});
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.