TRUCO: Cómo detectar el cierre o la salida de una página Web

Post original en JASoft.org: http://www.jasoft.org/Blog/post/TRUCO-Como-detectar-el-cierre-o-la-salida-de-una-pagina-Web.aspx

Seguramente te has topado en algunas ocasiones con que, tras haber rellenado algunos campos de un formulario , algunas aplicaciones Web te avisan si pretendes cerrar la ventana o abandonar la página, ya que perderías los datos.

Yo por ejemplo utilizo bastante el webmail de Google, GMail, y muchas veces si acabo de enviar un correo y cierro muy rápido la ventana, como el correo aún no ha terminado de enviarse me avisa para evitar que se pierda.

¿Cómo es posible conseguir esto?

La verdad es que es muy sencillo y se consigue en la práctica totalidad de los navegadores modernos (excepto en Opera) gracias al evento onbeforeunload de la ventana del navegador.

Consideremos el siguiente ejemplo:

<html>

<head>

<title>Prueba de abandono de página</title>

<script language="JavaScript" type0"text/javascript">
     

    var bPreguntar = true;

     

    window.onbeforeunload = preguntarAntesDeSalir;

     

    function preguntarAntesDeSalir()

    {

      if (bPreguntar)

        return "¿Seguro que quieres salir?";

    }

</script>

</head>

<body>

<h1>Ejemplo de abandono de página</h1>

<p>Por defecto preguntará hasta que pulses el botón de "No preguntar"</p>

<input type="button" value="Preguntar" onclick="bPreguntar = true;" >

&nbsp;&nbsp;

<input type="button" value="No preguntar" onclick="bPreguntar = false;" >

<br/><br/>

<a href="http://www.jasoft.org">Ir a otra página</a>

</body>

</html>

Deja de lado el código JavaScript por un momento.

Como vemos se trata de una página muy sencilla. contiene una cabecera, un texto explicativo, dos botones y un enlace. Su aspecto es el siguiente:

AbandonoPagina_1

Hemos creado una variable booleana, bPreguntar, con el valor por defecto verdadero, de modo que servirá para controlar si debemos preguntarle o no al usuario si de verdad quiere abandonar la página (por defecto se lo preguntaremos).

Lo único que tenemos que hacer es interceptar el evento onbeforeunload de la ventana actual y asignarle un manejador apropiado, en este caso le h llamado preguntarAntesDeSalir.

Dentro de este evento el navegador controlamos si se debe preguntar por el abandono de la página o no. El navegador entiende que si como resultado de este evento pasamos una cadena de texto, deberá preguntarle al usuario con ella si quiere abandonar o no la página, mostrando el texto especificado, y dándole a elegir entre ambas opciones (dejar la página o no):

AbandonoPagina_2

Como vemos apenas podemos controlar el aspecto del diálogo, limitándose a mostrar el texto junto con otro texto estándar del propio navegador.

La única "pega" es precisamente que no seremos capaces de controlar el aspecto de este diálogo y que éste cambia además entre los diferentes navegadores (los tengo todos instalados en inglés):

AbandonoPagina_3

Como vemos Firefox hace caso omiso del texto que le hemos indicado y muestra un mensaje propio. Chrome/Safari e Internet Explorer muestran un mensaje estándar pero lo acompañan de nuestro texto para poder dar una información más detallada. Personalmente el diálogo que me parece más claro es el de Internet Explorer.

Este evento se definió por primera vez en Internet Explorer 4 (¡en 1997!), y los demás navegadores le fueron añadiendo soporte mucho más adelante. En la actualidad está soportado por todas las versiones modernas de los navegadores. Yo lo he probado con Internet Explorer 7, 8 y 9, con Firefox 4, 5, 6 y 7 y con Google Chrome. Debería funcionar perfectamente con Safari tanto en Windows como en Mac. Me consta que no funciona con Opera pero no lo he probado.

¡Espero que te resulte útil!

Sin categoría

