Utilizar un evento como objeto

Una vez que se desencadena un evento es posible utilizarlo como objeto en JavaScript. Además que, dependiendo el que modelo se esté utilizando, el evento sigue un flujo a través del DOM.

Evento

Una vez que asociamos un evento a una acción podemos incluir como parámetro el evento que se ejecutó. Al hacer esto, el evento está disponible como objeto – con atributos y métodos -.

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo</title>
  </head>
  <body>
    <div id='contenedor'>
            <h1>Soy un título</h1>
      <p id='parrafo' >
        Ejemplo
      </p>
    </div>
  </body>
  <script>
  var parrafo = document.getElementById("parrafo")
  parrafo.addEventListener("click", parrafo_click)
 function parrafo_click(e) {
   console.log(e)
 }  
  </script>
</html>

Esto nos permite tener más control sobre la funcionalidad que queremos desarrollar, además de que posible modificar el comportamiento predeterminado que el evento tiene en el navegador.

Algunos atributos del evento son:

Atributo Descripción
target Elemento que tiene el evento asociado.
currentTarget Elemento en donde se está aplicando el evento.
altKey Indica si está presionada la tecla ALT cuando se da un clic
ctrlKey Indica si está presionada la tecla CTRL cuando se da un clic
shiftKey Indica si está presionada la tecla SHIFT cuando se da un clic
type Tipo de evento que se realizó.
pageX / pageY Tiene las coordenadas del cursor donde se dio un click

Es posible que algunos atributos y métodos cambien dependiendo del tipo de evento.

Captura y Propagación

La captura y propagación son modelos que determinan qué evento se desencadena primero cuando un nodo hijo y un nodo padre tienen asociado el mismo evento.

Captura

Este modelo analiza el documento desde el nodo raíz hacia el nodo sobre el cuál se desarrollo el evento.
En este caso se desencadena primero el evento en el nodo padre y después en el nodo hijo.

Captura de eventos.
<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Captura</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];
   
   titulo.addEventListener('click', rastrear_evento ,true);
   contenido.addEventListener('click', rastrear_evento, true);
   contenedor.addEventListener('click', rastrear_evento, true);   
   body.addEventListener('click', rastrear_evento, true);   
   html.addEventListener('click', rastrear_evento, true);
         
   function rastrear_evento(e) {   
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
   }
  </script>
</html>

Propagación

Este modelo analiza el documento desde el nodo nodo sobre el cuál se desarrollo el evento hacia el nodo padre.
En este caso se desencadena primero el evento en el nodo padre y después en el nodo hijo.

Propagación de eventos
<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Propagación</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>  
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];

   titulo.addEventListener('click', rastrear_evento ,false);
   contenido.addEventListener('click', rastrear_evento, false);
   contenedor.addEventListener('click', rastrear_evento, false);   
   body.addEventListener('click', rastrear_evento, false);   
   html.addEventListener('click', rastrear_evento, false);
   
   function rastrear_evento(e) {   
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
   }
   
  </script>
</html>

Cancelar

Se puede cancelar el flujo de la captura y la propagación utilizando cancelBubble (IE) y stopPropagation (IE9+ / otros).
De esta manera, si otros nodos tienen asociado el mismo evento lo pueden utilizar sin que se mezclen eventos.

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Captura</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];

   titulo.addEventListener('click', rastrear_evento ,true);
   contenido.addEventListener('click', rastrear_evento, true);
   contenedor.addEventListener('click', rastrear_evento, true);   
   body.addEventListener('click', rastrear_evento, true);   
   html.addEventListener('click', rastrear_evento, true);

   function rastrear_evento(e) {   
   	if (!e) {
      var e = window.event;
     }
     // La propiedad cancelBubble solo es soportada por IE 
     // Evita la propagación. 
     // No afecta al funcionamiento en otros navegadores
      e.cancelBubble = true;
   	if (e.stopPropagation) {
        e.stopPropagation();
     }
     
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
   }
   
  
  </script>
</html>

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Propagación</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];
   
   titulo.addEventListener('click', rastrear_evento ,false);
   contenido.addEventListener('click', rastrear_evento, false);
   contenedor.addEventListener('click', rastrear_evento, false);   
   body.addEventListener('click', rastrear_evento, false);   
   html.addEventListener('click', rastrear_evento, false);

   function rastrear_evento(e) {   
     if (!e) {
        var e = window.event;
     }
     // La propiedad cancelBubble solo es soportada por IE 
     // Evita la propagación. 
     // No afecta al funcionamiento en otros navegadores
     e.cancelBubble = true;
     if (e.stopPropagation) {
        e.stopPropagation();
     }
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
   }
   
  
  </script>
