Ir directamente al contenido de esta página

codexexempla.org

Cómo hacer accesible un vínculo a ventana nueva (2)

Tabla de contenidos

  1. Introducción
  2. El nuevo script
  3. Pruebas en navegadores

Introducción

La primera vez que me puse a pensar en el problema de cómo hacer accesible un vínculo a ventana nueva, di con una solución poco elegante —como se puede comprobar en «Cómo hacer accesible un vínculo a ventana nueva»—, aunque aun así la publiqué como ejemplo de una programación innecesariamente complicada. Sin embargo, a veces se aprende de los errores, así que partiendo de allí, llegué a una nueva solución.

Primero, había que hacer la lista de lo que había que mejorar:

Y segundo, había que conseguirlo.

El nuevo script

Helo aquí:


 01  var popups = new Array();
 02  var contador = 0;
 03  function buscar_popups(){
 04      var enlaces = document.getElementsByTagName('a');
 05      for (var k=0;k<enlaces.length;k++){
 06          if (document.addEventListener){
 07              if (enlaces[k].getAttribute('class')=="ventana_nueva"){ popups[popups.length]=enlaces[k]; }    
 08          } else {
 09              if (enlaces[k].className=="ventana_nueva"){ popups[popups.length]=enlaces[k]; }
 10          }
 11      }
 12      for (var l=0;l<popups.length;l++){
 13          if (document.addEventListener){     
 14              popups[l].addEventListener('click',abrir_ventana,false);
 15          } else {
 16              popups[l].attachEvent('onclick',abrir_ventana);
 17          }
 18      }
 19  }
 20  function abrir_ventana(evento){
 21      if(document.attachEvent){var destino = evento.srcElement.href;} else { var destino = this; }
 22      var id_popup = 'ventana'+contador++;
 23      var ventana_nueva = window.open(destino, id_popup, 'width=500px,height=250px,menubar=yes,resizable=yes,location=yes,scrollbars=yes,status=yes,toolbar=yes');
 24      if (document.addEventListener){ evento.preventDefault(); } else { return false; }
 25  }
 26  
 27  if(document.addEventListener){ window.addEventListener('load',buscar_popups,false); } else { window.attachEvent('onload',buscar_popups); }
            

En primer lugar, declaro las variables que voy a necesitar: una matriz en la que recoger las referencias a los vínculos a ventana nueva y un contador —que necesitaré luego para la función que abre las ventanas—. Ya en la función buscar_popups, obtengo la lista con los elementos a del documento.

El for de la líneas 5 a 11 busca en todos los enlaces la coincidencia de su atributo class con ventana_nueva. Elegí class por motivos de economía: además de indicar en el marcado que los vínculos van a ventana nueva por medio de title, no está de más añadir alguna pista visual sobre su comportamiento, como por ejemplo un icono. Así, si ya tenía un atributo identificativo, no necesitaba añadir ningún otro.

Como en el caso de IE6, getAttribute funciona de una manera extraña para el atributo class, se hace necesaria la línea alternativa con enlaces[k].className=="ventana_nueva" (línea 9). No se puede emplear enlaces[k].class=="ventana_nueva", porque class es una palabra reservada para futuros desarrollos de JavaScript1.

El for de las líneas 12 a 18 asigna escuchas a los vínculos de la matriz popups, detectando el soporte de addEventListener y supliendo su defecto con el código propietario de Microsoft.

Y ahora viene lo bueno.

Como ya sabía, con un alert(this); en la función abrir_ventana, IE iba a devolverme [object], y alert(this.href);, undefined. Sin embargo, sabía también que al lanzar una función desde addEventListener, se pasa a ésta, de manera implícita, un parámetro que hace referencia al propio evento —y que capturo por medio de abrir_ventana(evento) (línea 20)—, como se puede comprobar para Firefox añadiendo alert(evento); al comienzo de la función. Este navegador nos devuelve [object MouseEvent]. IE6 devuelve nuevamente [object], ¿pero podría éste hacer referencia al evento igual que en Firefox? Pues sí, como se comprueba por medio de evento.srcElement.href (línea 21)2. Así pues, detecto si el navegador soporta attachEvent —para estar seguro de que asigno a destino el valor que obtengo por medio de srcElement sólo en el caso de Explorer—, y en caso contrario el valor de destino equivale a this.

Ya sólo queda abrir la ventana (línea 23), y bloquear el funcionamiento por defecto de los vínculos (línea 24). Pero antes, en la línea 22 creo un identificador único para la nueva ventana, por si se da la circunstancia de que desde una página se abran varios enlaces de esta manera. En Firefox podía emplear como identificador el valor mismo de destino, pero IE6 lo considera un argumento inválido y genera un error, incluso convertido a literal —de manera redundante, por lo demás— por medio de toString().

Para comprobar el funcionamiento del script, haga clic sobre este vínculo; después desactive el soporte de JavaScript de su navegador y repita la operación.

Descargar el archivo .js.

He comprobado que este script funciona correctamente —sobre Windows— en:

Notas

  1. La lista completa de palabras reservadas —actuales y futuras— se recogen en la especificación ECMA-262. El PDF se puede encontrar en la página de ecma-internacional.org (inglés). Volver
  2. El problema es que en IE6 los eventos lo son siempre del objeto window; por ello existe srcElement —código propietario de Microsoft—, con el que se puede pedir información específica del elemento concreto sobre el que ha tenido lugar el evento. Volver

Contacto

En virtud de la Ley Orgánica 15/1999 de Protección de Datos de Carácter Personal le informo de que los datos que proporcione no serán empleados para otro fin que el de responder a su mensaje. En especial, me comprometo a no cederlos a terceros ni a emplearlos para enviar información no solicitada.

Del blog de Digital Icon