Ver índice de contenidos del libro

6.3. Handlers y listeners

En las secciones anteriores se introdujo el concepto de "event handler" o manejador de eventos, que son las funciones que responden a los eventos que se producen. Además, se vieron tres formas de definir los manejadores de eventos para el modelo básico de eventos:

  1. Código JavaScript dentro de un atributo del propio elemento HTML
  2. Definición del evento en el propio elemento HTML pero el manejador es una función externa
  3. Manejadores semánticos asignados mediante DOM sin necesidad de modificar el código HTML de la página

Cualquiera de estos tres modelos funciona correctamente en todos los navegadores disponibles en la actualidad. Las diferencias entre navegadores surgen cuando se define más de un manejador de eventos para un mismo evento de un elemento. La forma de asignar y "desasignar" manejadores múltiples depende completamente del navegador utilizado.

6.3.1. Manejadores de eventos de Internet Explorer

La familia de navegadores de Internet Explorer emplean los métodos attachEvent() y detachEvent() para asociar y desasociar manejadores de eventos. Todos los elementos y el objeto window disponen de estos métodos.

Los métodos requieren dos parámetros: el nombre del evento que se quiere manejar y una referencia a la función encargada de procesar el evento. El nombre del evento se debe indicar con el prefijo on incluido, como muestra el siguiente ejemplo:

function muestraMensaje() {
  alert("Has pulsado el ratón");
}
var elDiv = document.getElementById("div_principal");
elDiv.attachEvent("onclick", muestraMensaje);
 
// Más adelante se decide desasociar la función del evento
elDiv.detachEvent("onclick", muestraMensaje);

Asociar más de una función al mismo evento es igual de sencillo:

function muestraMensaje() {
  alert("Has pulsado el ratón");
}
 
function muestraOtroMensaje() {
  alert("Has pulsado el ratón y por eso se muestran estos mensajes");
}
 
var elDiv = document.getElementById("div_principal");
elDiv.attachEvent("onclick", muestraMensaje);
elDiv.attachEvent("onclick", muestraOtroMensaje);

Si el usuario pincha sobre el <div>, se muestran los dos mensajes de aviso que se han asignado al evento.

Se pueden mezclar incluso diferentes técnicas para asociar múltiples manejadores de eventos a un mismo evento de un elemento. El siguiente ejemplo utiliza la asignación semántica de manejadores para asignar el primer manejador y la función attachEvent() para asignar el segundo manejador. El resultado final es igual al del ejemplo anterior:

var elDiv = document.getElementById("div_principal");
elDiv.onclick = muestraMensaje;
elDiv.attachEvent("onclick", muestraOtroMensaje);

Sin embargo, no es posible asignar múltiples eventos mediante las propiedades de DOM:

var elDiv = document.getElementById("div_principal");
elDiv.onclick = muestraMensaje;
elDiv.onclick = muestraOtroMensaje;

6.3.2. Manejadores de eventos de DOM

La especificación DOM define otros dos métodos similares a los disponibles para Internet Explorer y denominados addEventListener() y removeEventListener() para asociar y desasociar manejadores de eventos.

La principal diferencia entre estos métodos y los anteriores es que en este caso se requieren tres parámetros: el nombre del "event listener", una referencia a la función encargada de procesar el evento y el tipo de flujo de eventos al que se aplica.

El primer argumento no es el nombre completo del evento como sucede en el modelo de Internet Explorer, sino que se debe eliminar el prefijo on. En otras palabras, si en Internet Explorer se utilizaba el nombre onclick, ahora se debe utilizar click.

Si el tercer parámetro es true, el manejador se emplea en la fase de capture. Si el tercer parámetro es false, el manejador se asocia a la fase de bubbling.

A continuación, se muestran los ejemplos anteriores empleando los métodos definidos por DOM:

function muestraMensaje() {
  alert("Has pulsado el ratón");
}
var elDiv = document.getElementById("div_principal");
elDiv.addEventListener("click", muestraMensaje, false);
 
// Más adelante se decide desasociar la función al evento
elDiv.removeEventListener("click", muestraMensaje, false);

Asociando múltiples funciones a un único evento:

function muestraMensaje() {
  alert("Has pulsado el ratón");
}
 
function muestraOtroMensaje() {
  alert("Has pulsado el ratón y por eso se muestran estos mensajes");
}
 
var elDiv = document.getElementById("div_principal");
elDiv.addEventListener("click", muestraMensaje, true);
elDiv.addEventListener("click", muestraOtroMensaje, true);

Si se asocia una función a un flujo de eventos determinado, esa función sólo se puede desasociar en el mismo tipo de flujo de eventos. Si se considera el siguiente ejemplo:

function muestraMensaje() {
  alert("Has pulsado el ratón");
}
var elDiv = document.getElementById("div_principal");
elDiv.addEventListener("click", muestraMensaje, false);
 
// Más adelante se decide desasociar la función al evento
elDiv.removeEventListener("click", muestraMensaje, true);

La última instrucción intenta desasociar la función muestraMensaje en el flujo de eventos de capture, mientras que al asociarla, se indicó el flujo de eventos de bubbling. Aunque la ejecución de la aplicación no se detiene y no se produce ningún error, la última instrucción no tiene ningún efecto.