Flujo del evento

El document responde a la estructura jerárquica definida por el modelo de objetos DOM, así en la página verás que los elementos suelen estar contenidos unos en otros. Cuando se produce un evento en un elemento que está anidado en otro u otros ¿que pasa si hay varios elementos que pueden responder al mismo evento?. La respuesta es el flujo de eventos definido en el DOM.

Un ejemplo: el body y los bloques div tienen asignados el evento onclick

<!doctype html>

<html>

<head>

<title>Documento sin título</title>

</head>

<body onclick="console.log('Pulsado en body')">

<div id="div1" onclick="console.log('Pulsado en div1')">

<h1>Cabecera</h1>
<div id="div2" onclick="console.log('Pulsado en div2')">Pulsa aquí</div>

</div>

<p>texto</p>

</body>

</html>

Ahora supón que haces click en el bloque div más interno, el que tiene id = "div2" y contenido Pulsa aquí. Al producirse esta acción el navegador capturará el evento recorriendo el DOM desde la raiz (document) hasta el elemento más profundo donde se ha producido el click.

En ese elemento ejecuta el manejador asociado. En el ejemplo verás en la consola la frase "Pulsado en div2"

Una vez ha terminado con el elemento más profundo, la señal del evento vuelve hacia arriba en el árbol y cada vez que encuentra un onclick en su camino ejecuta su función asociada. El evento asciende como una burbuja, de ahí el nombre inglés para ete proceso: bubble

Ejecuta el código del ejemplo en una ventana con el panel de desarrollador abierto, verás como aparecen las frases

Pulsado en div2
Pulsado en div1
Pulsado en body

En esta imagen puedes ver como es el flujo del evento a lo largo del árbol DOM de este documento (muy esquematizado). En rojo la primera fase, en busca del elemento más profundo capaz de responder. En azul el regreso a la raiz ejecutando en su camino cada función asociada.

Flujo de evetnos del DOM

Lógicamente si pulsas en el bloque h1 no se imprimirá Pulsado en div2, solo Pulsado en div1 y Pulsado en body.

Con el método event.stopPropagation() puede cortarse esta cadena o ascenso del evento por el árbol DOM.

Detalles

El documento web tiene una estructura jerárquica tipo árbol, donde los elementos de la página (párrafos, imagenes, bloques div, secciones, etc) y atributos (href, src, style...) son nodos.

Para alcanzar cualquier elemento es necesario recorrer el árbol desde el nodo raíz ( máximo nivel jerárquico) pasando por todos los nodos intermedios hasta alcanzar el elmento buscado.

Este recorrido se lleva a cabo cuando se produce alguna acción para encontrar los elementos que pueden responder a el evento provocado por la acción.

Existen dos fases descritas en el DOM, resumidas son:

  1. Buscar el elemento más profundo destinatario de la acción
  2. Volver a la raiz del documento ejecutando los manejadores de cada nodo

De esta manera se ejecutan todos los manejadores de un evneto desde el nodo más profundo hasta el más próximo a la raiz.

El evento asciende por el arbol como una burbuja, de ahi el nombre de bubble de este comportamiento.

El últmo manejador ejecutado es el manejador por defecto del evento, si existe. Se puede evitar con el método del evento preventDefaul().

La propagación del evento se puede cortar con el evento stopPropagation() ejecutada en cualquiera de los manejadores del evento.