jQuery: Detectar evento click fuera de un elemento

jQuery: Detectar evento click fuera de un elemento

Hoy os voy a hablar de un truquito en jQuery al que tuve que recurrir hace poco en uno de los proyectos que llevamos a cabo. La página en cuestión al que se lo apliqué es a: http://cincua.es/formacion/cursos.php

Si abajo seleccionáis alguna opción en formación veréis que se abre una ventanita desplegable donde seleccionamos el curso que queremos descargar y si no queremos alguna basta con hacer click fuera del recuadro emergente que sale para que se cierre. Esto está hecho con jQuery pero al inicio tenía un problema… siempre que hacía click para que apareciera dicha ventana nunca aparecía.

Esto se debía a que por código tengo programado que al hacer clic en el elemento body del HTML (es decir, en cualquier elemento de la página) oculto las ventanas emergentes. Pero si tengo programado que al hacer click en uno de los distintos tipos de cursos aparezca la ventana… ¿por qué no se muestran? Fácil, porque cuando haces click en un elemento primero se ejecuta el de mayor jerarquía, es decir el elemento body antes que el elemento del curso.

Para solucionarlo debemos manipular los eventos y parando su propagación. Para ello hacemos algo como lo siguiente:

$('body').click(function() {
    /* Aqui se esconden los menus que esten visibles*/
});

$('#dropList').click(function(e){
    /* Mostrar nuestro menú*/
    e.stopPropagation();
});

La propagación consiste en que cuando hago click en un evento, se ejecuta desde la etiqueta que hemos pulsado hasta la superior. Es decir, si hago click en el elemento cuya id es #dropList y que se encarga de mostrar ese elemento, tras ese buscará el siguiente elemento click superior (la etiqueta padre del elemento), seguido de la superior de ese, seguido de la superior de ese…

Así hasta llegar al elemento html que es el superior. Como el elemento body está por encima jerárquicamente y es donde me encargo de ocultar los menús, éste es el último en ejecutarse al hacer click y siempre me los esconde.

La línea clave está en la función e.stopPropagation(); donde obligo al evento a dejar de ejecutarse. Así cuando hago click en el elemento de id #dropList , ejecuta el código y al llegar a dicha función ya no se ejecuta el evento click del elemento superior. Así nunca se acaba ejecutando el del body y no me oculta los elementos.