Burbujeo y captura de eventos (DOM)

Hay dos formas de la propagación de eventos en el DOM de HTML, burbujeantes y captura.

La propagación de eventos es una forma de definir el orden de los elementos cuando se produce un evento. Si usted tiene un <p> elemento dentro de un <div> elemento, y el usuario hace clic en el <p> elemento, que de elemento de "click" evento debe ser manejada por primera vez?

En caso de que el burbujeo de la mayor parte del elemento interior se maneja primero y luego el exterior: el <p> Haga clic en el evento del elemento se maneja en primer lugar, a continuación, el <div> Haga clic en el evento del elemento. En caso de que el capturar la mayor parte del elemento exterior se maneja primero y luego el interior: el <div> Haga clic en el evento del elemento será tratada en primer lugar, a continuación, el <p> Haga clic en el evento del elemento.

Con la addEventListener() método que se puede especificar el tipo de propagación mediante el uso de la "useCapture" parámetro:

addEventListener( event , function , useCapture );

El valor predeterminado es falso, que utilizará la propagación burbujeo, cuando el valor se establece en true, el evento utiliza la propagación de captura.

<!DOCTYPE html>
<html>
<head>
<style>
div {
    background-color: coral;
    border: 1px solid;
    padding: 50px;
}
</style>
</head>
<body>
<p>Este ejemplo demuestra la diferencia entre burbujear y capturar al agregar detectores de eventos.</p>

<div id="myDiv">

  <p id="myP">Haga clic en este parrafo, estoy burbujeando.</p>
</div><br>
<div id="myDiv2">

  <p id="myP2">Haga clic en este parrafo, estoy capturando.</p>
</div>
<script>

document.getElementById("myP").addEventListener( "click", function() { alert("Hiciste click en el elemento P! burbujeando");}, false);
document.getElementById("myDiv").addEventListener("click", function() {alert("Hiciste click en el elemento DIV ! burbujeando");}, false);
document.getElementById("myP2").addEventListener("click", function() { alert("Hiciste click en el elemento P! capturando");}, true);
document.getElementById("myDiv2").addEventListener("click", function() { alert("Hiciste click en el elemento DIV! capturando");}, true);
</script>
</body>

</html>

El DOM permite capturar los eventos producidos en dos órdenes distintos. Si al tercer parámetro del método addEventListener le pasamos un valor false, luego el evento se captura primero por el objeto que produjo el evento y luego es capturado por todos los otros objetos superiores que capturan dicho evento. En caso de pasar el valor true, el evento es capturado por objetos que pertenecen a niveles superiores del DOM para luego ser capturado por el objeto que disparó el evento.

En el ejemplo que desarrollaremos dispondremos una serie de div, unos contenidos en otros y veremos las dos formas de capturar los eventos:

<!DOCTYPE html>
<html>
<head>
<title>Problema</title>
<script>
window.addEventListener('load',inicializarEventos,false);

function inicializarEventos()
{
  var ob=document.getElementById('div1i');
  ob.addEventListener('click',presionRecuadroInte,false);
  ob=document.getElementById('div1e');
  ob.addEventListener('click',presionRecuadroExte,false);
  ob=document.getElementById('div2i');
  ob.addEventListener('click',presionRecuadroInte,true);
  ob=document.getElementById('div2e');
  ob.addEventListener('click',presionRecuadroExte,true);
}

function presionRecuadroInte()
{
  alert('se presionó el recuadro interior');
}

function presionRecuadroExte()
{
  alert('se presionó el recuadro exterior');
}
</script>
<Style>
.recuadrointerior {
  font-family:Courier;
  font-size:12px;
  background-color:#ffffcc;
  border-width:1px;
  border-style:dotted;
  border-color:#ffaa00;
  padding:20px;
}
.recuadroexterior {
  font-family:Courier;
  font-size:12px;
  background-color:#ff9900;
  border-width:1px;
  border-style:dotted;
  border-color:#ffaa00;
  padding:20px;
}
</Style>
</head>
<body>
<h1>Presione con el mouse en el recuadro interior y en el recuadro exterior.</h1>
<h3>Si disponemos false en el tercer parámetro de la función addEventListener</h3>
<div id="div1e" class="recuadroexterior">
Este es contenido del recuadro exterior.
<div id="div1i" class="recuadrointerior">
Este es contenido del recuadro interior.
</div>
También es contenido del recuadro exterior.
</div>
<h3>Si disponemos true en el tercer parámetro de la función addEventListener</h3>
<div id="div2e" class="recuadroexterior">
Este es contenido del recuadro exterior.
<div id="div2i" class="recuadrointerior">
Este es contenido del recuadro interior.
</div>
También es contenido del recuadro exterior.
</div>
</body>
</html>

El código javascript es:

window.addEventListener('load',inicializarEventos,false);

function inicializarEventos()
{
  var ob=document.getElementById('div1i');
  ob.addEventListener('click',presionRecuadroInte,false);
  ob=document.getElementById('div1e');
  ob.addEventListener('click',presionRecuadroExte,false);
  ob=document.getElementById('div2i');
  ob.addEventListener('click',presionRecuadroInte,true);
  ob=document.getElementById('div2e');
  ob.addEventListener('click',presionRecuadroExte,true);
}

function presionRecuadroInte()
{
  alert('se presionó el recuadro interior');
}

function presionRecuadroExte()
{
  alert('se presionó el recuadro exterior');
}

Primero registramos el evento click para los dos primeros div:

  var ob=document.getElementById('div1i');
  ob.addEventListener('click',presionRecuadroInte,false);
  ob=document.getElementById('div1e');
  ob.addEventListener('click',presionRecuadroExte,false);

Como podemos observar indicamos en el tercer parámetro el valor false, con esto logramos que cuando se dispare el evento click primero lo capture el div interior y luego el div exterior.

  ob=document.getElementById('div2i');
  ob.addEventListener('click',presionRecuadroInte,true);
  ob=document.getElementById('div2e');
  ob.addEventListener('click',presionRecuadroExte,true);

Si pasamos como parámetro a la función addEventListener el valor true significará que si presionamos el botón del mouse dentro del div interior primero se dispara el evento del div exterior y por último se dispara el evento click del div interior.