jQuery – Propagación de eventos

Posted on


Hola, tal vez al leer el título de este post parezca o suene medio raro, pero es un tema bastante importante el cual si no se conoce puede causar funcionamientos «extraños» al ejecutar una determinada función jQuery, lo cual podría hacernos pensar que esta mal, cuando realmente no es así, es porque se desconoce como se propagan los eventos.

La propagación de eventos en jQuery describe el flujo de un evento a través de la jerarquía del DOM, cuando un evento es lanzado en un determinado elemento, si existe un manejador para ese evento entonces se ejecuta dicha función, una vez que se ha terminado de procesar el evento es pasado al elemento superior y así sucesivamente.

Esto puede sonar un poco confuso, así que vamos a ilustrarlo, si tenemos algo como:

Se tienen tres divs, uno dentro de otro, y esos divs tienen la clase prop, así entonces definimos el siguiente manejador para el evento clic utilizando jQuery:

   1:   $("div.prop").click(function () {
   2:      alert('Ha dado clic en el div: ' + $(this).attr('id'));
   3:   })

Como selector le decimos que tome todos los div que tengan la clase prop [div.prop], luego que capture el evento click y en el código de la función que por medio de un alert muestre el id del div, esto último accediendo al valor del atributo id.

Y efectivamente cuando damos clic en algún div se muestra el mensaje con el id del control, pero ouch si damos clic en el divNieto luego de mostrar el mensaje con el id divNieto también lo hace para el div hijo y el div padre… es decir nuestro código jQuery no funciona bien ! o mejor aún, no hace lo que lo yo quiero !!

Y efectivamente no hace lo que yo quiero ! Pero no es porque funcione mal… es porque así debe funcionar !!

Ahora bien, porque funciona así? la respuesta esta en el título de este post.. y es porque el evento se propaga !… en otras palabras, cuando se da clic en el divNieto entra al manejador del evento y ejecuta el código necesario, una vez que ha terminado de ejecutarse el código se va al elemento superior, y verifica si para el evento desencadenado (para este caso el click) existe un manejador, como efectivamente si existe entonces entra a la función y ejecuta el código JavaScript, por lo tanto muestra de nuevo el mensaje y de nuevo sucede con el divPadre…uff ya vimos que no es que el código este mal…es que simplemente así es como se realiza la propagación de eventos.

Pero bueno, ya sabemos que nuestro código esta correcto, pero no hace lo que queremos que haga, así que tenemos dos diferentes formas para evitar este «problema»:

  • Retornar false: simplemente añadimos un return false al final de la función.
   1:   $("div.prop2").click(function () {
   2:      alert('Ha dado clic en el div: ' + $(this).attr('id'));
   3:      return false;
   4:   })
  • Hacer uso del evento stopPropagation: Una solución en mi opinión mas bonita, primero declaramos una variable en la firma de la función (en el ejemplo uso e) y en lugar de retornar false le decimos e.stopPropagation()
   1:  $("div.prop3").click(function (e) {
   2:      alert('Ha dado clic en el div: ' + $(this).attr('id'));
   3:      e.stopPropagation();
   4:  })

Bueno espero que este post les sea de utilidad y les pueda ahorrar muchos dolores de cabeza y sobre todo que haya quedado claro que es la propagación de eventos.

Les dejo el ejemplo en donde el primera medida se propaga el evento, y luego se detiene haciendo uso del return false y el stopPropagation:

Descarga del ejemplo !

6 comentarios sobre “jQuery – Propagación de eventos

    Juanquex escribió:
    04/06/2012 en 11:30

    Muy interesante sigue así!

    adriandegenhardt escribió:
    02/15/2013 en 10:31

    Tengo un problema similar usando imageTick para usan una imagen en vez de un checkbox, los que realizaron la maqueta incluyeron el input dentro de una etiqueta label esta me propaga el click y hace que el check se tilde y se vuelva a destildar. Capture el click del label y use e.stopPropagation() y también return false; en ninguno de los dos casos pude detener la propagación del click a la imagen que esta dentro del label.
    El Codigo seria este:

    Html:

    Script:

    $(document).ready(function(){
    $.imageTick.logging = true;
    $(«input[type=’checkbox’]»).imageTick({
    tick_image_path: «/JFP/regional/images/elementos/check_1.png»,
    no_tick_image_path: «/JFP/regional/images/elementos/no_check_1.png»
    });

    $(«label[id=’lbCheck’]»).click(function(e){
    e.stopPropagation();
    });
    });

      Julio Avellaneda respondido:
      03/12/2013 en 09:17

      hola, bueno la verdad esta raro, pero creo q la mejor solución seria acomodar tu html para no usar la anidación que comentas, igual has probado colocar el return false en el imagetick?

        adriandegenhardt escribió:
        03/12/2013 en 09:21

        Debido a que no podía tocar la maqueta por que asi nos las entregan modifique el código de imageTick agregando un e.preventDefault(); antes del trigger que llama al click del check y funciono, muchas gracias por la respuesta.

        Julio Avellaneda respondido:
        03/12/2013 en 09:22

        Vale amigo, cualquier cosa me cuentas.

        Saludos!

Replica a Julio Avellaneda Cancelar la respuesta