Pseudo-lightbox

Todo empezó cuando tenía que actualizar mi página de caricaturista. Al querer que validara de forma estricta, decidí en implementar el efecto lo más simple posible (incluso sin transiciones).

Las primeras pruebas

Como es natural, las primeras líneas del código las fui probando en mi navegador habitual, en donde normalmente no tengo problemas con mis códigos, pero al ir chequeándolo el los otros, he notado que algunas declaraciones tenía que cambiarlas. Por ejemplo, para ocultar la pantalla me bastaba con una capa bien posicionada, y con el estilo...

 height: 100%;

... Pero al no tener contenido, esa capa no cubría la pantalla en al menos un navegador. También, para simplificar aún más el código, pensaba poner la imágen a mostrar como fondo de una capa; al usar estilos me hubiera ahorrado el código para posicionar la imágen.

Ayudado por la vieja herramienta "Destripador", la intención se convirtió en un código de pocas líneas:

ie = (document.all) ? true:false;
function mostrar(que)	{
	var x, y, an, al;
	x = (ie) ? document.documentElement.scrollTop + "px" : window.scrollY + "px";
	y = (ie) ? document.documentElement.scrollLeft + "px" : window.scrollX + "px";
	al = window.document.documentElement.clientHeight + "px";
	an = window.document.documentElement.clientWidth + "px";
	pop = document.createElement("div");
	with(pop.style)	{
		top = x;
		left = y;
		height = al;
		width = an;
		position = "absolute";
	}
	pop2 = pop.cloneNode(true);
	with(pop.style)	{
		(ie)	?	filter = "alpha(opacity=80)" : opacity = ".8";
		backgroundColor = "#eeeeee";
	}
	with(pop2.style)	{
		background = "transparent url(../dibujos/reloj.gif) no-repeat center center";
	}
	im = document.createElement("img");
	with(im.style)	{
		visibility = "hidden";
		position  = "absolute";
		border = "3px inset gray";
		cursor = "pointer";
	}
	im.onload = function()	{
		this.style.backgroundColor = "white";
		xx = (parseInt(an) -  this.width) / 2;
		yy = (parseInt(al) - this.height) / 2;
		this.style.top = yy + "px";
		this.style.left = xx + "px";
		this.style.visibility = "visible";
	}
	im.src = que;
	pop2.appendChild(im);
	document.body.style.overflow = "hidden";
	document.body.appendChild(pop);
	document.body.appendChild(pop2);
	im.onclick = function()	{
		document.body.removeChild(pop2);
		document.body.removeChild(pop);
		document.body.style.overflow = "auto";
	}
}

Después de este primer código, inicié un mensaje en los forosdelweb, con la intención de recibir comentarios y sugerencias; además, con el nivel de conocimientos de sus participantes, pensé que sería muy fácil su mejora y/u optimización.

Añadiendo transiciones

Antes de recibir respuesta alguna, me rondaba por la cabeza, la manera de conseguir un opacamiento gradual de las capas, de fácil implementación, simplemente se trataba de modificar el estilo opacity, y en el otro navegador el filtro de mismo nombre.

Para poder temporizar la transición, también decidí asignarle un identificador a las nuevas capas, y de paso añadí la posibilidad de cambiar el color de fondo de la capa que oculta la página, podiéndo usar colores poco habituales como el "pink", "magenta" u otros (¡hay gente para todo!).

function tag(id)	{return document.getElementById(id);}
function opacar(capa, _n)	{
	__n = _n / 10
	with(tag(capa).style)	{
		(ie)	?	filter = "alpha(opacity=" + _n + "0)" : opacity = __n;
	}
}

Con estos "añadidos" tuve que modificar la línea de opacamiento de la imagen con un sistema "gradual":

for (opacando = 1; opacando <= 10; opacando ++)
	setTimeout("opacar('pop2', " + opacando + ")", opacando * 50 + 500);

Y usando el mismo concepto, hemos cambiado la restauración de la visibilidad de la página al clickear sobre la imagen:

im.onclick = function()	{
	for (opacando = 1; opacando < 10; opacando ++)
		setTimeout("opacar('pop', " + (10 - opacando) + ")", opacando * 50);
	for (opacando = 0; opacando < 10; opacando ++)
		setTimeout("opacar('pop2', " + (10 - opacando) + ")", opacando * 50 + 500);
	setTimeout("document.body.removeChild(tag('pop2'))", 1000);
	setTimeout("document.body.removeChild(tag('pop'))", 1000);
	document.body.style.overflow = "auto";
}

Véase el resultado completo en el siguiente mensaje de la pregunta del foro.

