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()?

Egor Sazanovich
źródło
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();
});
Alexey Lebedev
źródło
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

adeneo
źródło
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');
        });
geckob
źródło
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();
     }
});
dule
źródło
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;
*/
});
Andriy
źródło