jQuery: fire click () prima dell'effetto blur ()


134

Ho un campo di input, dove provo a dare suggerimenti per il completamento automatico. Il codice sembra

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

blur()All'evento dell'ingresso voglio nascondere il div dei risultati:

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

Quando scrivo qualcosa nel mio input invio richiesta al server e ottengo una risposta json, analizzandola in ul-> li struttura e inserisco questo ul nel mio #myresultsdiv.

Quando faccio clic su questo elemento li analizzato, voglio impostare il valore da li per inserire e nascondere #myresultsdiv

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

Tutto sta andando bene, ma quando faccio clic sul mio blur()evento li si attiva prima click()e il valore dell'input non ottiene l'html di li.

Come posso impostare un click()evento prima blur()?


quindi quel caso perché usi la funzione di sfocatura? quando il bisogno è già soddisfatto dalla funzione clic.
Owais Iqbal,

Questo probabilmente non cambierà l'ordine in cui vengono attivati ​​i tuoi eventi, ma se blursi attiva davvero dopo aver fatto clic su un li, probabilmente non è necessario eseguire $("#myresults").hide()nel gestore di clic. Quello che sembra stia accadendo è che $(this).html()sta restituendo una stringa vuota. Potresti logo alert $(this).html()per esserne sicuro?
veeTrain,

@OwaisIqbal a volte non ci sono risultati, a volte l'utente non vuole selezionare nulla dai suggerimenti, a volte l'utente non vuole più usare questo input, ma devo nascondere il risultato inutilizzato
Egor Sazanovich,

@veeTrain ci sono molte azioni nei miei gestori, le ho appena minimizzate per capire facilmente il problema nella mia domanda. ps ho provato ad aggiungere watch-point in firebug blur()e click()gestori, non ci sono azioni dopo le blur()fine
Egor Sazanovich,

Sembra che tu abbia bisogno di mettere in coda le funzioni. Prova a dare un'occhiata a questa pagina: stackoverflow.com/questions/1058158/… . La porzione First-In-First-Out (FIFO) potrebbe interessarti
Patriotec,

Risposte:


312

Soluzione 1

Ascolta mousedowninvece di click.

Gli eventi mousedowne blursi verificano uno dopo l'altro quando si preme il pulsante del mouse, ma clicksi verificano solo quando lo si rilascia.

Soluzione 2

È possibile preventDefault()in mousedownper bloccare la discesa dal rubare messa a fuoco. Il leggero vantaggio è che il valore verrà selezionato quando si rilascia il pulsante del mouse, ovvero come funzionano i componenti di selezione nativi. 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
La soluzione 1 ha funzionato per me in questa stessa situazione! Facile cambiamento! Grazie :)
Jon,

Grazie :) Ma puoi spiegare perché l'ascolto di Mousedown invece del clic funziona come un incantesimo?
Mudassir Ali,

3
@MudassirAli perché l'evento mousedown viene prima della sfocatura e il clic viene dopo. jsfiddle.net/f3BKP
Alexey Lebedev

La soluzione n. 1 è secondo me la scelta migliore. Semplice ed efficace Il timeout significherebbe più codificare + più spazio per comportamenti imprevisti (quanto tempo è scaduto? Abbastanza a lungo per registrare il clic, ma non troppo a lungo per confondere l'uso ...).
c24,

5
La soluzione n. 2 è geniale. Non l'avrei mai capito! Grazie
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();
}

VIOLINO


2

Ho affrontato questo problema e l'utilizzo mousedownnon è un'opzione per me.

Ho risolto questo problema utilizzando setTimeoutla funzione gestore

        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

Ho appena risposto a una domanda simile: https://stackoverflow.com/a/46676463/227578

Un'alternativa alle soluzioni di mousedown è che ignora gli eventi di sfocatura causati facendo clic su elementi specifici (ad esempio, nel gestore della sfocatura, salta l'esecuzione se è il risultato di un clic su un elemento specifico).

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

nel mio caso, event.relatedTarget restituisce null, qualche idea sul perché potrebbe essere?
gaurav5430,

ok, ha ottenuto la risposta qui: stackoverflow.com/questions/42764494/...
gaurav5430

0

Le soluzioni Mousedown non funzionano per me, quando faccio clic su elementi non pulsanti. Quindi, ecco cosa ho fatto con la funzione di sfocatura nel mio codice:

.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;
*/
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.