El mensaje iba evolucionando, y aparecieron nuevos retos, como evitar el scroll al usar las flechas del teclado, y que se puede resolver (siempre considerando los navegadores usados... los más comunes) con este código:

function nada() {return false;}
// Y llamándolo así:
for (i in keys = ["onkeypress", "onkeydown", "onkeyup"])
	document[keys[i]] = nada;

Pero aún seguía el problema en opera, y buscando en Internet, encontré un evento que desconocía: "mousewheel", que añadí al array de claves "keys".

Desde otro mensaje de los foros: Pop uP, Plantearon implementar el típico juego de controles para moverse adelante y atrás, y a pesar de que este proyecto no era tan ambicioso, me ha parecido una buena idea.

Pseudo-estructurado

Un consejo que siempre doy con respecto a las imágenes, es evitar recargar las mismas imágenes más de una vez... no se consumen muchos recursos y se evitan esperas innecesarias. Así que dentro de esta nueva estructura crearemos un objeto para guardar las imágenes "visitadas", que tendrán un identificador que se pasará como segundo parámetro del nuevo método.

var pseudo = new Object();
pseudo.espera = 25;
pseudo.fondo = "gray";
pseudo.visitadas = new Object();
pseudo.mostrar = function()	{
	// aquí el código
}

Usaremos miniaturas de las imágenes que se ven en esta otra página: Andalucía, y las propias imágenes serán las que se mustren con sus respectivos mensajes.

Las miniaturas:

Almuñecar Carnaval Almería Castillo Almería Costa del Sol Salobreña

Las primeras modificaciones será la implementación de un sistema para evitar redundancias. Si queremos ver una foto anteriormente cargada, no volverla a cargar, sino guardar una copia de cada imagen, clonando la capa que la contiene; y para no tener que reescribir los principales atributos y estilos, guardamos esa capa cuando la imagen se carga:

if (!pseudo.cargada)	pseudo.visitadas[this.id] = this.parentNode.cloneNode(true);

Antes de seguir vamos a mostrar algunas posibilidades de personalización del sistema. Podemos cambiar en cualquier momento el color del fondo simplemente modificando la variable "pseudo.fondo" (el valor del mismo al principio es pseudo.fondo = "gray"); así como la temporización del efecto con la variable pseudo.temporizador (inicializado a 25).


Hemos visto como realizar simples personalizaciones, con la modificación de un par de variables. Ahora el nuevo reto será conseguir aplicar el efecto a otros elementos de una página web.

La frase del día

Hemos rescatado de esta página: "Ponga una cita en su página" la frase que se muestra a continuación (es un sistema aleatorio):

La cita

Si la teoría de la evolución de Darwin fuera cierta, a estas alturas los gatos ya sabrían manejar un abrelatas

Larry Wright , dibujante estadounidense (1942)

Ustedes pensarás que el autor de estas líneas se ha vuelto loco, pero en realidad la intención es mostrar otras cosas que no sean imágenes con o sin comentarios. Puede ver los resultados pinchando sobre el título de esta sección: La frase del día.

Para poder obtener este resultado, aplicando el efecto a otras capas y no sólo a imágenes, nos hemos ayudado de la capacidad de reservar las capas en memoria, para no tener que recargar más de una vez las imágenes. Para ello hemos creado un nuevo método para reservar clones de las capas que deseémos:

pseudo.asignaCapa = function(actual, copia)	{
	if ((this.visitadas[copia] == undefined))	{
		al = window.document.documentElement.clientHeight + "px";
		an = window.document.documentElement.clientWidth + "px";

		pop = document.createElement("div");
		pop.id = "pseudo_capa";//copia;

		with(pop.style)	{
			height = al;
			width = an;
		}

		clon = pseudo.tag(actual).cloneNode(true);
		clon.id = "pseudo_" + actual;
		anchura = pseudo.tag(actual).offsetWidth;
		altura = pseudo.tag(actual).offsetHeight;
		tope = parseInt((parseInt(al) - altura) / 2) + "px";

		with(clon.style)	{
			display = "block";
			position = "absolute";
			width = anchura + "px";
			height = altura + "px";
			backgroundColor = "white";
			top = tope;
			left = parseInt((parseInt(an) - anchura) / 2) + "px";
			cursor = "pointer";
		}
		pop.appendChild(clon);
		this.visitadas[copia] = pop;
	}
}

Para conseguir el efecto, previamente hay que hacer que la capa se guarde entre las "visitadas", y despreocuparse del primer parámetro de la llamada "pseudo.mostrar()"; véase como se realiza la llamada:

