(Remarque: selon les commentaires de Sharky, j'ai inclus du code pour détecter les espaces arrière)
J'ai donc souvent vu ces questions sur SO, et j'ai récemment rencontré le problème du contrôle de la fonctionnalité du bouton de retour moi-même. Après quelques jours de recherche de la meilleure solution pour mon application (Single-Page with Hash Navigation), j'ai trouvé un système simple, sans navigateur et sans bibliothèque pour détecter le bouton de retour.
La plupart des gens recommandent d'utiliser:
window.onhashchange = function() {
//blah blah blah
}
Cependant, cette fonction sera également appelée lorsqu'un utilisateur utilise un élément sur la page qui modifie le hachage d'emplacement. Pas la meilleure expérience utilisateur lorsque votre utilisateur clique et que la page recule ou avance.
Pour vous donner un aperçu général de mon système, je remplis un tableau avec des hachages précédents pendant que mon utilisateur se déplace dans l'interface. Cela ressemble à ceci:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Assez simple. Je fais cela pour assurer la prise en charge de plusieurs navigateurs, ainsi que la prise en charge des navigateurs plus anciens. Passez simplement le nouveau hachage à la fonction, et il le stockera pour vous, puis changera le hachage (qui sera ensuite mis dans l'historique du navigateur).
J'utilise également un bouton de retour dans la page qui déplace l'utilisateur entre les pages à l'aide du lasthash
tableau. Cela ressemble à ceci:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Donc, cela ramènera l'utilisateur au dernier hachage et supprimera ce dernier hachage du tableau (je n'ai pas de bouton de transfert pour le moment).
Alors. Comment puis-je détecter si un utilisateur a utilisé mon bouton de retour sur la page ou le bouton du navigateur?
Au début, j'ai regardé window.onbeforeunload
, mais en vain - cela n'est appelé que si l'utilisateur va changer de page. Cela ne se produit pas dans une application d'une seule page utilisant la navigation par hachage.
Donc, après quelques recherches supplémentaires, j'ai vu des recommandations pour essayer de définir une variable d'indicateur. Le problème avec cela dans mon cas, c'est que j'essaierais de le définir, mais comme tout est asynchrone, il ne serait pas toujours défini à temps pour l'instruction if dans le changement de hachage. .onMouseDown
n'a pas toujours été appelé en cliquant, et l'ajouter à un onclick ne le déclencherait jamais assez rapidement.
C'est à ce moment que j'ai commencé à regarder la différence entre document
, et window
. Ma dernière solution a été de définir l'indicateur à l'aide de document.onmouseover
et de le désactiver à l'aide de document.onmouseleave
.
Ce qui se passe, c'est que pendant que la souris de l'utilisateur se trouve à l'intérieur de la zone du document (lire: la page rendue, mais en excluant le cadre du navigateur), mon booléen est défini sur true
. Dès que la souris quitte la zone du document, le booléen bascule vers false
.
De cette façon, je peux changer mon window.onhashchange
pour:
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();
}
}
}
Vous noterez le chèque #undefined
. En effet, s'il n'y a pas d'historique disponible dans mon tableau, il revient undefined
. J'utilise ceci pour demander à l'utilisateur s'il souhaite quitter en utilisant unwindow.onbeforeunload
événement.
Donc, en bref, et pour les personnes qui n'utilisent pas nécessairement un bouton de retour dans la page ou un tableau pour stocker l'historique:
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
}
}
Et voila. un moyen simple en trois parties pour détecter l'utilisation du bouton de retour par rapport aux éléments de la page en ce qui concerne la navigation par hachage.
ÉDITER:
Pour vous assurer que l'utilisateur n'utilise pas de retour arrière pour déclencher l'événement de retour, vous pouvez également inclure les éléments suivants (Merci à @thetoolman sur cette question ):
$(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();
}
}
});
});