Eventos JavaScript

D

Hola!

Estoy realizando un pequeño proyectillo y haciendo una cosa que en un principio puede ser una chorrada me he encontrado con lo siguiente:

Supongamos que tengo un elemento A que se abre con un click en un botón B y se cierra cuando haces click fuera de A. Para ello bindeo el click en B, y como manejador pongo una función que seria tal que:

function abrir(){
     //cosas
     $(B).bind('clickoutside',cerrar);
}

En este caso para el evento clickoutside estoy utilizando este plugin de jquery http://benalman.com/code/projects/jquery-outside-events/examples/clickoutside/

El problema que me he encontrado es que se esto entra en condición de carrera con el propio bubbling del click en A, con lo que, tras llegar el click al document, detecta que es clickoutside de B y se cierra. Lo lógico sería hacer un preventdefault en abrir, pero si hago esto y tengo en la web otros elementos que se cierran con clickoutside no se cerrarán, ya que no he permitido el bubbling en el click.

Buscando por internet he encontrado que "la solución" es meter el bind del evento clickoutside en un setTimeout con 0 ms de retardo, de esta manera primero se resuelve la pila de eventos de js, y luego hace el bind, con lo que no se cerraría instantaneamente. Sabeis si existe alguna otra solución aceptable que no sea meterlo dentro de un settimeout?

AkroS

Lo raro es que sabiendo que es event bubbling no hayas dado con la solución buena :D
Prueba event.stopPropagation() en el bind del click A.
https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation

D

Si hago eso también estoy evitando que el resto de handlers de clickoutside se ejecuten y no es la intención :(

smintcs

el stopPropagation va dentro del handler B, ademas diria que el binding para cerrar A lo estas haciendo cada vez que se hace click en B, debería hacerse una sola vez al principio

bindeo A:
cerrar

bindeo B:
stopPropagation
abrir

cuando pulsa en B se abre y no se cierra por el stop propagation
cuando pulsa en A se cierra

D

Si evito la propagación en B no se dispararían los clickoutside del resto de elementos, y como he comentado antes la idea no es esa. En teoria con el setTimeout(fn,0) se lanza la función fn en el primer tick disponible tras consumir la pila de eventos, mi duda es si existe otra solución que no sea esa.

KoRMuZ

#1 Si quieres que se cierre cuando hagas click en algo que no es A, tienes un selector en jQuery que es ":not" así que, si no recuerdo mal, pero la sintaxis puede no ser correcta, con

$(":not(A)").bind('click', functionguapatuyaparacerrar);

O algo por el estilo, debería funcionar.

Como ya te digo, no recuerdo la sintaxis, pero el selector es ese.

smintcs

https://plnkr.co/edit/x2CQemYiz0gr3pL7YHDK?p=preview

Usuarios habituales