function mostrarFrase()	{
	with (pseudo)	{
		asignaCapa('cita', 'frase');
		guardar = fondo;
		fondo = 'pink';
		mostrar('', 'frase');
		fondo = guardar;
	}
}

Cuando una capa ya está entre las visitadas, no se permite volver a guardarla, y cuando se muestra siempre se chequea que esté entre las visitadas, y así evitar recargarla... Por cierto, en el siguiente enlace: pseudo, se puede bajar la librería.

Y no se olviden de la Hoja de estilo:

#pseudo_fondo, #pseudo_capa, .pseudo_img	{
	position: absolute;
}

Cambiar el dibujo de espera

Cada usuario tiene sus preferencias con respecto a los colores, y se ha visto lo sencillo que es cambiarlo en esta pseudo-librería, y otra cosa que nos puede gustar personalizar es el dibujo que se muestra mientras se cargan las imágenes (como ya hemos señalado, para la primera carga).

Pinche en el dibujo que le guste como fondo y cargue alguna imagen para ver el resultado... Si esa imagen ya se ha cargado, no podrá ver el efecto.

Seleccione un dibujo

Se puede cambiar el dibujo todas las veces que se quiera simplemente usando el método usar_reloj():

pseudo.usar_reloj(url);

Efecto en capas

Hemos visto una forma de aplicar el efecto a una capa, asignandole un nombre, y ubicándola entre las imágenes/capas ya visitadas... pero si quisiéramos usar una capa activa, el sistema propuesto dejaría de valernos. Además, para cerrar esa capa, podríamos pinchar sobre algún elemento activo, con lo que podríamos encontrarnos con problemas.

Con la selección de dibujos para indicar el estado de espera, Si pinchamos en uno cualquiera se le añade un borde visible indicando su selección, pero si pre-asignamos la capa, se mantendría siempre en el estado inicial.

La solución a este problema es usar siempre la misma capa clonándola, y le hemos añadido un parámetro que indique que se puede usar (ver ejemplo).

En el primero de los casos, usamos el argumento false, y con este valor superponemos una capa transparente que permite visualizar el contenido, pero se anulan las zonas activas. En el segundo no se añade nada y las zonas activas siguen igual.

Para mejorar el sistema hemos añadido también un botón de cierre en las capas asignadas, (el ejemplo de la frase) y lamentablemente se descuadran, así que es mejor usar esta última opción (ver resultados).

Para otros elementos, el secreto para poderlos representar es que puedan obtenerse las dimensiones de anchura y altura, por lo que de quererlos tener ocultos, es preferible hacerlo con la "visiblilidad". Los elementos ocultos con "display: none" no ocupan espacio en la tabla, y se obtendría esos parámetros con valor 0, y tendríamos la obligación de temporizar el efecto para obtener las dimensiones con valores fiables.

Ejemplo de efecto con una etiqueta object (el ejemplo está generado en YouTube): Carnaval en "La Herradura".

Debo advertir que hay elementos que pueden ser problemáticos a la hora de desactivarlos, como es el caso del fieldset de "la frase del día".

Probando on-line

Se pueden hacer modificaciones en el código siguiente, y probar el resultado pulsando el botón de envío de formulario. Si quiere volver al código original Pulse aquí.

Modificar y Probar



Comentarios

Nombre: nehemias ramirez
Procedencia: tabasco, mexico
E-Mail: ramirezgn@gmail.com
Fecha de envío: 12 de febrero de 2010, a las 17:39.
Valoración:
comentario:

Excelente contribucion a la comunidad desarrolladora...

gracias,,, lo probare... se ve sencillo de usar.


Colabore enviando su comentario

Nombre
Procedencia
Página web
E-mail *
Evaluación evaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluar
Código de envío

Rellene este campo con la clave de la imagen: codigo de envío

Nota Importante

El campo E-Mail es obligatorio para activar por correo electrónico el comentario (si no desea que se haga público, marque la casilla "anonimato"). También es obligatorio el código "captcha" (el número que se ve en la imagen adjunta); y por supuesto, debe existir un comentario.

Puede encontrar información sobre este sistema de comentarios en este enlace: Ponga comentarios en su web.

Edición negrita cursiva subrayado   alineación izquierda alineación derecha alineación centrada alineación justificada   Insertar enlace insertar imagen   Emoticones: [:)] [:(] [:x] [BIEN] [MAL] [SI] [NO] [APLAUSOS] [MEJORABLE] [¡A VER!] [¡DÉJAME PENSAR!] [FLIPE] [¡SIN PALABRAS!]
Copyright © 2006-2018 www.caricatos.net
Visitas: 2446