Udostępnij za pośrednictwem


RIA y páginas con estado

Como usuarios de internet tenemos patrones de comportamiento adquiridos... imagina que estas navegando por un sitio y has llegado a un punto que no te convence. Llegados a este punto tienes básicamente 3 opciones:

1 - Hacer click en el menú de navegación e ir al paso anterior

2 - Hacer click en el típico logo para volver hasta el principio y empezar de nuevo

3 - Hacer click en el botón de atrás del navegador

Las dos primeras opciones están más trabajadas desde un punto de vista de desarrollo, pero desde un punto de vista de usabilidad, depende de cómo hayas hecho esos enlaces y dónde los hayas puesto para que el usuario los perciba o no. De accesibilidad hablaremos en otro post. La opción 3 estamos acostumbrados a que nunca falle... nos lleva a la página anterior, que conlleva tradicionalmente el estado anterior y listo!

Claro... que si estamos trabajando con aplicaciones p.ej AJAX... no esta tan claro que cada página se corresponda con un estado en la navegación por el sitio web. Al trabajar con Javascript, la parte cliente puede variar tanto como para poder considerar que ha pasado pro diferentes estados.

Esto nos puede afectar tanto a nivel de navegación, como a nivel de guardar un determinado estado en favoritos del navegador.

Imaginemos que tenemos una galería de fotos en Javascript, al hacer click en una foto la mostramos mas grande. Podríamos considerar que tenemos 2 estados diferentes, la galería y la vista detalle; pero al haber estado trabajando con Javascript, las acciones se han realizado en la misma página, de modo que cuando estamos viendo la foto en detalle, no podemos dar atrás en el navegador para ver la vista galería ni guardar la foto en favoritos. No hay un estado que podamos almacenar.

¿ Entonces ?

Bien, entonces lo que nos toca es ser capaces de serializar el estado de una página y almacenarlo de alguna forma que podamos acceder a ella. Y teniendo en cuenta las diferencias que tenemos entre navegadores... fácil, no?  x)

Para ilustrar el post he creado una pequeña aplicación de ejemplo que os podéis descargar en este enlace

Creando el estado

El estado pueden ser infinidad de cosas... cómo se esta mostrando la página, que valores tienen los controles... lo primero que debemos tener claro es qué es un estado y qué lo forma.

En el ejemplo que tenemos, el estado va a implicar una u otra foto en primer plano, de modo que lo que hemos de preservar es la dirección de la foto a mostrar.

 Almacenando el estado

Aqui es donde la matan x)  Lo más fácil a día de hoy para programadores .NET es utilizar las asp.net 3.5 extensions preview, el Microsoft.Ajax.js ha sido actualizado con unos prototipos para el manejo del estado. Tiene como ventaja que podemos trabajar con el estado tanto desde el cliente como desde el servidor.

Si os habéis descargado los laboratorios que comentaba en un post anterior, tenéis los siguientes proyectos para practicar y echarle un primer vistazo

NETFramework35Enhancements_TrainingKit\Labs\AspNetAjaxHistory

Hoy... por ser miércoles... vamos a hacerlo con la parte cliente de la librería.

Lo primero y muy importante ...

En el scriptmanager de la página poned la propiedad EnableHistory a true

<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="true" >

Esto va a añadir un iframe a la página cliente para poder hacer los trucos Javascript que tendríamos que hacer nosotros a mano, si echaís un vistazo al fuente de la página en el cliente...

<iframe id="__historyFrame" src="/WebSite1/ScriptResource.axd?d=mfsa1_YluC_H6UGgoZq8xp82Y2Fwlt3V_nmPLNbI8rE1" style="display:none;">

;)

Una vez hemos habilitado el iframe, vamos a trabajar con los nuevos objetos en javascript para manejar el historial. Primero vamos a subscribirnos al evento de navegación, así tendremos control sobre lo que pasa cuando el usuario navega

function pageLoad()
{
    Sys.Application.add_navigate(onNavegar);
}

function onNavegar(sender ,e)
{
    if (userNavigated)
    {
        restaurarEstado(e.get_state());
    }
}

La variable userNavigated nos va a ayudar a discernir entre una navegación provocada por el usuario o una provocada por nosotros desde desarrollo. Tras implementar estas funciones, sabemos que cuando el usuario navegue se va a llamar a nuestra función restaurarEstado

Como hemos dicho antes, en esta aplicación sencilla el estado va a consistir en la dirección de la imagen a mostrar, de modo que para restaurar el estado sólo hay que recuperar la imagen guardada y mostrarla

function restaurarEstado ( estado )
{
    var RutaImagen = estado.RutaImagen;
    if ( RutaImagen == null || RutaImagen == "")
    {
        RutaImagen = ImagenXDefecto;
    }
    $get("fotoGrande").src = RutaImagen;
}

La variable estado la cargamos y la almacenamos nosotros cada vez que queramos almacenar un estado nuevo.

Llegados a este punto ya tenemos una aplicación que es capaz de recuperar un estado grabado y mostrarlo en la página. Lo único que nos falta es saber cómo almacenar el estado. Si miramos el código HTML, vemos que cada vez que se hace click se llama a un método que muestra la foto

<li><img src="imgs/VisitaBilbao01.JPG" alt="Vacas" id="i1" onclick="MostrarFoto(1)"/></li>

Dada la naturaleza de la aplicación de ejemplo, esta es la acción que va a implicar que queramos almacenar un nuevo estado, porque así el usuario podrá navegar atrás y adelante por las fotos con los botones del navegador. Vamos a ver la implementación

function MostrarFoto(id)
{
    var img = "imgs/" + fotos[--id];
    $get("fotoGrande").src = img;
    almacenarEstado(img);
}

function almacenarEstado( img )
{
    var pageState = { "RutaImagen" : img };
    Sys.Application.addHistoryPoint(pageState,img);
    userNavigated = true;
}

Es muy sencillo, creamos un objeto con el estado de la página (pageState) y se lo pasamos como parámetro a Sys.Application.addHistoryPoint. El segundo parámetro que recibe es el nombre con el que se va a almacenar ese estado en el historial. El echo de añadir un nuevo estado, internamente va a trabajar contra el iframe y va a provocar una navegación, para diferenciar esta navegación de una iniciada por el usuario, marcamos el userNavigated a true.

y listo :)

 

Otras opciones

Como comentaba más arriba, podéis utilizar infinidad de frameworks javascript o controles descargados de internet para que os gestionen el estado, de hecho si os animáis podéis programaros el vuestro propio...

<bricomania> mantenéis un hashtable indice/estado, cada vez que haya un nuevo estado, se marca la url con el índice nuevo y se añade el nuevo estado al hashtable. Cuando el indice de la url no se corresponda con el indice actual, recuperáis del hashtable con el índice de la url como base y establecéis el nuevo estado en la página.... </bricomania>

...bien.. no es tan fácil... hay que lidiar con las diferencias entre navegadores, ver cuándo cambia la url y en base a qué, tener en cuenta navegación hacia atrás y hacia adelante... realmente un framework os ahorrará bastante tiempo :)

Happy Hacking

Ds

Lectura interesante sobre el tema de almacenar y recuperar estado

https://yuiblog.com/blog/2007/02/21/browser-history-manager/
https://weblogs.asp.net/bleroy/archive/2007/09/07/how-to-build-a-cross-browser-history-management-system.aspx

Comments