</html>

Nota

La w3 – ( especificación / borrador )- implementa ambos modelos.

Oldie (IE6, IE7, IE8) utiliza únicamente el modo de propagación pero IE9+ ya soporta ambos modelos.

Remover Eventos

Para quitar un evento asociado a un nodo con addEventListener se utiliza removeEventListener, si se utilizó attachEvent se utiliza detachEvent.

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Captura</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];
   
   ;(function asociar_eventos() {
     if (titulo.addEventListener) {
       titulo.addEventListener('click', rastrear_evento ,true);
       contenido.addEventListener('click', rastrear_evento, true);
       contenedor.addEventListener('click', rastrear_evento, true);   
       body.addEventListener('click', rastrear_evento, true);   
       html.addEventListener('click', rastrear_evento, true);       
     } else {
       titulo.attachEvent('onclick', rastrear_evento);
       contenido.attachEvent('onclick', rastrear_evento);
       contenedor.attachEvent('onclick', rastrear_evento);   
       body.attachEvent('onclick', rastrear_evento);   
       html.attachEvent('onclick', rastrear_evento);
     }
   }());

   function rastrear_evento(e) {   
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
     remover_eventos();
   }

   function remover_eventos() {
     if (titulo.removeEventListener) {
       titulo.removeEventListener('click', rastrear_evento ,true);
       contenido.removeEventListener('click', rastrear_evento, true);
       contenedor.removeEventListener('click', rastrear_evento, true);   
       body.removeEventListener('click', rastrear_evento, true);   
       html.removeEventListener('click', rastrear_evento, true);         
     } else {
       titulo.detachEvent('click', rastrear_evento);
       contenido.detachEvent('click', rastrear_evento);
       contenedor.detachEvent('click', rastrear_evento);   
       body.detachEvent('click', rastrear_evento);   
       html.detachEvent('click', rastrear_evento);       
     }
   }
  
  </script>
</html>

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Ejemplo - Propagación</title>
    <style>
    #contenedor {width: 940px; height: 500px; border: 1px solid #333; margin: 0 auto;}
    #contenido { width: 500px; height: 200px; margin: 150px auto; background: #555; text-align: center; line-height: 200px;}
    </style>
  </head>
  <body>
    <div id='contenedor'>
      <div id='contenido'>
          <h1>Clic Aquí</h1>
      </div>
    </div>
  </body>
  <script>  
   var titulo = document.getElementsByTagName('h1')[0];
   var contenido = document.getElementById('contenido');
   var contenedor = document.getElementById('contenedor');   
   var body = document.getElementsByTagName('body')[0];
   var html = document.getElementsByTagName('html')[0];
   
   ;(function asociar_eventos() {
     if (titulo.addEventListener) {
       titulo.addEventListener('click', rastrear_evento ,false);
       contenido.addEventListener('click', rastrear_evento, false);
       contenedor.addEventListener('click', rastrear_evento, false);   
       body.addEventListener('click', rastrear_evento, false);   
       html.addEventListener('click', rastrear_evento, false);       
     } else {
       titulo.attachEvent('onclick', rastrear_evento);
       contenido.attachEvent('onclick', rastrear_evento);
       contenedor.attachEvent('onclick', rastrear_evento);   
       body.attachEvent('onclick', rastrear_evento);   
       html.attachEvent('onclick', rastrear_evento);
     }
   }());
   

   
   function rastrear_evento(e) {   
     console.log('El evento: ' + e.type + ' comenzó en: ' + e.target.nodeName + '. Ahora  está en: ' + e.currentTarget.nodeName);
     remover_eventos();
   }
   
   function remover_eventos() {
     if (titulo.removeEventListener) {
       titulo.removeEventListener('click', rastrear_evento ,false);
       contenido.removeEventListener('click', rastrear_evento, false);
       contenedor.removeEventListener('click', rastrear_evento, false);   
       body.removeEventListener('click', rastrear_evento, false);   
       html.removeEventListener('click', rastrear_evento, false);         
     } else {
       titulo.detachEvent('click', rastrear_evento);
       contenido.detachEvent('click', rastrear_evento);
       contenedor.detachEvent('click', rastrear_evento);   
       body.detachEvent('click', rastrear_evento);   
       html.detachEvent('click', rastrear_evento);       
     }
   }
   
   
  </script>
</html>

Por último

Después de estas publicaciones ya tienes el conocimiento básico de qué es el DOM y cómo utilizarlo en JavaScript.