soy Kseso y esto EsCSS

Recordando valores entre refrescos, tres (sabores) métodos para elegir

Tres métodos para guardar información de una página y recuperarla tras su cierre o refresco.

Recordando valores entre refrescos, tres (sabores) métodos para elegir

✎ 7
COLABORACIÓN AUTOR INVITADO
Recordando valores entre refrescos, tres (sabores) métodos para elegir

Existen algunos casos en que queremos mantener valores o formatos personalizados de una página, pero como usuarios. Si somos los creadores o editores del documento, está claro que podemos modificar y guardar los cambios en el código fuente; pero para quien solamente puede verlo en un navegador esto se hace más complicado.

Si no disponemos de un complemento o plug-in que nos ayude, eso de agregar o eliminar texto, señaladores, marcas, cambios para ver después de abrir nuevamente el documento, será una ausencia que lamentaremos más de una vez cuando queramos dejar un párrafo para leer mañana y retomarlo en el mismo punto, o cuando se nos refresque el documento por las suyas y perdamos el contenido de un formulario.

Claro que siempre está la posibilidad de agregar algo de javascript en nuestro sitio y darle a los visitantes esa comodidad.

Método 1: Local Storage

Algún memorioso recordará el userData behavior de Internet Explorer 5, que permitía guardar hasta 1M de texto (convertible luego a código) usando un identificador como referencia para recuperar los datos aún después de cerrada la página, el navegador y hasta el sistema operativo.

Pues resulta que hoy existe un recurso muy similar (dependiendo del navegador anda en los 4 ó 5M de capacidad) que se supone es compatible al menos con los navegadores de escritorio. Se conoce como localStorage y guarda parejas clave:valor,otraclave:otrovalor que se pueden recuperar en cualquier momento desde el documento.

Para probarlo vamos a poner un caso común en textos con párrafos muy largos: tenemos que cerrar el navegador y continuar la lectura más tarde, dejando un señalador o marca en la posición en la que la abandonamos.

Para el ejemplo (que es muy básico) vamos a usar una lista numerada con algunos datos sueltos que escribí hace algunos años para un sitio ya desaparecido y que voy a aprovechar ahora como relleno en vez del clásico "lorem ipsum".

Un botón va a registrar el desplazamiento vertical del documento en forma de valor dentro de localStorage. Una vez guardado, ya no importa si seguimos moviendo la scrollbar; al recargar, refrescar o reabrir la página, un escript va a mover al documento hasta esa coordenada 'Y' que habíamos registrado.

See the Pen Remember page position with ´local storage´ . by solipsistaCP (@solipsistacp) on CodePen.

El JS es muy breve:

function recordar() { localStorage.setItem("p05IcI0n", pageYOffset) } window.addEventListener("load", function(){ setTimeout(function(){window.scrollTo( 0, localStorage.getItem("p05IcI0n") )}, 100); }, false);
  • Una función guarda como un ítem de "storage" la clave "p05IcI0n" y el valor que será la coordenada "y" del desplazamiento de la página en el momento de clickear el botón.
  • Luego se agrega un escuchador de evento para que al cargarse el código completamente se ejecute una función anónima para desplazar el documento con scrollTo(x, y). Este método acepta 2 parámetros, que son la coordenada horizontal y la vertical hasta donde debe llegar el desplazamiento.
  • Pero está metido en una linea de código algo extraña. Resulta que en algunos navegadores lentos (o en circunstancias que lo demoran) el movimiento de la ventana necesita un retraso para su ejecución, y por eso lo escribimos dentro de un setTimeout(); que no lo ejecuta directamente sino a través de otra función anónima, porque es lo correcto para el caso.
  • La coordenada horizontal para nuestro ejemplo siempre es "0", y la vertical la extraemos del storage, llamando al valor del ítem por su clave. Esto es posible porque el método previamente convierte la cadena de texto a objeto, y desde un objeto de javascript sí se pueden reconocer claves para leer su valor.

Método dos: Cookie

El problema de los "storage" es que no trabajan en todas las plataformas, y muchos móviles aún no los reconocen. Entonces para lograr el efecto hay que usar métodos más viejos, más modestos, y más compatibles.

Existe un espacio en la caché del navegador que permite guardar información sobre el usuario asociándolo a la página, pero no es el único uso que tiene. Las "cookies" pueden guardar cualquier dato literal separados por 'punto y coma', lo que nos permite agregar nuestro valor de desplazamiento con el formato (clásico) de "identificador=valor;".

Aunque en este caso la extracción es más compleja, porque se leen todas las cookies como una cadena de texto; además tiene otras dificultades (como la caducidad) que debemos resolver.

Una limitación más (que a nosotros no nos afecta) es el tamaño máximo de la cadena, que no pasa de los 4K en total.

See the Pen Remember page position with cookie. by solipsistaCP (@solipsistacp) on CodePen.

