Trabajando Con Eventos En Netscape 6
By Scott Andrew LePera
Noviembre 30, 2000
Traducción al español de Jose Luis Pumarega y Fernando Gutierrez.
Este artículo es una toma de contacto con el modelo de eventos en Netscape 6 y Mozilla. He tratado de tocar los puntos principales de modo que puedas gastar menos tiempo leyendo aburridos tutoriales como este y emplear más tiempo en hacer cosas divertidas en la web. Que no te asusten los eventos; ¡Son tus amigos!.
Deberás usar Netscape 6 o una versión reciente de Mozilla para ver los ejemplos del tutorial. También ayudará que te leas Scripting For The 6.0 Browsers antes de leer esto, pero hey, yo no soy tu madre.
Una Carretera De Dos Sentidos
Echemos un vistazo a cómo los navegadores 4.x manejan los eventos. Cuando un evento ocurre en un documento web, como cuando se pulsa en un enlace, un objeto especial llamado event object se crea. El objeto event almacena datos acerca del evento específico que ha ocurrido, como las coordenadas del ratón, el tipo de evento (click, onmouseover, et al.), qué teclas fueron pulsadas en el momento de producirse el evento, y así. El desarrollador puede escribir funciones especiales llamadas event handlers (menejadores de eventos) para interceptar e inspeccionar el objeto event y contestar adecuadamente.
En Netscape, los objetos event se representan normalmente por una "e" minúscula, mientras que en Internet Explorer el objeto event es una propiedad del objeto window, llamado window.event.
Cuando se produce un evento, no se queda quieto en el mismo foco en el que ocurrió. En cambio, viaja a través del documento, en cascada a través de los elementos de al página hasta que no puede viajar más. La dirección en la que viaja -y el camino que toma hasta llegar allí-depende del navegador que uses. En Netscape, los eventos viajan hacia dentro hasta el blanco del evento. En Internet Explorer los eventos viajan hacia fuera, hasta la ventana del navegador.
Para clarificar esto, debemos examinar los conceptos de captura de eventos y burbujeo de eventos.
La Captura de eventos fue introducida por Netscape. El navegador Netscape, te permite "capturar" eventos en cuanto caen el el elemento de la página que es objeto de ese evento. Por ejemplo, cuando pulsas un enlace, el evento comienza en el document y viaja hacia el enlace. Usando captura de eventos (a través del método de Navigator captureEvents) puedes capturar el evento en el documento antes de que este llegue al enlace. Puedes usar entonces un handler (o manejador de eventos) especial para realizar tareas específicas hacia, o con, los datos del objeto evento, antes de que el evento llegue hasta el enlace. Lo básico de esta aproximación es que el evento nunca volverá hacia los elementos padres que contienen el elemento objeto del evento de nuevo.
Captura de eventos:
document -> etiqueta de enlace -> texto del enlace
Internet Explorer introdujo el concepto de Burbujeo de eventos (o event bubbling). En Internet Explorer los eventos se mueven hacia arriba desde el elemento objeto del evento hacia sus elementos padres. El modelo de eventos de Internet Explorer te permite interceptar eventos y procesarlos en tanto que "burbujean hacia la superficie" (el objeto window). Un resumen de esta aproximación es que los manejadores adjuntos a los elementos cercanos a la "superficie" pueden necesitar procesar antes los datos del evento.
Burbujeo de eventos:
Texto del enlace -> Etiqueta del enlace -> document
El modelo que ofrece Netscape 6 (y Mozilla) combina algo de ambas aproximaciones con un poco de funcionalidad extra. Veámoslo.
El camino en el que viajan los eventos en NS6 es facil de seguir. Los eventos comienzan en la ventana y viajan hasta el elemento objetivo del evento (captura de eventos). Pero al alcanzarlo, se da la vuelta y recorre hacia atrás el camino por el que vino, hasta que alcanza de nuevo el objeto ventana (burbujeo de eventos).
Así, cada evento de Netscape 6 está dividido en tres partes , o fases separadas. La primera es cuando el evento viaja hacia su objetivo. Es la fase de captura de eventos. Más tarde veremos como inteceptar el evento durante esta fase.
La segunda fase es cuando el evento se encuentra en el elemento. Bastante simple.
La tercera fase es la de burbujeo, cuando el evento está de regreso a la ventana del navegador. Es durante esta fase durante la cual la mayoría de los manejadores de eventos se disparan por defecto.
Camino de los eventos en Netscape 6/Mozilla:
window -> document -> etiqueta de enlace -> texto -> etiqueta de enlace -> document -> window
Fabuloso, así que ahora tenemos lo mejor de ambos mundos. Netscape 6 nos permite capturar eventos en cualquier nivel del documento, en cualquier fase. ¿Pero cómo hacemos esto? Sigue leyendo.
Tanto Netscape como IE proveen de una manera de adjuntar manejadores de eventos a los elementos via scripts. La sintaxis standartd se parece a esta:
element.onTipoDeEvento = nombreFuncion
He aquí un ejemplo más concreto:
function procesaEnlace(){
alert("El enlace dirige a " + this.href)
}
links["miEnlace"].onclick = procesaEnlace
Bueno, hay algo básico en esta aproximación: Un elemento puede tener sólo un manejador de eventos para cada tipo específico. Si yo quisiera añadir un segundo manejador onClick, separado del anterior, para el enlace del ejemplo anterior, se me acabó la suerte, por que sólo hay un manejador onClick por enlace.
El modelo NS6/Mozilla toma este problema adquiriendo un concepto de lenguajes de programación más potentes: el event listener. En resumen, un event listener (o "escucha eventos") es un objeto especial que define una acción a tomar cuando ocurre un evento. El event listener entonces se añade a un elemento, como un enlace, capa, o lo que tengas. Entonces el escucha eventos (event listener), hurm, escucha si un evento específico se produce. Cuando el evento en cuestión alcanza el elemento, el event listener ejecuta su acción, normalmente una función.
Lo bueno de los event listener es que puedes tener más de uno escuchando el mismo evento del mismo objeto. Así que si quisieras tener cinco métodos onClick añadidos al mismo enlace, solo tendrías que incrustarle cinco event listeners separados que escuchasen específicamente al evento click y asignarlos al enlace. Hay más, puedes definir event listeners para contestar sólo a eventos en fase de captura o de burbujeo. Por ejemplo padrías tener dos event listener que escuchen ambos eventos onMouseDown, pero uno se ejecuta cuando el evento viaja hacia su objetivo, y el otro sólo cuando burbujea.
¿Demasiado bueno para ser verdad? Puede. Para poder usar las ventajas de este nuevo material que es el Event Listener, primero debemos saber cómo usarlo correctamente.
Escuchando
Para añadir un event listener, debes usar el método addEventListener. Esta es la sintaxis:
objeto.addEventListener(tipoDeEvento,nombreDeLaFuncion,captura)
tipoDeEvento es una cadena que representa el tipo de evento que quieres ecuchar. Ejemplos válidos serían "mousedown," "click," o "focus." Fíjate en que no incluyen el prefijo "on", como podría tenerlo un manejador de eventos. Por ejemplo: "click" es un valor aceptable, mientras que "onclick" no.
nombreDeLaFuncion es al función que quieres que se ejecute cuando se capture el evento específico. No es una cadena, si no la referencia a una función, de manera que ¡no uses comillas! Por ejemplo si quisieras que un event listener ejecutase la función processValue cuando detectase el evento onMouseDown,pasaríamos simplemente processValue en el parámetro nombreDeLaFuncion. Pasar "processValue" - como una cadena entrecomillada - es incorrecto y producirá error.
captura es una variable booleana (verdadero o falso) que dirá al event listener cuando ejecutar la función descrita por nombrDeLaFuncion. Si captura es true, la función se ejecuta en su parte de captura (viajando hacia su objetivo). Si captura es false, la función se ejecuta cuando el evento está en su fase de burbujeo (volviendo hacia el objeto window) Es importante ver que el event listener sólo se dispara una vez - un event listener que salta durante la fase de captura no lo hará en el momento que el evento lo atraviese de nuevo durante el burbujeo.
Aquí hay un ejemplo en el que añadimos un event listener a un elemnto DIV, y lo configuramos para que ejecute una función cuando escuche un mouseup durante su fase de captura. He aquí nuestra etiqueta DIV.
<div id="myDiv" style="position:absolute; left:10px; top:10px; width:100px; height:100px; background-color:red;visibility:visible;"> Mouseup me, baby! </div>
Ahora el script. Primero, escribamos una simple función que sea ejecutada por el event listener:
function cucha(){
alert("Lo he oído!");
}
Después, usaremos el método DOM document.getElementById para poner el manejador en el elemento DIV. Si no estás familiariado con este método DOM, echa un ojo a Scripting For The 6.0 Browsers para los detalles. Dado que tenemos que esperar a que la página se cargue, endosaremos estas pocas sentencias en una función llamada init y la llamaremos en el manejador onload del documento.
function init(){
divTag = document.getElementById("myDiv");
}
onload = init;
Ahora vamos a añadirle nuestro event listener.
¡Esto es! Pulsa aquí para ver el resultado.
Para eliminar un event listener debes usar el método removeEventListener.
Los tres parámetros deben ser exáctamemye los mismos que pasaste cuando creaste el Listener que ahora quieres eliminar.
Aquí hay otro ejemplo que cambia el color de una capa en un mouseover y mouseout, usando los mismos principios. Para variar un poco atraparémos el evento cuando vuelva durante la fase de burbujeo:
Pulsa aquí para ver el ejemplo en acción.
Whoa! ¿Qué hace esa cosa de e.type en la función changeMe()?
Ah, muy observador. Lo que estamos haciendo es usar la función para atrapar el objeto evento -- e -- y examinar en el en el primer momento un mouseover o mouseout cuando pase por la capa. Recuerda, el objeto evento contiene información acerca del evento en tanto que viaja hacia y hasta la ventana del navegador a el objetivo y vuelve de nuevo. En este caso, estamos buscando que el objeto evento nos diga qué tipo de evento ha ocurrido, y de acuerdo con ello, decidir de qué color va a quedar la capa.
Como te habrás imaginado, la propiedad type del objeto evento es una cadena que contiene el nombre del evento que se ha disparado. Pero el modelo de eventos de Netscape 6/ Mozilla puede decirnos bastante más. Ahora es un buen momento para mirar el objeto event en si mismo y qué otras ventajas que ofrece.
A aquellos de vosotros que sigais agarrados tenazmente al modelo antiguo de Netscape 4.x os alegrará saber que las propiedade del evento pageX y pageY, para devolver coordenadas relativas al documento, y layerXy layerY para devolver coordenadas de evento relativas a la posición del elemento, siguen funcionando. pageX y pageY están además reflejadas en sus análogos para el Mozilla, clientX y clientY, que son también accesibles desde el objeto event.
Otras propiedades útiles que incluye el objeto event son:
type - Esta ya la hemos visto. Es una cadena que contiene el tipo de evento que ha sucedido.
target - Es una referencia al objeto objetivo del evento, aquel hacia el que se dirigirá el evento y subirá burbjeante.
currentTarget - Esta es una referencia a aquel objeto cuyo event listener invocó a la función listener. Esto provee información como en qué parte de la jerarquía del documento está actualmente el evento.
Fíjate en que target y currentTarget no son necesariamente el mismo objeto o elemento. Por ejemplo, digamos que que tienes una capa verde dentro de otra capa roja más grande. Decides añadir un event listener a la capa roja para escuchar eventos del tipo mousedown. Ahora lu pruebas, pulsas (mousedown) en la capa verde. En el momento en que el event listener se disparael objeto target debería estar en la cap verde, por que es en la que se ha pulsado físicamente. El currentTarget sería la capa roja, por que es el objeto en el que el evento está en ese momento (y subsecuentemente, el que disparó la función).
button - Si el evento fue activado por un botón del rartón esta propiedad guardará un número indicando qué boton fue pulsado o soltado. Es idéntica a la propiedad de Netscape which, que sigue presente en Mozilla/NS6
eventPhase - Es un número que indica la fase actual del evento, Este valor puede ser 0 (cero) para la captura, 1 (uno) para el momento en el que el evento alcanza el objetivo, o 3 para el burbujeo.
cancelBubble - Es un Boolean que determina si puede o no el evento continuar burbujeando hacia arriba al siguiente elemento de la jerarquía. Por defecto suele ser false, dado que algunos eventos no burbujean por defecto. Si es necesario, puedes usar un event listener para cambiar esta propiedad a true y detener el progreso del evento hacia el siguiente elemento de la cadena (a no ser que el elemento no sea cancelable, mira más abajo).
bubbles - Otro Boolean, sólo que este indica si el evento burbujea por defecto. En casos especiales un evento puede no burbujear. Es posible que necesites probar esta propiedad para probar si tu manejador de eventos requiere burbujeo.
cancelable - Este Boolean indica si el evento es cancelable o no (Si, ¡algunos eventos no pueden cancelarse!)
keyCode - Si el evento viene de pulsar una tecla, esta propiedad guarde al código numérico de esa tecla.
Además, hay varias propiedades para tratar teclas modificadoras. Mientras que el viejo modelo del Netscape los contiene en una propiedad llamada modifiers, el modelo de eventos de NS6/Mozilla simplifica las cosas ofreciendo las propiedades booleanas altKey, ctrlKey y shiftKey (aunque, al contrario que IE, Mozilla no distingue entre los lados derecho e izquierdo del teclado).
El modelo de eventos de NS6/Mozilla provee mucha de la flexibilidad y funcionalidad que necesitamos. Miralo un poco, aprende sus trucos, y pronto estarás creando interactivas, dinámicas páginas web y aplicaciones en tiempo record.
Aprende más
function init(){
divTag = document.getElementById("myDiv");
divTag.addEventListener("mouseup",cucha,true);
}
onload = init;
objeto.removeEventListener(tipoEvento,nombreFuncion,captura)
function changeMe(e){
var color;
window.status = e.type;
if (e.type=="mouseover") color = "green";
else color = "red";
divTag.style.backgroundColor = color;
}
function init(){
divTag = document.getElementById("myDiv");
divTag.addEventListener("mouseover",changeMe,false);
divTag.addEventListener("mouseout",changeMe,false);
}
onload = init;
El Evento Principal