3 thoughts on “TRUCO: Cómo detectar el cierre o la salida de una página Web

  1. Descubrí el evento OnBeforeUnload hace poco tiempo pero no me sirvió. Se trataba de un proyecto donde el servidor mantiene una conexión con base de datos siempre activa (y este requisito era innegociable), y quise usarlo para avisar al usuario de que debía cerrar la conexión antes de abandonar la página.

    El inconveniente que encontré es que se pregunta incluso cuando navegamos a otra página de la propia aplicación, no había manera de preguntar sólo al navegar fuera o cerrar el navegador.
    Técnicamente sé que se podría extender el comportamiento de OnBeforeUnload, estableciendo un flag antes de navegar a otra página de la aplicación para evitar la pregunta (algo como tu bPreguntar), pero entonces no podría utilizar sencillos enlaces href sino métodos Javascript, por lo que tras buscar alguna librería que hiciera esto y no encontrarla, lo descarté.

    Aprovechando que sacas el tema, ¿sabes de alguna solución? 😉

  2. Hola Pablo,

    Lo que no sé es siquiera cómo conseguir que tengas la conexión a la BBDD abierta todo el tiempo en el servidor, ya que la página al terminar su ciclo de vida la cerrará ¿no?
    Además es muy poco escalable, ues en las apps Web se trata siempre de todo lo contrario a eso… En fin, es simple curiosidad…

    En cualquier caso, el evento salta incluso al recargar la página actual, como tú dices.

    Tendría que hacer pruebas, pero yo creo que la mejor estrategia en este caso sería interceptar el evento onunload de la ventana actual.

    Desde éste abres inmediatamente otra ventana lo más pequeña que puedas, desde la cual detectas si la ventana padre existe o no. Si existe es que es un cambio de página, no un cierre de la ventana. Si no existe es que es un cierre y entonces puedes lanzar la tarea que consideres oportuna en el servidor llamando a otra página que a su vez cierre la centana que has abierto.

    Tendría el efecto «chungo» de que habría una pequeña ventanita que se abriría cada vez que cambies de página, pero también tus requisitos no son precisamente los más normales 🙂

    Otra posible solución que se me ocurre es la siguiente:

    1.- Pones el tiempo de sesión muy pequeño (no sé, un minuto, o algo que tenga sentido para la demora en el cierre de la conexión).
    2.- Tienes una página en el servidor que sirva únicamente para mantener la sesión abierta, del estilo de la técnica que explico aquí: http://www.jasoft.org/Blog/post/PermaLinkaspxguid=7c56bb9b-6955-4865-880b-f964ca6.aspx
    3.- En el cierre de sesón (Session_onEnd) cierras la conexión.

    No sé, seguramente estrujándome el coco un poco más se me ocurriría alguna cosa adicional, pero con estos dos creo que hay posibilidades.

    Saludos,

  3. Gracias José Manuel.

    En cuanto a mantener la conexión abierta, puse los mismos inconvenientes que tú y algunos más, pero como indico era «innegociable»: se usa el número de conexiones del servidor como control de usuarios concurrentes, y este es el concepto de facturación al cliente final, además hay conexiones desde otros clientes no web (Windows) por lo que la respuesta fue: NO.

    Gracias por las ideas, la primera de la ventana en el cambio de página no la había pensado, pero como tú dices tiene un aspecto feo (casi tan feo como mantener la conexión abierta en el servidor 😉

    Pero la idea de la caducidad de la sesión sí me gusta, de hecho tengo hecho algo similar pero con aviso al usuario:
    1. Caducidad de unos 5 minutos.
    2. A los 4 minutos, JavaScript muestra una ventana: «Va a caducar la sesión [Mantener] [Abandonar]»
    3. Si se pulsa mantener, se hace algo como lo que tú propones: mantener la sesión viva en el servidor y reiniciar esos 4 minutos.

    Son los problemas que nos surgen por migrar aplicaciones antiguas sin libertad para hacer borrón y cuenta nueva.

    Y para otra vez comentaré en jasoft para evitar bifurcaciones.

    ¡Saludos!

Deja un comentario

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