function recordar() { document.cookie = "p05IcI0n="+pageYOffset+"; expires=Tue, 19 Jan 2038 04:14:07 GMT"; } window.addEventListener("load", function(){ Y = (document.cookie.split("p05IcI0n=")[1]).split(";")[0]; setTimeout(function(){window.scrollTo( 0, Y )}, 100); }, false);
  • La primera función otra vez es para grabar la posición del documento al clickear el botón, pero ya vemos que el método es bastante distinto. No hay un par "ítem:valor" sino una cadena de texto con partes reconocibles separadas por punto y coma.
  • Primero agregamos a las cookies de la página un literal que podamos ubicar facilmente y no se confunda con otro (por eso la forma encriptada de escribir "posición"), y la separamos del valor que nos interesa con un signo "igual". Como en el ejemplo anterior, ese valor es el desplazamiento del documento sobre la coordenada "y", capturado con window.pageYOffset.
  • Luego ponemos un límite de tiempo para la duración de nuestra cookie. Si no escribimos ninguno, ésta se borrará al cerrar la sesión, y ya no sirve para nuestro ejemplo donde queremos que el navegador recuerde la posición de la página cuando lo abramos de nuevo. El valor para "expires=" parece algo caprichoso, pero tiene que ver con la época en que se inventaron las cookies. Es la fecha máxima que debería aceptar una máquina de 32bits. Claro, hoy las de 64b podrían llegar más lejos.
  • Al cargarse el documento, la función anónima vuelve a desplazar hasta la coordenada que guardamos. Y esta vez repartí todo en dos líneas para que se entienda más fácil, no porque sea necesario para el funcionamiento.
  • Primero vamos a extraer el valor que nos interesa a una variable. Para eso capturamos toda la cadena de la cookie y empezamos a cortar lo que no nos sirve con el método split(). Lo muestro paso a paso por si no queda claro:
    • Si nos desplazamos (y grabamos) unos 500 (pixeles), la cadena leída por document.cookie se vería así:
      "p05IcI0n=500; expires=Tue, 19 Jan 2038 04:14:07 GMT;"
    • Al cortar por "p05IcI0n=", tenemos esto:
      Y="","500; expires=Tue, 19 Jan 2038 04:14:07 GMT;"
    • El primer elemento (que en nuestro ejemplo está vacío, pero podría contener otros valores agregados por otros escripts) no nos interesa, así que apuntamos directamente al segundo que es el que empieza con el valor que buscamos (Y[1]):
      Y="500; expires=Tue, 19 Jan 2038 04:14:07 GMT;"
    • Y una vez que lo tenemos en la variable, lo cortamos con otro split(";") para que quede:
      Y=["500"," expires=Tue, 19 Jan 2038 04:14:07 GMT",""]
    • Entonces tomamos solamente el primer elemento (Y[0]), y ya tenemos el valor que buscamos:
      Y = "500"
  • Ahora el mecanismo es igual al ejemplo anterior, esperamos 100 milisegundos y movemos el documento 500px con scrollTo(0,Y) porque Y vale "500".

El método para extraer de una cadena el valor que necesitamos usando split() es poco utilizado porque en cada recorte termina descartando el resto de los valores.

Claramente un objeto que tenga la estructura "clave:valor" es mucho más útil y nos permite aprovechar todas sus parejas; tal como ocurre con los storage.

Y existe una forma de convertir cookies (de string) en objetos. Ya que estamos aquí, aprovecho para hacer una digresión y les muestro cómo hacerlo:

Supongamos que nuestra página tiene una cookie así:

"A=alfa;B=bravo;C=charly;p05IcI0n=500;D=delta"

Y tiene que quedar como un literal de objeto así:

{"A":"alfa","B":"bravo","C":"charly","p05IcI0n":"500","D":"delta"}

Lo primero que debemos hacer es modificar la cadena de texto de la cookie hasta igualar a la del objeto. Eso se hace con replace(); primero cambiamos los "=" y después los ";".

var miGalleta = "A=alfa;B=bravo;C=charly;p05IcI0n=500;D=delta"; var miCadenaObjeto = "{\""+ miGalleta.replace(/=/g,\":\"").replace(/;/g, "\",\"") +"\"}"; console.log(miCadenaObjeto); //'{"A":"alfa","B":"bravo","C":"charly","p05IcI0n":"500","D":"delta}"'

Como han visto, además tiene agregadas las llaves y las comillas del comienzo y final. Pero sigue siendo una cadena de texto, y para convertirla a un objeto que podamos manejar vamos a echar mano de un lenguaje llamado JSON (como el de los Argonautas, en inglés) que es el acrónimo de JavaScript Object Notation, y tal lo indica su nombre, es parte de javascript. Una de las cosas que permite es justamente convertir texto en un objeto propiamente dicho:

