ajax - evento - deshabilitar boton atras en navegador
¿Cómo puedo detectar si un usuario ha llegado a una página usando el botón Atrás? (9)
Aquí hay una solución moderna muy fácil para este viejo problema.
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
alert(''Got here using the browser "Back" or "Forward" button.'');
}
window.performance es actualmente compatible con todos los principales navegadores.
Esta pregunta es similar a Seguir cuando el usuario pulsa el botón Atrás en el navegador , pero no es el mismo ... Tengo una solución y la estoy publicando aquí para referencia y comentarios. Si alguien tiene mejores opciones, ¡soy todo oídos!
La situación es que tengo una página con una "edición in situ", a la flickr. Es decir, hay una DIV "haga clic aquí para agregar una descripción" que, al hacer clic, se convierte en TEXTAREA con los botones Guardar y Cancelar. Al hacer clic en Guardar, se publican los datos en el servidor para actualizar la base de datos y se coloca la nueva descripción en el DIV en lugar de TEXTAREA. Si la página se actualiza, la nueva descripción se muestra desde la base de datos con la opción "hacer clic para editar". Cosas bastante estándar de la web 2.0 en estos días.
El problema es que si:
- la página se carga sin la descripción
- una descripción es agregada por el usuario
- la página se navega hacia afuera haciendo clic en un enlace
- el usuario hace clic en el botón Atrás
Entonces, lo que se muestra (desde el caché del navegador) es la versión de la página sin el DIV modificado dinámicamente que contiene la nueva descripción.
Este es un problema bastante grande ya que el usuario asume que su actualización se ha perdido y no necesariamente entenderá que necesita actualizar la página para ver los cambios.
Entonces, la pregunta es: ¿cómo se puede marcar una página como modificada después de que se ha cargado, y luego detectar cuándo el usuario "regresa a ella" y forzar una actualización en esa situación?
Aquí hay una versión de jQuery. Me he encontrado con la necesidad de usarlo algunas veces debido a la forma en que Safari desktop / mobile maneja la caché cuando un usuario presiona el botón Atrás.
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
// Loading from cache
}
});
Como mencioné anteriormente, encontré una solución y la estoy publicando aquí para referencia y comentarios.
La primera etapa de la solución es agregar lo siguiente a la página:
<!-- at the top of the content page -->
<IFRAME id="page_is_fresh" src="fresh.html" style="display:none;"></IFRAME>
<SCRIPT style="text/javascript">
function reload_stale_page() { location.reload(); }
</SCRIPT>
Los contenidos de fresh.html
no son importantes, por lo que lo siguiente debería ser suficiente:
<!-- fresh.html -->
<HTML><BODY></BODY></HTML>
Cuando el código del lado del cliente actualiza la página, necesita marcar la modificación de la siguiente manera:
function trigger_reload_if_user_clicks_back_button()
{
// "dis-arm" the reload stale page function so it doesn''t fire
// until the page is reloaded from the browser''s cache
window.reload_stale_page = function(){};
// change the IFRAME to point to a page that will reload the
// page when it loads
document.getElementById("page_is_fresh").src = "stale.html";
}
stale.html
hace todo el trabajo: cuando se carga llamará a la función reload_stale_page
, que actualizará la página si es necesario. La primera vez que se carga (es decir, después de realizar la modificación, la función reload_stale_page
no hará nada).
<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>
A partir de mi (mínimo) examen en esta etapa, esto parece funcionar como se desea. ¿He pasado por alto algo?
Este artículo lo explica. Vea el código a continuación: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
<html>
<head>
<script>
function pageShown(evt){
if (evt.persisted) {
alert("pageshow event handler called. The page was just restored from the Page Cache (eg. From the Back button.");
} else {
alert("pageshow event handler called for the initial load. This is the same as the load event.");
}
}
function pageHidden(evt){
if (evt.persisted) {
alert("pagehide event handler called. The page was suspended and placed into the Page Cache.");
} else {
alert("pagehide event handler called for page destruction. This is the same as the unload event.");
}
}
window.addEventListener("pageshow", pageShown, false);
window.addEventListener("pagehide", pageHidden, false);
</script>
</head>
<body>
<a href="http://www.webkit.org/">Click for WebKit</a>
</body>
</html>
Me encontré con un problema similar hoy y lo resolví con localStorage (aquí con un poco de jQuery):
$(function() {
if ($(''#page1'').length) {
// this code must only run on page 1
var checkSteps = function () {
if (localStorage.getItem(''steps'') == ''step2'') {
// if we are here, we know that:
// 1. the user is on page 1
// 2. he has been on page 2
// 3. this function is running, which means the user has submitted the form
// 4. but steps == step2, which is impossible if the user has *just* submitted the form
// therefore we know that he has come back, probably using the back button of his browser
alert(''oh hey, welcome back!'');
} else {
setTimeout(checkSteps, 100);
}
};
$(''#form'').on(''submit'', function (e) {
e.preventDefault();
localStorage.setItem(''steps'', ''step1''); // if "step1", then we know the user has submitted the form
checkOrderSteps();
// ... then do what you need to submit the form and load page 2
});
}
if ($(''#page2'').length) {
// this code must only run on page 2
localStorage.setItem(''steps'', ''step2'');
}
});
Si básicamente:
En la página 1, cuando el usuario envía el formulario, establecemos un valor "steps" en localStorage para indicar qué paso ha realizado el usuario. Al mismo tiempo, lanzamos una función con tiempo de espera que verificará si se ha cambiado este valor (por ejemplo, 10 veces / segundo).
En la página 2, cambiamos inmediatamente dicho valor.
Entonces, si el usuario usa el botón Atrás y el navegador restaura la página 1 en el estado exacto en que se encontraba cuando lo dejamos, la función checkSteps aún se está ejecutando, y es capaz de detectar que el valor en localStorage ha cambiado (y puede tomar las medidas apropiadas ) Una vez que este control ha cumplido su propósito, no hay necesidad de continuar ejecutándolo, por lo que simplemente no usamos setTimeout nunca más.
Puede usar localStorage o sessionStorage ( http://www.w3schools.com/html/html5_webstorage.asp ) para establecer un marcador (en lugar de usar un formulario oculto).
Puedes resolverlo usando el evento onbeforeunload :
window.onbeforeunload = function () { }
Tener una función de administrador de eventos vacío antes de descargar significa que la página se volverá a construir cada vez que se acceda a ella. Los javascripts volverán a ejecutarse, los scripts del lado del servidor se volverán a ejecutar, la página se compilará como si el usuario estuviera tocando por primera vez, incluso si el usuario llega a la página simplemente presionando el botón Atrás o Atrás .
Aquí está el código completo de un ejemplo:
<html>
<head>
<title>onbeforeunload.html</title>
<script>
window.onbeforeunload = function () { }
function myfun()
{
alert("The page has been refreshed.");
}
</script>
<body onload="myfun()">
Hello World!<br>
</body>
</html>
Pruébelo, navegue fuera de esta página y luego regrese usando los botones "Atrás" o "Adelante" en su navegador.
Funciona bien en IE, FF y Chrome.
Por supuesto, puedes hacer lo que quieras dentro de la función myfun .
Más información: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript
Usando esta página, especialmente incorporando el comentario de @sajith sobre la respuesta de @Nick White y esta página: http://www.mrc-productivity.com/techblog/?p=1235
<form name="ignore_me" style="display:none">
<input type="text" id="reloadValue" name="reloadValue" value="" />
</form>
$(function ()
{
var date = new Date();
var time = date.getTime();
if ($("#reloadValue").val().length === 0)
{
$("#reloadValue").val(time);
}
else
{
$("#reloadValue").val("");
window.location.reload();
}
});
Use una forma oculta Los datos del formulario se conservan (típicamente) en los navegadores cuando recarga o presiona el botón Atrás para regresar a una página. Lo siguiente va en su página (probablemente cerca de la parte inferior):
<form name="ignore_me">
<input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>
En su javascript, necesitará lo siguiente:
var dirty_bit = document.getElementById(''page_is_dirty'');
if (dirty_bit.value == ''1'') window.location.reload();
function mark_page_dirty() {
dirty_bit.value = ''1'';
}
El js que olfatea el formulario tiene que ejecutarse después de que el html se haya analizado por completo, pero puede poner tanto el formulario como el js en línea en la parte superior de la página (js segundos) si la latencia del usuario es una preocupación grave.