2011-02-04 4 views
27

Hay dos elementos en juego:Acción sobre la falta de definición, excepto cuando el elemento específico hace clic con jQuery

$('#myInput') // an input field for search 
$('#myList') // a list to display search results 

quiero ocultar la lista cuando la entrada ya no tiene el foco, así:

$('#myInput').blur(function() { 
    $('#myList').hide(); 
}); 

Esto funciona muy bien, excepto cuando se hace clic en un elemento de la lista, porque el evento de desenfoque dispara y oculta la lista antes de registrar el clic. El objetivo es que la lista permanezca visible cuando se hace clic en cualquier parte de la lista, aunque esto hará que la entrada se vuelva borrosa.

¿Cómo puedo hacer esto? ¡Gracias!

Respuesta

13

Usted puede lograr esto manteniendo una variable global, y setTimouts, a espere un retraso de 200ms y luego verifique si uno de los 2 elementos tiene foco.

var keepFocus = false; 

function hideList(){ 
    if(!keepFocus){ 
     $('#myList').hide(); 
    } 
} 

$('#myInput').blur(function() { 
    keepFocus = false; 
    window.setTimeout(hideList, 200); 
}).focus(function(){ 
    keepFocus = true; 
}); 


$('#myList').blur(function() { 
    keepFocus = false; 
    window.setTimeout(hideList, 200); 
}).focus(function(){ 
    keepFocus = true; 
}); 
+0

el desenfoque y el enfoque no parecen funcionar con #myList ya que no es una entrada. –

+0

@Justin, ¿qué es? Intente eliminar el método 'focus' de la lista y coloque el código' blur' en su lista 'click' event –

+0

Es solo un div. Sin embargo, he adaptado tu código para que funcione con mi configuración, ¡gracias! –

11

Debe poder decir "hacer este desenfoque() a menos que la lista gane enfoque al mismo tiempo".

Esta pregunta dice cómo detectar si un elemento tiene el foco: Using jQuery to test if an input has focus

Entonces todo lo que necesita hacer es:

$("#myInput").blur(function() { 
    if (!$("#myList").is(":focus")) { 
     $("#myList").hide(); 
    } 
}); 
+4

Parece que no funciona. document.activeElement muestra la etiqueta del cuerpo como el elemento "centrado". Supongo que no funciona porque la idea de "foco" está intrínsecamente vinculada a los campos de entrada. –

1

La mejor manera de hacer esto es conectar un controlador de eventos para el elemento del cuerpo, y luego otro manejador de la lista que se detiene de propagación de eventos:

$(body).click(function() { 
    $("#myList").hide(); 
}); 

$("#myList").click(function (e) { 
    e.stopImmediatePropagation(); 
}); 

Esta escucha por un clic fuera de # myInput y oculta #myList. Al mismo tiempo, la segunda función escucha un clic en # myList y, si ocurre, impide que hide() se active.

+4

Esto está ignorando el teclado. La desenfoque se dispara cuando se quita un campo de pestañas. –

7

Me he enfrentado exactamente con el mismo problema, así que así es como lo resolví.

Se me ocurrió el hecho de que blur() dispara antes que .

por lo que he tratado de cambiar click() a mousedown() y descubrió que mousedown() incendios antes blur().

Y imitar click() que tendrá que disparar mousedown() y luego mouseup()

Así que en su caso me gustaría hacer algo como esto:

var click_in_process = false; // global 

$('#myList').mousedown(function() { 
    click_in_process = true; 
}); 

$('#myList').mouseup(function() { 
    click_in_process = false; 
    $('#myInput').focus(); 

    // a code of $('#myList') clicking event 

}); 

$('#myInput').blur(function() { 
    if(!click_in_process) { 
     $('#myList').hide(); 

     // a code of what you want to happen after you really left $('#myInput') 

    } 
}); 

Demo/ejemplo: http://jsfiddle.net/bbrh4/

Esperanza ¡ayuda!

+1

¿Qué sucede si el orden de los eventos es diferente en un navegador o dispositivo específico? Si recuerdo correctamente este orden no está definido. – Gherman

+1

@German Funcionó correctamente en todos los dispositivos y navegadores que tenía en ese momento (como recuerdo Chrome/Firefox/Opera/IE/iOS/Android/WP). Tal vez algo ha cambiado, pero para ser sincero, lo dudo. Pero si tiene algún ejemplo específico en mente, estaré encantado de saberlo. Y si es cierto, recomendaría escribir un servicio/ayudante/biblioteca, donde podría hacer diferentes lógicas dependiendo del navegador o dispositivo actual. –

+1

No tengo ningún mal ejemplo. Solo estaba siendo extremadamente cauteloso. Teóricamente, el orden de los eventos no está definido en los estándares. – Gherman

Cuestiones relacionadas