var miObjeto = JSON.parse(miCadenaObjeto); //AHORA ES OBJECT var Y = miObjeto.p05IcI0n; //GUARDAMOS EL VALOR DE LA CLAVE p05IcI0n console.log(Y); // 500

Huelga decir que de esta forma podemos leer cualquier cookie en el documento, parsearla a objeto y recorrerla para encontrar una clave o valor que nos interese.

Y ahora sí, terminada la digresión, seguimos con un último ejemplo.

Método tres: Name

Resulta que los anteriores no son los únicos medios para guardar una cadena de texto perdurable. Al menos, entre recargas de página.

Un caso muy común para querer mantener una posición, un foco en formulario, una configuración... es el problema que aparece en el envío de datos al servidor, cuando la página "se recarga sola".

Por lo general, se va a parar al tope del documento, y no siempre es práctico para el usuario si el formulario que está llenando está más abajo y tiene que empezar a buscarlo de nuevo. Y, según cada diseño, pueden existir más valores que no queramos perder, aún después de enviar un formulario.

Así que vamos a cambiar un poco el último ejemplo usando un selector para colores de fondo que se van a mantener aún después del envío, y que se van a ignorar si el formulario no valida (lo podemos confirmar en la barra de dirección si sacamos el ejemplo del pen).

Otro detalle es que no necesitamos un botón (que en este caso además es unsubmit) para guardar automaticamente el color. Se puede hacer al refrescar la página con su comando correspondiente, y en esta demo estoy agregando unas líneas que aparecen ocultas ("comentadas"), como para que las prueben después a gusto.

Y ya que estamos, les presento otro método que mantiene una string (de tamaño muy corto, pero que a nosotros nos sirve) entre refresh de página; ya no entre sesiones.

Cuando necesitamos identificar una ventana, un marco, una nueva pop-up, debemos darle un nombre para después apuntarle con javascript. Ese nombre obviamente se mantiene mientras no cerremos la página madre o la única que tengamos (según sea el caso), así que si le ponemos como window.name la cadena que necesitamos para leer después de la recarga, ya tenemos otro valor a quien recurrir si no queremos usar storages o cookies.

Nota del autor: no recuerdo a quién le vi usar este truco; pero si él no puso los créditos, supongo que yo tampoco debo hacerlo ;-)

See the Pen Remember data with `window.name` by solipsistaCP (@solipsistacp) on CodePen.

El código es tan austero como los previos:

<script type="text/javascript"> window.addEventListener("load", function(){ //alert("Color de fondo: "+window.name); document.body.style.backgroundColor = window.name; }, false); /*window.addEventListener("beforeunload", function(){ window.name=document.formulario.color.value; }); */ </script> · · · <body> <input type="submit" onclick=" alert('Anterior:'+window.name); window.name=document.formulario.color.value; alert('Actual: '+window.name)" value="ENVIAR COLOR DE FONDO" /> </body>

Agregué algunas alertas para seguir los pasos del escript que voy a explicar ahora.

  • Primero encontramos el escuchador de eventos para que al cargar el documento se cambie al nuevo color de fondo. Como en principio no hay ninguno, la instrucción no tiene efecto y va a funcionar recién cuando se asigne un name. Si descomentamos la primer alerta podremos ver el valor del nombre al inicio.
  • El segundo escuchador asigna el evento que se dispara justo antes de salir del documento, y es el que pone como nombre de ventana el color que tenga elegido el select. De momento no trabaja, porque está comentado, pero lo pueden editar en el pen y recargar el marco para confirmar que funciona.
  • La mejor manera de ver cómo mantiene el valor entre recargas (repito: no entre sesiones ni después de un cierre de ventana) es ir al botón, que también tiene dos alertas para confirmar el valor inicial y el nuevo que estamos grabando; además de la línea que cambia manualmente el nombre con el valor del select. En nuestra página de producción, todo esto se elimina, porque el botón es solamente para probar sin refrescar el documento a cada rato.

Es evidente ahora que estos métodos nos permiten guardar no sólo distancias para desplazar o colores de fondo, sino también tamaños de fuente, perfiles de alto contraste, de zoom, ... y cualquier formato de estilo que se nos ocurra ofrecerle al usuario.

Ejemplos así estarían más acordes con el objetivo del blog, pero preferí dejarlos para que los inventaran ustedes.

Furoya: Autor del artículo

Artículo original de Furoya.
La intención del autor con sus colaboraciones no es que los artículos sirvan para hacer un copy&paste de códigos sino que comprendas y aprendas la lógica y el cómo trabaja javaScript.
Y a partir de lo expuesto experimentes tú.
El autor del post y el editor del blog te animamos a que plantees tus dudas o reflexiones y que compartas tus realizaciones en base a lo expuesto en los comentarios. Recuerda que puedes incluir pens (ejemplos en Codepen.io) en ellos.