Dizque



Cajón de sastre, Desarrollo web, JavaScript

Ventanas popup y buenas prácticas

Saltar a Anotaciones relacionadas

No, no soy partidario de su uso, pero en ocasiones tienen su utilidad. Las ventanas popup pueden ser un buen recurso para, por ejemplo, mostrar ayuda al usuario sobre la cumplimentación de un formulario complejo.

Hoy abriremos ventanitas con javascript, pero no a lo tonto. Trataremos de

  1. respetar al usuario;
  2. minimizar la necesidad de marcado específico;
  3. no interferir con otros scripts.

Respetar al usuario

Para mantener intacta la libertad de elección del usuario a la hora de activar el enlace (guardar destino, añadirlo a marcadores, abrirlo en una nueva pestaña…) utilizaremos un enlace de los de toda la vida. Nada de añadir en el marcado manejadores onclick, ni hablar de href absurdos como # o javascript:bla();. Nada de hacer el mal.

Nuestro enlace apuntará a su destino:

<a href="/ayuda/formulario-dificilisimo.html#campo-chungo">Ayuda sobre campo chungo</a>

Esa es la forma de vida que hace de los enlaces unos tipos simpáticos prontos a sonreír.

Minimizar el marcado

Lo ideal sería no tener que hacerlo, pero de alguna manera tenemos que indicar qué enlaces son los que se abrirán en una nueva ventana. Podemos marcarlos con tiza, con un hierro al rojo, o aprovechar alguno de los atributos aplicables a los enlaces.

Los atributos más apropiados para introducir nuestra «marca del zorro» son class y rel. Hoy me quedo con rel. El marcado, pues, quedará así:

<a rel="help" href="/ayuda/formulario-dificilisimo.html#campo-chungo">Ayuda sobre campo chungo</a>

Y ahora sí, hablemos de javascript.

Recopilando enlaces

Lo primero que hará nuestro querido script es recopilar la lista de enlaces a los que añadirá el manejador para abrirlos en una nueva ventana.

var el;
var links = document.getElementsByTagName("a");
for (var i = 0; null != (el = links[i]); ++i) {
    if (/\bhelp\b/.test(el.rel)) {
        // aquí irá la chicha
    };
};

Puesto en cristiano: recogemos en una colección todos los enlaces presentes en el documento. Iteramos sobre la colección y comprobamos en cada enlace, mediante una expresión regular, que su atributo rel contiene el valor help (recordemos que el atributo rel puede contener varios valores separados por espacios).

Manejando el evento onclick

Ahora a por la chicha. Sabiendo que el es el enlace con el que vamos a trapichear…

el.onclick = function() {
    var w = window.open(this.href, 'mywin');
    if (!w) return true;
    w.focus();
    return w.closed;
};

Esto es, asignamos una función como manejador del evento onclick del enlace de nuestros amores. La función trata de crear una nueva ventana a partir de la URL indicada en el href del enlace (en estos casos this hace referencia al elemento que ha disparado el evento) con un nombre que nos permitirá reutilizarla cuando abramos otro popup (en lugar de ir por ahí abriendo ventanas a lo loco).

A continuación comprueba que efectivamente se ha abierto la ventana. Si no se ha conseguido, permite que la activación del enlace siga su curso y el nuevo contenido se cargue en la ventana actual. Si se ha abierto con éxito (o se ha recuperado una ventana anterior con el mismo nombre), la trae al frente utilizando el método focus() y, para detener la activación del enlace, devuelve el valor del atributo closed de la ventana popup, que, desde que el mundo es mundo, vale false cuando la ventana está abierta.

(De la asignación de manejadores de eventos hablaremos largo y tendido en otra ocasión.)

Inicialización al finalizar la carga del documento

Para juguetear con el DOM, necesitamos un documento completo. Por tanto, nuestro script comenzará a actuar cuando se dispare window.onload. Como somos buenas personas, utilizaremos un truco (ideado por Simon Willinson) que evitará colisiones con otros scripts que actúen sobre el mismo documento.

