sábado, 21 de agosto de 2010

Ocultar elemento flotante al dar click fuera de él con jQuery


Durante el desarrollo de un plugin de jQuery ya hace mucho tiempo me encontre con el problema de hacer desaparecer un elemento flotante cuando daban click fuera de él. Como la historia tiende a repetirse hoy me he encontrado con el mismo problema.

Elementos:
Lista - Elemento Flotante
Boton - Encargado de mandar a mostrar la lista

Solucion:

Asigno un manejador de eventos al click del document, en el cual valido 4 cosas
1) La lista este visible
2) El click no sea generado por la lista
3) El click no sea generado por el boton
4) El click no sea generado por algun elemento dentro de la lista

Si el conjunto de estas condiciones se cumple entonces oculto el elemento.

Bueno el primer paso es facil

var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible')){ //Facil
alert('Oculta la lista');
}
});

Comparacion de objetos.

Parace facil, solo comparo los objetos y ya quedo. Pero, ¡Oh sorpresa! no se puede ralizar una comparación de la forma:


var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible') && $(event.target) != oMiLista){
alert('Oculta la lista');
}
});

Esto es por que la comparación se debe de realizar con los objetos en bruto. Con lo cual la comparación quedaria de la siguiente manera:

var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible') && event.target != oMiLista[0]){//event.target == oMiElemento.get(0)
alert('Oculta la lista');
}
});

Bueno, con esto se solucionan los pasos 2 y 3, ahora hay que buscar entre los elementos de la lista. Para esto busco los elementos padres del event.target con la funcion parents(), mapeo los elementos resultantes y los devuelvo en bruto, generando un arreglo con ellos. Por ultimo valido que la lista no se encuentre dentro del arreglo con la funcion inArray(), la cual tiene que devolver el valor -1. Asi que todo esto quedaria de la siguiente manera:


var oMiLista = $('#foo');
var oMiBoton = $('#bar');
$(document).bind('click',function(event){
if(oMiElemento.is(':visible') &&
event.target != oMiLista[0]&&
event.target != oMiBoton[0]&&
jQuery.inArray(oMiLista[0],$(event.target).parents().map(function(){return this}).get()) == -1
{
alert('Oculta la lista');
}
});


Les dejo un ejemplo practico aqui, espero que les sea de ayuda.

Saludos

1 comentario:

Unknown dijo...

hola muchas gracias por el tutorial, pero yo necesito que inicialmente el div este visible y que al hacer click dentro de el se oculte, esto para para poner un div sobre un iframe y así el primer click le salte un po up al usuario, y se oculte para que así pueda utilizar el iframe que es un reproductor