lunes, 17 de enero de 2011

Aproximacion: Haciendo zoom a pagina web con Javascript

Algunas ocasiones me llegue a encontrar con diferentes páginas que logran hacer zoom a su contenido y se veia bien por aquello de las diferentes resoluciones que maneja cada quien en su computadora (llamese mac, pc, portatil, etc), pero tal era la sorpresa cuando veía que la pagina estaba echa en flash y en lo personal no me agradan las paginas cuyo contenido esta basado en flash. Me di a la tarea de intentar generar mediante JS alguna forma de tener una aproximación para poder hacer zoom al contenido de la página web.

El componente que presentare esta sustentado en mantener una página HTML lo mas limpia posible en cuanto a CSS y JS concierne, refiriendome a tener la menor cantidad posible de CSS o JS inscrustado directamente en la página, con la finalidad de manejar cada componente (visual-css o funcional-js) manejable y 'portable' entre las mismas páginas que el sitio web contenga.

Este es el código, el cual explicare mas delante. Es necesario generar un archivo llamado Zoom.js e insertar el siguiente código:
var Zoom = {
isIE :  navigator.appVersion.match(/MSIE/),
scale : 1,
properties : new Array("width", "left", "height", "top", "fontSize"),
resolutions : {
r1024X600:0.70,
r800X600:0.60,
r1024X768:0.65
},
attach : function(){
var r = "r"+screen.width+"X"+screen.height;
if(Zoom.resolutions[r] != null){
Zoom.scale = Zoom.resolutions[r];
}
if(Zoom.scale != 1){
var images = document.getElementsByTagName("img");
var maps = document.getElementsByTagName("map");
var css = document.styleSheets;
var i=0;
for(i=0;images && i<images.length;i++){
Zoom.imageScale(images[i]);
}
for(i=0;maps && i<maps.length;i++){
map = maps[i];
for(j=0;j<map.childNodes.length;j++){
area = map.childNodes[j];
if(String(area.nodeName).toUpperCase() == "AREA"){
Zoom.areaScale(area);
}
}
}
for(i=0; css && i<css.length;i++){
try{
var rule = Zoom.isIE ?css[i].rules:css[i].cssRules;
Zoom.cssScale(rule);
}catch(e){
//Algunos navegadores no permiten modificar ciertos CSS por cuestiones de seguridad
//se cacha la excepcion y se continua con el resto de los estilos
}
}
}
},
removePX : function(toRemove){
if(String(toRemove).toLowerCase().indexOf("px") >0){
return String(toRemove).substr(0, String(toRemove).length-2);
}
return null;
},
imageScale : function(image){
var w = (image.offsetWidth*Zoom.scale).toFixed(2);
var h = (image.offsetHeight*Zoom.scale).toFixed(2);
image.style.height = h+"px";
image.style.width = w+"px";
},
cssScale : function(cssRules){
for(var j=0;cssRules!=null && j<cssRules.length;j++){
for(var k=0;k<Zoom.properties.length;k++){
var name = Zoom.properties[k];
var size = Zoom.removePX(cssRules[j].style[name]);
if(size != null){
size*=Zoom.scale;
size = size.toFixed(2);
cssRules[j].style[name] = size+"px";
}
}
if(String(cssRules[j].selectorText).toLowerCase() == "#main"){
cssRules[j].style.left = "50%";
cssRules[j].style.marginLeft = -(document.getElementById("main").offsetWidth/2)+"px";
}
if(String(cssRules[j].selectorText).toLowerCase() == "#mainmenu"){
cssRules[j].style.left = "50%";
cssRules[j].style.marginLeft = -(document.getElementById("mainMenu").offsetWidth/2)+"px";
}
}
},
areaScale : function(area){
var coords = String(area.coords).split(",");
var strCoords = area.coords;
for(var i=0;coords!=null && i<coords.length;i++){
if(i==0){
strCoords = "";
}
coords[i] = (coords[i]*Zoom.scale).toFixed(0);
strCoords+=((strCoords.length>0?",":"")+coords[i]);
}
area.coords = strCoords;
}
}


Ahora lo interesante... que hace el código y como lo hace.. así como un breve ejemplo.

Porque definir una 'variable' llamada Zoom... JS maneja las variables como objetos, de forma que las podemos manipular de ambas formas, como objetos o como números, arreglos, cadena de caracteres, etc... y dado que necesitamos diferentes métodos y propiedades propias del componente hacemos que la variable Zoom, tenga propiedades y métodos, de los cuales los manipulamos a su uso según convenga.

Como se menciono en un inicio, el componente se basa en el uso de CSS (mas delante pondre un breve tutorial sobre CSS).
De forma general lo que hace el codigo es buscar todos los estilos aplicados e intentar aplicarle una escala (zoom), tomando como base la resolucion de la pantalla para determinar el % a escalar la pagina. La escala puede ser en ambos sentidos, reducir el tamaño, asi como incrementarlo de ser necesario.

¿A que elementos les hara escala?
En general lo que mas nos interesa reducir son:
- tamaño de las imagenes
- tamaño de fuentes
- ancho, alto, x, y de los elementos de la pagina
Lo que hace es, tomando como base una lista de propiedades CSS (Zoom.properties), aplicar la escala a dichas propiedades CSS del elemento seleccionado. No es necesario ocuparnos de que elementos seleccionara, dado que lo que modifica es las propiedades de las hoja de estilo que tengamos ligadas en la pagina, sin alterar la hoja de estilo original. Se pueden tener mas de 1 hoja de estilo y tomara la base del concepto CSS para aplicar el cambio de tamaños en base a como esten añadidas dentro de la pagina
En el codigo, se muestra que pueden existir ciertos elementos que deseemos aplicarle alguna regla diferente, para lo que debemos tomar como base el nombre del estilo y hacer lo propio en la funcion Zoom.cssScale

¿Como mandar llamar esta funcion?
se manda llamar mediante la instruccion de javascript Zoom.attach(); en la cual consulta el tamaño de alto y ancho disponibles de la pantalla y determina que escala es la que realizara.
Lo mas conveniente es llamar la funcion en el evento onload del body, algo similar a esto:
<head>
<link href="ruta_archivo_css.css" rel="stylesheet" type="text/css" media="screen"/>
<script src="Zoom.js"></script>
</head>
<body onLoad="Zoom.attach()">
[CONTENIDO]
</body>


Mas delante pondre algun ejemplo mas completo y concreto para que se pueda observar la funcionalidad. Esta utileria fue probada en IE7+, FF3+, Chrome y Safari, intentando cubrir los navegadores mas comunes