javascript - evento - deshabilitar boton atras en navegador
Cómo detectar el evento del botón Atrás del navegador-Navegador cruzado (8)
¿Cómo se puede detectar definitivamente si el usuario presionó o no el botón Atrás en el navegador?
¿Cómo se exige el uso de un botón de retroceso dentro de la página dentro de una aplicación web de una sola página usando un sistema #URL
?
¿Por qué los botones del navegador no disparan sus propios eventos?
(Nota: según los comentarios de Sharky, he incluido el código para detectar retrocesos)
Por lo tanto, he visto estas preguntas con frecuencia en SO, y recientemente me he topado con el problema de controlar la funcionalidad del botón de retroceso por mi cuenta. Después de unos días de buscar la mejor solución para mi aplicación (una página con Hash Navigation), he encontrado un sistema simple, de navegador cruzado y sin bibliotecas para detectar el botón Atrás.
La mayoría de las personas recomiendan usar:
window.onhashchange = function() {
//blah blah blah
}
Sin embargo, esta función también se invocará cuando un usuario use un elemento dentro de la página que cambie el hash de ubicación. No es la mejor experiencia de usuario cuando su usuario hace clic y la página va hacia atrás o hacia adelante.
Para darle un esquema general de mi sistema, estoy llenando una matriz con hashes previos a medida que mi usuario se mueve a través de la interfaz. Se ve algo como esto:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Muy claro. Hago esto para asegurar el soporte entre navegadores, así como el soporte para navegadores más antiguos. Simplemente pase el nuevo hash a la función y lo almacenará por usted y luego cambiará el hash (que luego se colocará en el historial del navegador).
También utilizo un botón de retroceso en la página que mueve al usuario entre páginas usando la matriz lasthash
. Se parece a esto:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Así que esto moverá al usuario de nuevo al último hash, y eliminará el último hash de la matriz (no tengo ningún botón de reenvío en este momento).
Asi que. ¿Cómo puedo detectar si un usuario ha usado o no mi botón de retroceso en la página o el botón del navegador?
Al principio miré window.onbeforeunload
, pero fue en vano, solo se llama si el usuario va a cambiar de página. Esto no ocurre en una aplicación de una sola página que utiliza navegación hash.
Entonces, después de excavar más, vi recomendaciones para tratar de establecer una variable de indicador. El problema con esto en mi caso es que trataría de configurarlo, pero como todo es asincrónico, no siempre se establecería a tiempo para la instrucción if en el cambio de hash. .onMouseDown
no siempre se llamó con un clic, y agregarlo a un onclick nunca lo desencadenaría lo suficientemente rápido.
Esto es cuando comencé a ver la diferencia entre el document
y la window
. Mi solución final fue establecer el indicador usando document.onmouseover
, y deshabilitarlo usando document.onmouseleave
.
Lo que sucede es que, mientras el mouse del usuario está dentro del área del documento (léase: la página representada, pero excluyendo el marco del navegador), mi booleano se establece en true
. Tan pronto como el mouse abandona el área del documento, el booleano cambia a false
.
De esta manera, puedo cambiar mi window.onhashchange
a:
window.onhashchange = function() {
if (window.innerDocClick) {
window.innerDocClick = false;
} else {
if (window.location.hash != ''#undefined'') {
goBack();
} else {
history.pushState("", document.title, window.location.pathname);
location.reload();
}
}
}
Notará el cheque de #undefined
. Esto es porque si no hay historial disponible en mi matriz, devuelve undefined
. Lo uso para preguntarle al usuario si quiere irse usando un evento window.onbeforeunload
.
Entonces, en resumen, y para las personas que no necesariamente usan un botón de retroceso en la página o una matriz para almacenar el historial:
document.onmouseover = function() {
//User''s mouse is inside the page.
window.innerDocClick = true;
}
document.onmouseleave = function() {
//User''s mouse has left the page.
window.innerDocClick = false;
}
window.onhashchange = function() {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back button was clicked
}
}
Y ahí lo tienes. una forma simple, en tres partes, para detectar el uso del botón de retroceso frente a los elementos en la página con respecto a la navegación hash.
EDITAR:
Para asegurarse de que el usuario no utilice el retroceso para activar el evento posterior, también puede incluir lo siguiente (Gracias a @thetoolman en esta pregunta ):
$(function(){
/*
* this swallows backspace keys on any non-input element.
* stops backspace -> back
*/
var rx = /INPUT|SELECT|TEXTAREA/i;
$(document).bind("keydown keypress", function(e){
if( e.which == 8 ){ // 8 == backspace
if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
e.preventDefault();
}
}
});
});
Aquí está mi opinión. La suposición es que, cuando la URL cambia pero no se detecta ningún clic dentro del document
detectado, se trata de un explorador de vuelta (sí o reenviar). El clic de un usuario se restablece después de 2 segundos para que esto funcione en páginas que cargan contenido a través de Ajax:
(function(window, $) {
var anyClick, consoleLog, debug, delay;
delay = function(sec, func) {
return setTimeout(func, sec * 1000);
};
debug = true;
anyClick = false;
consoleLog = function(type, message) {
if (debug) {
return console[type](message);
}
};
$(window.document).click(function() {
anyClick = true;
consoleLog("info", "clicked");
return delay(2, function() {
consoleLog("info", "reset click state");
return anyClick = false;
});
});
return window.addEventListener("popstate", function(e) {
if (anyClick !== true) {
consoleLog("info", "Back clicked");
return window.dataLayer.push({
event: ''analyticsEvent'',
eventCategory: ''test'',
eventAction: ''test''
});
}
});
})(window, jQuery);
Document.mouseover no funciona para IE y FireFox. Sin embargo, he intentado esto:
$(document).ready(function () {
setInterval(function () {
var $sample = $("body");
if ($sample.is(":hover")) {
window.innerDocClick = true;
} else {
window.innerDocClick = false;
}
});
});
window.onhashchange = function () {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back or forward button was pressed
}
};
Esto funciona para Chrome e IE y no para Firefox. Todavía estoy trabajando para que Firefox funcione bien. Cualquier forma fácil de detectar el clic del botón para avanzar / retroceder del navegador es bienvenido, no particularmente en JQuery sino también en AngularJS o Javascript simple.
Había estado luchando con este requisito durante bastante tiempo y tomé algunas de las soluciones anteriores para implementarlo. Sin embargo, me encontré con una observación y parece funcionar en los navegadores Chrome, Firefox y Safari + Android y iPhone
En la carga de la página:
window.history.pushState({page: 1}, "", "");
window.onpopstate = function(event) {
// "event" object seems to contain value only when the back button is clicked
// and if the pop state event fires due to clicks on a button
// or a link it comes up as "undefined"
if(event){
// Code to handle back button or prevent from navigation
}
else{
// Continue user action through link or button
}
}
Déjeme saber si esto ayuda. Si me falta algo, lo entenderé con gusto.
Lo resolví haciendo un seguimiento del evento original que desencadenó el hashchange
(ya sea un golpe, un clic o una rueda), para que el evento no se confundiera con un simple aterrizaje en la página, y usando una bandera adicional en cada uno de mis enlaces de eventos. El navegador no volverá a configurar la bandera en false
al presionar el botón Atrás:
var evt = null,
canGoBackToThePast = true;
$(''#next-slide'').on(''click touch'', function(e) {
evt = e;
canGobackToThePast = false;
// your logic (remember to set the ''canGoBackToThePast'' flag back to ''true'' at the end of it)
}
Navegador: https://jsfiddle.net/Limitlessisa/axt1Lqoz/
Para control móvil: https://jsfiddle.net/Limitlessisa/axt1Lqoz/show/
$(document).ready(function() {
$(''body'').on(''click touch'', ''#share'', function(e) {
$(''.share'').fadeIn();
});
});
// geri butonunu yakalama
window.onhashchange = function(e) {
var oldURL = e.oldURL.split(''#'')[1];
var newURL = e.newURL.split(''#'')[1];
if (oldURL == ''share'') {
$(''.share'').fadeOut();
e.preventDefault();
return false;
}
//console.log(''old:''+oldURL+'' new:''+newURL);
}
.share{position:fixed; display:none; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.8); color:white; padding:20px;
<!DOCTYPE html>
<html>
<head>
<title>Back Button Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body style="text-align:center; padding:0;">
<a href="#share" id="share">Share</a>
<div class="share" style="">
<h1>Test Page</h1>
<p> Back button press please for control.</p>
</div>
</body>
</html>
Probé las opciones anteriores, pero ninguna de ellas me funciona. Aquí está la solución
if(window.event)
{
if(window.event.clientX < 40 && window.event.clientY < 0)
{
alert("Browser back button is clicked...");
}
else
{
alert("Browser refresh button is clicked...");
}
}
Consulte este enlace http://www.codeproject.com/Articles/696526/Solution-to-Browser-Back-Button-Click-Event-Handli para más detalles
Puede probar el controlador de eventos popstate
, por ejemplo:
window.addEventListener(''popstate'', function(event) {
// The popstate event is fired each time when the current history entry changes.
var r = confirm("You pressed a Back button! Are you sure?!");
if (r == true) {
// Call Back button programmatically as per user confirmation.
history.back();
// Uncomment below line to redirect to the previous page instead.
// window.location = document.referrer // Note: IE11 is not supporting this.
} else {
// Stay on the current page.
history.pushState(null, null, window.location.pathname);
}
history.pushState(null, null, window.location.pathname);
}, false);
Nota: para obtener los mejores resultados, debe cargar este código solo en páginas específicas donde desea implementar la lógica para evitar cualquier otro problema inesperado.
El evento popstate se activa cada vez que cambia la entrada del historial actual (el usuario navega a un nuevo estado). Eso sucede cuando el usuario hace clic en los botones Atrás / Adelante del navegador o cuando se llaman programáticamente los métodos history.back()
, history.forward()
, history.go()
.
El event.state
es propiedad del evento y es igual al objeto de estado histórico.
Para la sintaxis de jQuery, envuélvala (para agregar incluso el oyente después de que el documento esté listo):
(function($) {
// Above code here.
})(jQuery);
Ver también: window.onpopstate en la carga de la página
Vea también los ejemplos en las aplicaciones de una sola página y en la página pushState HTML5 :
<script>
// jQuery
$(window).on(''popstate'', function (e) {
var state = e.originalEvent.state;
if (state !== null) {
//load content with ajax
}
});
// Vanilla javascript
window.addEventListener(''popstate'', function (e) {
var state = e.state;
if (state !== null) {
//load content with ajax
}
});
</script>
Esto debería ser compatible con Chrome 5+, Firefox 4+, IE 10+, Safari 6+, Opera 11.5+ y similares.