domingo, 21 de marzo de 2010

Liquid Page and Resizeable Background Image (Páginas Líquidas)

(Creador: Freddy Torres.

¿Qué se quiere lograr?


Hace un par de meses se presento un requerimiento por parte de un cliente. Deseaba poder mostrar sus fotos en pantalla, y que las mismas ocuparan lo largo y ancho del explorador en su totalidad. Incluido esta el requerimiento de evitar que la misma se deforme, porque de no ser así, bastaría con colocar un código como este:


El problema con el código anterior es que no se preserva el radio de aspecto de la imagen de fondo (http://en.wikipedia.org/wiki/Aspect_ratio_(image)), por ejemplo: Supongamos que tenemos una imagen de tamaño 1280 x 800 (ar: 16:9 universal to high-definition television and European digital television), y nuestro explorador se encuentra en resolución 800 x 600 (ar: 4:3 universal for standard-definition video formats). El resultado sería una imagen deformada, ajustada de su tamaño original hacia 800 x 600, obviamente no es el resultado deseado.

¿Cómo lo solucioné?

La solución requiere realizar un cálculo en tiempo real que detecte el tamaño actual del explorador, y escale la imagen proporcionalmente a la mayor de las dimensiones del mismo. (WTF…?). Sencillo, que no deforme la foto, y que ocupe la mayor cantidad de pantalla posible.

¿Qué herramientas me apoyan?

Obviamente se necesitan algunas librerías de javascript que permitan gestionar y consultar las dimensiones del explorador. Aquí entra el grandioso JQUERY FRAMEWORK, mas específicamente la librería “jquery.dimensions.min.js”, que permite realizar un par de operaciones escenciales:

- $(window).width();
- $(window).height();

Por consiguiente, es necesaria la librería del propio framework “jquery-1.4.2.min.js”

Luego el algoritmo va como sigue……

El HTML:


********* IMPORTANTE **********
El identificador de la imagen (id=”liquidImage”) debe ser tomado en cuenta para el javascript que sigue.



EL JAVASCRIPT:

$(document).ready(function() {
Liquify();
$(window).bind("resize", function() {
Liquify();
});
});

Function Liquify(){
// dimensiones del explorador
var $winwidth = $(window).width();
var $winheight = $(window).height();

// dimensiones originales de la imagen
var $x = 1024; // cambiar de acuerdo al requerimiento o pasar por parametro
var $y = 768; // cambiar de acuerdo al requerimiento o pasar por parametro
var $dx = 4; // radio de aspecto x
var $dy = 3; // radio de aspecto y

// algoritmo
var $p = $winwidth / $dx;
var $coef = 0;
var $newwidth = 0;
var $newheight = 0;

// calculamos la mayor de las dimensiones del explorador
if (($winheight / $dy) > $p) {
// height predomina
$coef = $winheight / $y;
$newheight = $winheight;
$newwidth = $x * $coef;
} else {
// width predomina
$coef = $winwidth / $x;
$newwidth = $winwidth;
$newheight = $y * $coef;
}

// seteamos las dimensiones deseadas a la imagen de background
$("#liquidImage").attr({
width: $newwidth
});
$("#liquidImage").attr({
height: $newheight
});
}

¿Qué defectos tiene?

1. Las variables de dimensiones originales de la imagen están hard-coded en el javascript, y deben ser cambiadas de acuerdo al requerimiento. Lo ideal es hacer un pluing de jquery que reciba estas variables por parámetro, y tenga algunas seteadas por defecto.

lunes, 8 de marzo de 2010

z-index, position: absolute e Internet explorer

Hace poco estaba haciendo un menu el cual abria un div sobre el resto del contenido de la pagina con JQuery, el codigo es algo asi:









<div class="Container">
<div class="bar fl">
<a href="#" id="btn1">
            <img src="<%=Url.Content("~/Content/Imagenes/img1.jpg") %>" alt="<%=Resources.buscarPorCine %>" />
        </a><a href="#" id="btn2">
            <img src="<%=Url.Content("~/Content/Imagenes/img2.jpg") %>" alt="<%=Resources.buscarPorPelicula %>" />
</div>
<div class="Buscador" id="Buscador1">    
            contenido    
        </div>
<div class="Buscador" id="Buscador2">
            contenido
        </div>

</div>

<style type="text/css">
.bar
{
    width: 100%;
    height: 44px;
    background: url(Imagenes/bar.jpg) repeat-x;   
    z-index: 5;
}

.Buscador
{
    background-color: #483456;
    border-color: #483456;
    height: 500px;
    width: 946px;
    z-index: 5;   
    position: absolute;
    top: 365px;
    display:none;   
}
</style>

<script type="text/javascript" language="javascript">
    $(document).ready(function() {
        $("#btn1").click(function() {
            $("#Buscador2").slideUp();

            $("#Buscador1").delay(1000).slideDown();
           
        });

        $("#btn2").click(function() {
            $("#Buscador1").slideUp();
            $("#Buscador2").delay(1000).slideDown();
           
        });
    });
</script>







Básicamente dos links programados por JQuery para animar el menú, y el resto CSS con z-index y position absolute para mostrar el div encima del contenido.

Este código funciona perfecto en la mayoría de los exploradores, menos por supuesto en IE 6 y 7, donde el menu en lugar de colocarse encima del contenido se colocaba a la derecha de la pagina, destruyendo todo.
Bueno, el problema tiene algo que ver con la forma de manejar el Z-Index de IE 7, el cual al dibujar los elementos con esta propiedad "genera una nueva pila de contexto", 
y aunque aun no entiendo muy bien lo que esto significa, la solución consiste en colocar un div por encima del que queremos que aparezca encima del contenido,
 con un z-index mayor, veamos el código:






<div class="Container">
<div style="z-index: 7;">
        <div class="Buscador" id="Buscador1">     
            contenido     
        div>
div>
<div style="z-index: 7;">
     <div class="Buscador" id="Buscador2">
            contenido
     div>
div>
<div class="bar fl">
<a href="#" id="btn1">
            <img src="" alt="" />
        a><a href="#" id="btn2">
            <img src=""     alt="" />
div>


<style type="text/css">
.bar
{
    width: 100%;
    height: 44px;
    background: url(Imagenes/bar.jpg) repeat-x;    
    z-index: 5;
}

.Buscador
{
    background-color: #483456;
    border-color: #483456;
    height: 500px;
    width: 946px;
    z-index: 5;    
    position: absolute;
    top: 365px;
    display:none;    
}
style>

<script type="text/javascript" language="javascript">
    $(document).ready(function() {
        $("#btn1").click(function() {
            $("#Buscador2").slideUp();

            $("#Buscador1").delay(1000).slideDown();
            
        });

        $("#btn2").click(function() {
            $("#Buscador1").slideUp();
            $("#Buscador2").delay(1000).slideDown();
            
        });
    });
script>

Adicionalmente tuve que mover los dos divs del menú a la parte superior del código.

sábado, 6 de marzo de 2010

Introduccion a Asp MVC (parte 1)




De un año para acá Microsoft a desarrollado una alternativa a Web Forms para el desarrollo de páginas y aplicaciones web en el framework asp .Net, este nuevo Framework está basado en MVC (Modelo - Vista - Controlador), un patrón de ingeniería de software bastante utilizado en otras tecnologías webs como Ruby on Rails (construido totalmente en base a MVC) y frameworks para Java y PHP.

¿Porque este cambio de dirección por parte de Microsoft, y que beneficios puede traer la utilización de esta tecnología con respecto a Web Forms?.

Antes de entrar en detalle, repasemos un poco el funcionamiento de las paginas web



Http (Hypertext transfer protocol)


Es el protocolo utilizado para la transferencia de datos entre el cliente (el Browser en nuestro caso) y el servidor. La comunicación entre ambos se produce con dos objetos, el request que consiste en una petición del cliente, y el response, la respuesta que envía.


El request es la petición del cliente al servidor para que ejecute alguna accion, tipicamente pedir informacion o realizar cambios (guardar, actualizar o eliminar datos).


El request puede ser de varios tipos, de los cuales nos enfocaremos en el Get y Post


El Get es utilizado para la petición de recursos al servidor. Este tipo de peticiones no debe ser utilizado para peticiones que causen ningún tipo de cambio, como lo puede ser la eliminación de registros en una base de datos, esto debido a la facilidad con las que pueden ser realizadas estas peticiones. Por ejemplo, veamos la siguiente tabla:




El boton eliminar es un link < a > a un URL, cuando se realiza una petición a este URL se elimina el dato. Ahora, si esta pagina tiene acceso público, el robot de google podría ingresar a ella en cualquier momento y realizar peticiones a los links encontrados, eliminando los datos de la pagina sin que nos demos cuenta.


La petición de tipo Post permite enviar datos en el cuerpo del request para que sean procesados por el servidor, como lo es crear, actualizad o eliminar registros de una base de datos.





Html (Hypertext markup language)


Es el principal lenguaje utilizado para estructurar las paginas webs. Los navegadores interpretan los documentos Html para generar la vista a mostrar al usuario.


Los documentos Html pueden incluir adicionalmente documentos del tipo Css para agregar estilos a la pagina, y scrips, tipicamente en lenguaje JavaScript, que agregan funcionalidades a la pagina del lado del cliente.


Estas 3 tecnologías (html, css y javascript) son las tecnologías del lado del cliente mas utilizadas.





Http, Html y el navegador


Como vimos, las paginas Webs son usualmente documentos Html con Css y Javascripts, mostrados por un navegador, el cual se comunica con un servidor a través del protocolo Http.


Todas las peticiones del cliente al servidor son realizadas a un URL:


www.ejemplo.com/MiPeticion/1?queryString=2


Donde la primera parte (www.example.com) indica la dirección del servidor, y el resto es la petición es interpretada por este para determinar la respuesta o acción a tomar y retornar al cliente. 
En el caso de las peticiones Post, el servidor  recibe adicionalmente los datos enviados en el cuerpo del request. Esto campos son introducidos usualmente por el cliente en un formulario html (< form >).


En la siguiente parte veremos como funciona esto en Web Forms y las diferencia con Asp MVC.