Entre las nuevas opciones que nos ofrece HTML5 (esta vez, en el sentido más amplio del término, JavaScript incluido) se encuentra la API de visibilidad de página: un pequeño conjunto de propiedades y eventos que nos facilitan el saber si el visitante de nuestra web tiene ésta en primer plano o está viendo otra pestaña.

He preparado dos sencillos ejemplos para ver cómo funciona esta API:

NOTA: El segundo ejemplo no funciona correctamente en Chrome (pausa pero no reanuda luego la reproducción). En Firefox, Opera e IE10 sí funciona y, ya que esto era un simple ejemplo, no he dedicado más tiempo a buscar la causa exacta (lo siento 😛 ).

Veamos cómo llevarlos a cabo:

Simple comprobación de la visibilidad de página

La API de visibilidad nos ofrece dos propiedades y un evento:

  • document.hidden : Propiedad booleana, true si la página no es visible.
  • document.visibilityState : Propiedad que puede ser hidden (oculta), visible (en primer plano) o prerender (la página se está precargando y no es visible al usuario).

El primer ejemplo consiste en este sencillo código HTML:

<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Test de PageVisibility (visibilidad de página)</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>
<h1>Probando las propiedades de visibilidad de página en HTML5</h1>
<p>Cambia de pestaña en tu navegador y comprueba los resultados aquí:</p>
<div id="state"></div>
</div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>

Ahora, mediante JavaScript, obtenemos el valor de visibilityState y lo insertamos en el #state:

// Adaptado de David Walsh y Sam Dutton
// Modificamos el nombre de la propiedad si el navegador ofrece soporte
//mediante prefijos. Según CanIUse sólo debemos preocuparnos por webkit http://caniuse.com/#search=visibility
var hidden, state, visibilityChange, stateDiv, traducciones;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
state = "visibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
state = "webkitVisibilityState";
}

stateDiv = document.getElementById('state');

traducciones = {
'hidden' : "oculta",
'visible' : "visible", //Un poco innecesario, quizá, pero ya que traducimos los demás...
'prerender' : "precargando"
};

// Disparamos una función sobre el evento visibilityChange
document.addEventListener(visibilityChange, function () {
stateDiv.innerHTML += '<br> La página está ahora: <span>' + traducciones[document[state]] + '</span>';
}, false);

// Establecemos el valor inicial
stateDiv.innerHTML = 'La página está ahora: <span>' + traducciones[document[state]] + '</span>';

Al principio del código establecemos una serie de variables para ayudarnos a lidiar con los navegadores que precisan prefijo (actualmente, webkit):

var hidden, state, visibilityChange, stateDiv, traducciones;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
state = "visibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
state = "webkitVisibilityState";
}

Posteriormente, accedemos al div #state:

stateDiv = document.getElementById('state');

Dado que el valor de esta propiedad estará en inglés, almacenamos un objeto con las traducciones necesarias:

traducciones = {
'hidden' : "oculta",
'visible' : "visible", //Un poco innecesario, quizá, pero ya que traducimos los demás...
'prerender' : "precargando"
};

Ahora «escuchamos» (siempre me ha sonado estúpido) el evento visibilityChange y escribimos el resultado en el div #state:

document.addEventListener(visibilityChange, function () {
stateDiv.innerHTML += '<br> La página está ahora: <span>' + traducciones[document[state]] + '</span>';
}, false);

Cuando la página carga, escribimos el estado inicial:

stateDiv.innerHTML = 'La página está ahora: <span>' + traducciones[document[state]] + '</span>';

Puedes ver el resultado en esta demo: http://demo.cmorales.es/pagevisibility/

Pausar y reanudar un slider según la visibilidad de la página

La aplicación práctica del anterior ejemplo es cercana a cero (si no cero directamente 😛 ). Sin embargo, no hace falta ser un genio de la creatividad para encontrar usos mucho más útiles para esta nueva API de HTML5.

Podemos pausar un vídeo cuando el usuario deje nuestra web y reanudar la reproducción cuando vuelva a ella.

Hay webs que dan recompensas al usuario por ver anuncios, vídeos o visitar otras páginas. Podríamos detectar si nuestro usuario está realmente viendo los anuncios y denegarle el premio en caso contrario (siento dar la idea 😛 ).

Si tenemos un carrusel (o slider) automático en nuestra web, podemos pausar su reproducción cuando el usuario no la está viendo, para no malgastar recursos de su navegador. Y esto mismo es lo que he hecho en el segundo ejemplo, usando el popular flexslider (un slider responsive).

He partido directamente de una de las demos que se incluyen en su descarga. Primero necesitamos, como en el ejemplo anterior, configurar unas variables para los navegadores que necesiten prefijos (webkit, no miro a nadie…). Una vez hecho eso, usamos la propia API de flexslider para «escuchar» el evento visibilityChange:

$(window).load(function(){
var hidden, state, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
state = "visibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
state = "webkitVisibilityState";
}

$('.flexslider').flexslider({
animation: "slide",
slideshowSpeed: 3000,
start: function(slider){
$('body').removeClass('loading');
// Disparamos una función sobre el evento visibilityChange
document.addEventListener(visibilityChange, function () {
if ( document[state] == 'hidden' ) {
slider.pause();
} else if ( document[state] == 'visible' ) {
slider.play();
}
}, false);
}
});
});

La animación está configurada para cambiar cada 3 segundos. Sin esta solución, al cambiar de pestaña y volver tras 3 segundos (o más), el carrusel estaría en una foto diferente. Al usar la API de visibilidad, al volver nos encontramos con la misma foto, y la reproducción se reanuda.

NOTA: Como ya indiqué, en Chrome no se reanuda la reproducción, no sé muy bien por qué. El primer ejemplo sí funciona, por lo que supongo que es más un problema del propio Flexslider. Para los propósitos de este tutorial, no me compensa detenerme a solucionarlo.

Una API muy simple, pero que puede dar lugar a soluciones muy interesantes.

Esta entrada fue publicada en Tutorial

4 thoughts on “API de visibilidad de página en HTML5

  1. Justo lo que buscaba,muchas gracias. P.D deberías usar el plugin de facebook para publicar comentarios,da paja escribir correo y nombre,saludos.

    1. De nada.

      PD: Se puede iniciar sesión con FB, Twitter, WordPress o G+, hay unos botones pequeños a la derecha del formulario de comentarios. El plugin de FB no me gusta, aunque gracias por la sugerencia.

  2. Hola, me gustaria saber en el ejemplo del codigo fuente, que programa estas usando y el thema del color que estas usando, muchas gracias y un cordial saludo Sebastián.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Facebook