(Nota: secondo il feedback di Sharky, ho incluso il codice per rilevare i backspaces)
Quindi, ho visto queste domande frequentemente su SO, e recentemente ho incontrato il problema del controllo della funzionalità del pulsante Indietro da solo. Dopo alcuni giorni di ricerca della migliore soluzione per la mia applicazione (Pagina singola con navigazione hash), ho trovato un sistema semplice, senza browser e senza libreria per il rilevamento del pulsante Indietro.
Molte persone raccomandano di usare:
window.onhashchange = function() {
//blah blah blah
}
Tuttavia, questa funzione verrà chiamata anche quando un utente utilizza l'elemento in-page che modifica l'hash della posizione. Non la migliore esperienza utente quando l'utente fa clic e la pagina va avanti o indietro.
Per darti un quadro generale del mio sistema, sto riempiendo un array con hash precedenti mentre il mio utente si sposta attraverso l'interfaccia. Sembra qualcosa del genere:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Abbastanza diretto. Lo faccio per garantire il supporto cross-browser, nonché il supporto per i browser più vecchi. Passa semplicemente il nuovo hash alla funzione e lo memorizzerà per te e poi cambierà l'hash (che viene quindi inserito nella cronologia del browser).
Uso anche un pulsante Indietro in-page che sposta l'utente tra le pagine usando l' lasthash
array. Sembra così:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Quindi, questo riporterà l'utente all'ultimo hash e rimuoverà l'ultimo hash dall'array (al momento non ho un pulsante avanti).
Così. Come faccio a rilevare se un utente ha utilizzato o meno il mio pulsante Indietro in-page o il pulsante del browser?
In un primo momento ho guardato window.onbeforeunload
, ma senza successo - che viene chiamato solo se l'utente sta per cambiare pagina. Ciò non accade in un'applicazione a pagina singola che utilizza la navigazione hash.
Quindi, dopo qualche altro scavo, ho visto dei consigli per provare a impostare una variabile flag. Il problema con questo nel mio caso è che proverei a impostarlo, ma poiché tutto è asincrono, non sarebbe sempre impostato in tempo per l'istruzione if nella modifica dell'hash. .onMouseDown
non veniva sempre chiamato in clic e aggiungerlo a un clic non lo avrebbe mai attivato abbastanza velocemente.
Questo è quando ho iniziato a guardare la differenza tra document
, e window
. La mia soluzione finale era impostare il flag usando document.onmouseover
e disabilitarlo usando document.onmouseleave
.
Quello che succede è che mentre il mouse dell'utente è all'interno dell'area del documento (leggi: la pagina renderizzata, ma escluso il frame del browser), il mio valore booleano è impostato su true
. Non appena il mouse lascia l'area del documento, il booleano si sposta su false
.
In questo modo, posso cambiare il mio window.onhashchange
in:
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();
}
}
}
Noterai il controllo per #undefined
. Questo perché se non c'è cronologia disponibile nel mio array, ritorna undefined
. Lo uso per chiedere all'utente se desidera uscire utilizzando un window.onbeforeunload
evento.
Quindi, in breve, e per le persone che non utilizzano necessariamente un pulsante Indietro in-page o un array per memorizzare la cronologia:
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
}
}
E il gioco è fatto. un modo semplice in tre parti per rilevare l'utilizzo del pulsante Indietro rispetto agli elementi in-page per quanto riguarda la navigazione dell'hash.
MODIFICARE:
Per garantire che l'utente non utilizzi backspace per attivare l'evento back, è possibile includere anche quanto segue (Grazie a @thetoolman su questa domanda ):
$(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();
}
}
});
});