jQuery: clic de fuego () antes del evento blur ()

134

Tengo un campo de entrada, donde trato de hacer una sugerencia de autocompletar. El código se parece a

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

En el blur()evento de entrada, quiero ocultar los resultados 'div:

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

Cuando escribo algo en mi entrada, envío una solicitud al servidor y obtengo una respuesta json, la analizo en la estructura ul-> li y pongo esta ul en mi #myresultsdiv.

Cuando hago clic en este elemento li analizado, quiero establecer el valor de li para ingresar y ocultar #myresultsdiv

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

Todo va bien, pero cuando hago clic en mi blur()evento li se activa antes click()y el valor de entrada no obtiene el html de li.

¿Cómo puedo configurar un click()evento antes blur()?

Egor Sazanovich
fuente
Entonces, ¿por qué usas la función de desenfoque? cuando su necesidad ya está satisfecha con la función de clic.
Owais Iqbal
Esto probablemente no cambiará el orden en que se activan sus eventos, pero si blurrealmente se dispara después de hacer clic en un li, entonces probablemente no necesite ejecutar $("#myresults").hide()en el controlador de clics. Lo que parece que está sucediendo es que $(this).html()está devolviendo una cadena vacía. ¿Podría usted logo alert $(this).html()para asegurarse?
veeTrain
@OwaisIqbal a veces no hay resultados, a veces el usuario no quiere seleccionar nada de las sugerencias, a veces el usuario ya no quiere usar esta entrada, pero debo ocultar el resultado no utilizado
Egor Sazanovich
@veeTrain hay muchas acciones en mis controladores, las minimicé para comprender fácilmente el problema en mi pregunta. PD: He intentado agregar un punto de observación en Firebug blur()y click()controladores, no hay acciones después de que blur()finalice
Egor Sazanovich
Parece que necesita poner en cola las funciones. Intente echar un vistazo a esta página: stackoverflow.com/questions/1058158/… . La porción de Primero en entrar, primero en salir (FIFO) puede pertenecer a usted
Patriotec

Respuestas:

312

Solución 1

Escuche en mousedownlugar de click.

Los eventos mousedowny blurse producen uno tras otro cuando presiona el botón del mouse, pero clicksolo ocurre cuando lo suelta.

Solución 2

Puede preventDefault()en mousedownbloquear el menú desplegable de robar el foco. La ligera ventaja es que el valor se seleccionará cuando se suelte el botón del mouse, que es cómo funcionan los componentes de selección nativos. 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
fuente
12
¡La solución 1 funcionó para mí en esta misma situación! Cambio fácil! Gracias :)
Jon
Gracias :) Pero, ¿puedes explicar por qué escuchar el mousedown en lugar del clic funciona de maravilla?
Mudassir Ali
3
@MudassirAli porque el evento de mousedown ocurre antes del desenfoque, y el clic aparece después. jsfiddle.net/f3BKP
Alexey Lebedev
La solución n. ° 1 es, en mi opinión, la mejor opción. Simple y efectivo. El tiempo de espera significaría más para codificar + más espacio para un comportamiento inesperado (¿cuánto tiempo de espera? El tiempo suficiente para registrar el clic, pero no demasiado para confundir el uso ...).
cw24
55
La solución n. ° 2 es ingeniosa. ¡Nunca lo habría descubierto! Gracias
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();
}

VIOLÍN

adeneo
fuente
2

Enfrenté este problema y usar mousedownno es una opción para mí.

Resolví esto usando setTimeoutla función de controlador

        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
fuente
2

Acabo de responder una pregunta similar: https://stackoverflow.com/a/46676463/227578

Una alternativa a las soluciones de mousedown es hacer que ignore los eventos de desenfoque causados ​​al hacer clic en elementos específicos (es decir, en su controlador de desenfoque, omita la ejecución si es el resultado de hacer clic en un elemento específico).

$("#myinput").live('blur',function(e){
     if (!e.relatedTarget || !$(e.relatedTarget).is("#myresults ul li")) {
         $("#myresults").hide();
     }
});
dule
fuente
en mi caso, event.relatedTarget devuelve nulo, ¿alguna idea de por qué podría ser eso?
gaurav5430
ok, obtuve la respuesta aquí: stackoverflow.com/questions/42764494/…
gaurav5430
0

Las soluciones de mousedown no me funcionan cuando hago clic en elementos que no son botones. Entonces, esto es lo que he hecho con la función de desenfoque en mi código:

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