var oldOnload = window.onload;
if (typeof oldOnload == 'function') {
    window.onload = function() {
      oldOnload();
      popups_init();
    };
} else {
    window.onload = popups_init;
};

Encapsulación

Y para rematar la faena, lo metemos todo en un saco cortado según el patrón de Funciones anónimas y autoejecutables en javascript. Ahí va la criatura completa:

(function() {
    function popups_init() {
        var el;
        var links = document.getElementsByTagName("a");
        for (var i = 0; null != (el = links[i]); ++i) {
            if (/\bhelp\b/.test(el.rel)) {
                el.onclick = function() {
                    var w = window.open(this.href, 'mywin');
                    if (!w) return true;
                    w.focus();
                    return w.closed;
                    };
            };
        };
    };

    var oldOnload = window.onload;
    if (typeof oldOnload == 'function') {
        window.onload = function() {
          oldOnload();
          popups_init();
        };
    } else {
        window.onload = popups_init;
    };
})();

La dejo a mano, lista para descarga y uso. Utilízala si quieres, es beerware, pero quede dicho: mi intención al escribir esta nota es enseñar a pescar. Poco a poco iremos aprendiendo también a fabricar nuestras propias cañas.




10 comentarios RSS

  • #1
  • are
  • 2006-05-23 22:38:13

Me gusta, sólo le faltaria añadir un atributo title con un texto alertando que va a abrirse una ventana nueva :)

Lo del title es una buena idea. De hecho, la consideré y la descarté para poder mantener el script independiente del lenguaje natural utilizado en el documento. Ya hablaremos de ello.

En cualquier caso, me gusta que te guste ;)

  • #3
  • are
  • 2006-05-24 10:55:12

cierto, el script deberia ser independiente del idioma. No existe nada parecido a una implementación tipo gettext para js?

Are, si existe yo no la conozco.

Una triquiñuela que he empezado a utilizar consiste en extraer los textos que necesita el script del contenido del documento. Pero, claro, no siempre es posible.

Un procedimiento similar a gettext sería el siguiente:

  1. Cuando el script comienza su ejecución (DOM completo), extrae del documento el código del lenguaje natural (es, an_ES, en_US).

  2. Realiza una llamada estilo AJAX para cargar un algo y espera.

  3. Cuando se completa la carga de ese algo, se evalua su contenido y el script continúa su ejecución (en una función de callback).

Creo que me voy a poner con ello.

  • #5
  • Andrey
  • 2006-07-29 01:10:22

BUen dia, puede ke me salga un poco del tema pero ncesito hacer una ventana como el alert() en javacript pero ke contenga los clasicos botones Aceptar - cancelar y pues su funcionamiento es posible, agradecere su atencion
Graciass…

Efectivamente, Andrey, te has ido de tema y bastante. Anyway…

Lo que tú andas buscando se llama confirm. Tienes la documentación en w3schools, por ejemplo.

  • #7
  • Raquel
  • 2006-08-30 04:32:43

Caray, alguien puede ayudarme? En mi pc no logro abrir ventanas de los links, algo le pasò que ahora tengo este problema, gracias si alguien puede auxiliarme. Saludos!!!

  • #8
  • lara
  • 2006-11-03 22:20:43

Gracias!!! muy bueno!!

  • #9
  • Jose Gabriel
  • 2007-10-03 15:01:49

Muy bueno, me gusto lo de mantener el link normal.-

  • #10
  • feramadeus
  • 2008-04-04 20:40:19

Tengo en un campo de mi base de datos codigo html. como hago para poder incluir ese html en el popup javascript y que me muestre el popup en base a eso? el campo es text y esta en mysql. Trabajo en php. he leido algo como que debe ser en el atributo text pero no sale. alguna idea?


Di la tuya

Puedes usar markdown y estas etiquetas HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong> . Por favor, evita el abuso de las mayúsculas y cuida la ortografía.