martes, 27 de septiembre de 2011

Cómo crear una ventana modal propia (3)

Esto se complica, se hace retorcido, hay mucha cosa y poca sustancia pero me parece elemental entender el por qué de las cosas, es un vicio que vale la pena cultivar porque a la larga, simplifica la vida y en este caso de las ventanas modales hará que el resultado final sea un código muy corto y sin cosas raras; algo que uno pueda entender y adaptar a sus propias necesidades sin tener que seguir un curso avanzado en la NASA.

Si una de las claves de las ventanas modales es lograr que se muestren en el centro mismo de la página, sea cual sea el navegador que se usa y sea cual sea su tamaño o dónde nos encontremos dentro de ella, la segunda de las claves es poder aplicarlas a una etiqueta cualquiera sin tener que escribir mucho código.

Es lo que hace la mayoría de ellas, nos dicen pongan una clase XXX o un atributo REL o decenas de variantes similares; y todo el truco está ahí, hacer que algo que aparentemente no hace nada, haga algo.

Voy a elegir una etiqueta cualquiera, por ejemplo SPAN, la elijo porque no quiero complicarme la vida, porque no tiene propiedades por defecto, porque es una etiqueta inocua y en definitiva, la elijo porque si pero, podría ser cualquier otra.

Si dijera que escribimos esto y cuando se hace click en el texto se mostrará una ventana modal con la imagen, estaría mintiendo porque eso no es un enlace y el navegador no es adivino así que no pasaría absolutamente nada:
<span class="un_nombre" url="la_URL_de_una_imagen" h="500" w="200"> click para ver la imagen </span>
Sólo veria esto:

click para ver la imagen

Sin embargo, hay una forma de conseguir que esa etiqueta que aparentemente es nula, se transforme en una etiqueta activa. Para eso, JavaScript tiene una función muy importante llamada addEventListener() que nos permite agregarle eventos a cualquier tipo de etiqueta y de ese modo. modificarla de manera dinámica, es decir, luego de ser creada.

Los eventos en JavaScript son todas "esas cosas que ocurren" en la página cuando interactuamos con ella. El más elemental es el que usarenos aquí y el el evento click o sea, que pasa cuando se hace click sobre una etiqueta que, como en este caso, no es un enlace.

Es lo mismo que ocurre cuando se agrega onclick="algo();" en una etiqueta con la diferencia de que en este caso no necesitaremos escribirlo y dejaremos que sea JavaScript el que lo agregue de manera automática.

El código sería algo similar a esto:
function agregarevento() {
// creo una lista con todas las etiquetas SPAN
var s = document.getElementsByTagName("span");

// leo la lista una por una
for (var i=0; i<el.length; i++) { // guardo el contenido del atributo class
var c = s[i].className;

// si es una etiqueta SPAN con la clase que definí, le agrego un evento
if (c=="un_nombre") {
if (s[i].addEventListener) {
// Firefox, Chrome, Opera, IE9
s[i].addEventListener("click", demo, false);
} else if (s[i].attachEvent) {
// Internet Explore 8
s[i].attachEvent("onclick", demo);
}
}
}
}
¿Qué hará eso? Agregar un onclick en esas etiquetas pero claro, debemos indicarle algo más: cuál es la función a ejecutar que es la que contendrá el código de lo que ocurrirá cuando haga click y que en este caso llamé demo. En este caso, esa función dice algo tan simple como mostrar una ventana de alerta con un texto :
function demo() {
alert("HOLA");
}
Un último detalle importante a tener en cuenta es que para agreagr un evento de este modo, debemos asegurarnos que la páginas se haya cargado y por eso, todo lo anterior, lo ejecutamos así:
window.onload = agregarevento;
Ahora, probamos:


Si vamos hacia arriba y volvemos a hacer click en la etiqueta SPAN "pasará algo".

¿Y si no hubiera etiquetas SPAN con esa clase? No pasaría nada, no habría error de ninguna clase.

¿Y si hubiera varias etiquetas SPAN con esa clase? El evento se agregaría a todas ellas y esa es la clave de las ventanas modales, leen el documento (nuestra página) y agregan un evento en determinadas etiquetas aparentemente normales, transformándolas en otra cosa.


Claro que en este ejemplo no pasa nada muy interesante; pero, para eso es que la etiqueta SPAN tiene atributos "raros", en este caso, personales y que pueden tener cualquier nombre:
<span class="un_nombre" url="la_URL_de_una_imagen" h="500" w="200"> click para ver la imagen </span>
class="un_nombre" es la clase genérica que usaremos para agregar eventos
url="la_URL_de_una_imagen" es la dirección de la imagen que uno quiere mostrar
h="500" es la altura de esa imagen
w="200" es el ancho de esa imagen

Así que sólo se trata de "leer" esos datos cuando se hace click y luego "armar" el contenido a mostrar; para eso, se usa la función getAttribute() y el tema sería bastante complejo de resolver sino fuera porque hay gente que ya pensó estas cosas y da soluciones que podemos aplicar. El problema es que si hacemos click en una etiqueta donde hemos agregado un evento, se ejecuta la función indicada sin problema y la mayoría de los navegadores no requiren que se identifique esa etiqueta con un ID, basta usar algo así:
var direccion = this.getAttribute("url"); // nos dirá el contenido del atributo
Pero, en IE (por lo menos en sus versiones 7 y 8, no ocurre eso y, obligatoriamente, se requiere de un ID cosa que nos complicaría mucho a la hora de estar escibiendo cosas porque, los IDs siempre deben ser diferentes.

Como decía ante, alguien ya resolvió el problema y lo que hace es agregar unas de líneas de código extra para agregar de modo automatico un ID en el caso de estar usándose IE. Por lo tanto, la función definitiva quedaría así:
var IEelem={}; // una variable para IE

// esta es la función que agrega el ID
function IEaddID(fn,uniqueID) {
return function(event) { return fn.call(IEelem[uniqueID],event); }
}

function agregarevento() {
// creo una lista con todas las etiquetas SPAN
var s = document.getElementsByTagName("span");

// leo la lista una por una
for (var i=0; i<el.length; i++) { // guardo el contenido del atributo class
var c = s[i].className;

// si es una etiqueta SPAN con la clase que definí, le agrego un evento
if (c=="un_nombre") {
if (s[i].addEventListener) {
// Firefox, Chrome, Opera, IE9
s[i].addEventListener("click", demo, false);
} else if (s[i].attachEvent) {
// Internet Explore 8
var uniqueID = s[i].uniqueID;IEelem[uniqueID] = s[i];
s[i].attachEvent("onclick",IEaddID(demo,uniqueID));
}
}
}
}
Y sí, con todos estos elementos reunidos, ya se puede armar el rompecabezas y al fin, tener una ventana modal propia.

No hay comentarios:

Publicar un comentario