Come verificare se l'utente può tornare indietro nella cronologia del browser o meno


Risposte:


119

Risposta breve: non puoi.

Tecnicamente esiste un modo preciso, che verificherebbe la proprietà:

history.previous

Tuttavia, non funzionerà. Il problema è che nella maggior parte dei browser questa è considerata una violazione della sicurezza e di solito restituisce un valore indefinito .

history.length

È una proprietà che altri hanno suggerito ...
Tuttavia , la lunghezza non funziona completamente perché non indica dove ti trovi nella storia. Inoltre, non inizia sempre con lo stesso numero. Un browser non impostato per avere una pagina di destinazione, ad esempio, inizia da 0 mentre un altro browser che utilizza una pagina di destinazione inizierà da 1.

testo alternativo

Il più delle volte viene aggiunto un collegamento che chiama:

history.back();

o

 history.go(-1);

e si prevede che se non è possibile tornare indietro, fare clic sul collegamento non fa nulla.


Questa è una buona informazione, ma non risolve il problema. Sarebbe per elaborare del codice che funziona effettivamente su qualsiasi browser. Forse un codice che controlla prima il browser che stai utilizzando.
Santiago Bendavid,

5
Quello che sto dicendo è che non esiste una risposta definitiva. Stai dicendo i pro e i contro di ogni approccio, ma non come ottenere uno script che controlla quale browser stai usando ed esegui in modo condizionale l'uno o l'altro pezzo di codice.
Santiago Bendavid,

Posso sapere cosa intendi con "Il problema è che nella maggior parte dei browser questa è considerata una violazione della sicurezza" Un altro utente in un altro thread ha anche indicato che essere in grado di ottenere la cronologia del browser del client sta violando la sicurezza, ma non spiega perché. Qualcuno può dare qualche esempio quali sono le minacce alla sicurezza?
Kevin Chandra,

Un sito Web non dovrebbe essere in grado di conoscere la cronologia di un utente che potrebbe includere informazioni personali indirette. Un sito può utilizzare il monitoraggio / i cookie per sapere cosa sta facendo l'utente sul sito stesso, ma non dovrebbe, ad esempio, essere autorizzato a capire quale banca utilizzo, a quale scuola vanno i miei figli, ecc ... Pertanto, i browser non consentiranno l'accesso a quella proprietà
McAden

84

C'è un altro modo per verificare: controlla il referrer. La prima pagina di solito avrà un referrer vuoto ...

if (document.referrer == "") {
    window.close()
} else {
    history.back()
}

3
Il referrer può essere nascosto per motivi di privacy.
Kornel,

11
Il referrer è sempre vuoto quando una pagina non è stata caricata da un collegamento ma inserendo l'URL nella barra degli indirizzi o caricando un segnalibro. Tali pagine possono sicuramente avere una cronologia, quando la scheda / finestra del browser aveva già caricato un'altra pagina!
giovedì

1
Ma è la soluzione applicabile per la navigazione attraverso il sito web multipagina
Dan,

36
Non funziona se una finestra è stata aperta con target = "_ blank" per forzare una nuova finestra. Il pulsante Indietro sul browser non funzionerà, ma ci sarà un document.referrer
Mike_K

3
Questo non funzionerà se si proviene da una pagina protetta (HTTPS) a una pagina non protetta (HTTP), poiché ciò rimuoverà il referrer.
Kevin Borders,

55

Il mio codice consente al browser di tornare indietro di una pagina e, in caso contrario, carica un URL di fallback. Rileva anche le modifiche agli hashtag.

Quando il pulsante Indietro non era disponibile, l'URL di fallback verrà caricato dopo 500 ms, quindi il browser ha il tempo sufficiente per caricare la pagina precedente. Il caricamento dell'URL di fallback subito dopo window.history.go(-1);indurrebbe il browser a utilizzare l'URL di fallback, poiché lo script js non si è ancora fermato.

function historyBackWFallback(fallbackUrl) {
    fallbackUrl = fallbackUrl || '/';
    var prevPage = window.location.href;

    window.history.go(-1);

    setTimeout(function(){ 
        if (window.location.href == prevPage) {
            window.location.href = fallbackUrl; 
        }
    }, 500);
}

7
Penso che questo inchiodi davvero il nocciolo della domanda, il perché una persona si preoccupa e cosa si può effettivamente fare al riguardo in modo affidabile e coerente.
Chris Marisic,

1
Ha funzionato fino a quando ho preso l'URL in cui risiede il pulsante Indietro e lo ho incollato in una nuova scheda in cromo. Facendo clic sul pulsante Indietro si è arrivati ​​a una scheda vuota. :(
karlingen,

3
Questo è il comportamento predefinito di Chrome. Hai "visitato" la pagina chrome://newtabe quindi puoi tornare indietro nella storia.
redelschaap

Fai attenzione perché con una connessione di rete lenta raggiungerai l'URL di fallback abbastanza regolarmente.
Cameck,

14

Ecco come l'ho fatto.

Ho usato l' evento 'beforeunload' per impostare un valore booleano. Quindi ho impostato un timeout per controllare se il "beforeunload" è stato attivato.

var $window = $(window),
    $trigger = $('.select_your_link'),
    fallback = 'your_fallback_url';
    hasHistory = false;

$window.on('beforeunload', function(){
    hasHistory = true;
});

$trigger.on('click', function(){

    window.history.go(-1);

    setTimeout(function(){
        if (!hasHistory){
            window.location.href = fallback;
        }
    }, 200);

    return false;
});

Sembra funzionare nei principali browser (testato FF, Chrome, IE11 finora).


1
Questa è di gran lunga la migliore risposta alla domanda. Puoi facilmente sostituirlo window.location.href = fallbackcon window.close()e funziona anche.
Vitani,

13

questo sembra fare il trucco:

function goBackOrClose() {  

    window.history.back();
    window.close(); 

    //or if you are not interested in closing the window, do something else here
    //e.g. 
    theBrowserCantGoBack();

}

Chiama history.back () e quindi window.close (). Se il browser è in grado di tornare indietro nella cronologia, non sarà in grado di passare alla dichiarazione successiva. Se non è in grado di tornare indietro, chiuderà la finestra.

Tuttavia, tieni presente che se la pagina è stata raggiunta digitando un URL, Firefox non consentirà allo script di chiudere la finestra.


3
Ho scoperto che questo non funziona se non uso un setTimeout con un ritardo di alcune centinaia di millisecondi circa prima di provare a eseguire la dichiarazione successiva, altrimenti verrà eseguito comunque dopo aver eseguito history.back ()
Ken Fehling il

Non l'ho provato personalmente, quale browser era?
xtrahelp.com

Avevo lavorato bene con la funzione setTimeout nella risposta di seguito. es: setTimeout (function () {window.close ()}, 400);
Gilchris,

2
window.close()è considerato un rischio per la sicurezza da molti browser moderni. Alcuni non ti lasceranno fare.
Rudi Kershaw,

puoi fare qualsiasi cosa dopo window.history.back (); window.close (); è solo un esempio
hariszaman,

13

C'è uno snippet che utilizzo nei miei progetti:

function back(url) {
    if (history.length > 2) {
        // if history is not empty, go back:
        window.History.back();
    } else if (url) {
        // go to specified fallback url:
        window.History.replaceState(null, null, url);
    } else {
        // go home:
        window.History.replaceState(null, null, '/');
    }
}

Cordiali saluti: Uso History.js per gestire la cronologia del browser.


Perché confrontare history.length con il numero 2?

Perché la pagina iniziale di Chrome viene conteggiata come primo elemento nella cronologia del browser.


Esistono poche possibilità history.lengthe il comportamento dell'utente:

  • L'utente apre una nuova scheda vuota nel browser e quindi esegue una pagina. history.length = 2e vogliamo disabilitareback() in questo caso, perché l'utente passerà alla scheda vuota.
  • L'utente apre la pagina in una nuova scheda facendo clic su un collegamento da qualche parte prima. history.length = 1e di nuovo vogliamo disabilitareback() metodo.
  • E infine, l'utente arriva alla pagina corrente dopo aver ricaricato alcune pagine . history.length > 2e ora back()può essere abilitato.

Nota: ometto il caso in cui l'utente accede alla pagina corrente dopo aver fatto clic sul collegamento dal sito Web esterno senzatarget="_blank" .

Nota 2: document.referrer è vuoto quando si apre il sito Web digitando il suo indirizzo e anche quando il sito Web utilizza ajax per caricare le sottopagine, quindi ho smesso di controllare questo valore nel primo caso.


Questo approccio ha funzionato alla grande per me. In realtà memorizzo collegamenti di fallback statici per le mie pagine che utilizzo sul fallback.
Greg Blass,

Ma, se torni indietro, la storia.lunghezza non cambierà .. Quindi, non funziona correttamente
Ciprian Mocanu

Sfortunatamente, hai ragione. Uso questo frammento solo con la struttura "un passo indietro" ...
gregmatys,

10

Fai attenzione window.history.lengthperché include anche voci perwindow.history.forward()

Quindi potresti avere forse window.history.lengthpiù di 1 voci, ma nessuna cronologia. Ciò significa che non succede nulla se spariwindow.history.back()


9

Non è possibile verificare direttamente se il pulsante Indietro è utilizzabile. Puoi guardare history.length>0, ma ciò sarà vero se ci sono anche pagine davanti alla pagina corrente. Puoi solo essere sicuro che il pulsante Indietro sia inutilizzabile quandohistory.length===0 .

Se ciò non è abbastanza buono, tutto ciò che puoi fare è chiamare history.back()e, se la tua pagina viene ancora caricata in seguito, il pulsante Indietro non è disponibile! Ovviamente ciò significa che se il pulsante Indietro è disponibile, ti sei appena allontanato dalla pagina. Non ti è permesso annullare la navigazione onunload, quindi tutto quello che puoi fare per fermare il ritorno in realtà è restituire qualcosa daonbeforeunload , il che si tradurrà in un grande prompt fastidioso. Non ne vale la pena.

In effetti, in genere è un'idea davvero negativa fare qualsiasi cosa con la storia. La navigazione della cronologia è per browser Chrome, non per pagine Web. L'aggiunta di collegamenti "torna indietro" in genere provoca più confusione dell'utente di quanto valga la pena.


2
per quanto riguarda la lunghezza, nemmeno in tutti i browser. Alcuni browser considerano la pagina corrente come un elemento della cronologia e iniziano da 1. Dovresti includere il rilevamento del browser.
McAden,

In realtà ho pensato che fosse sempre 1! L' 0era un brainfart, ho pensato che i browser sarebbe sempre rispondere con 1o più. Si scopre che Opera e IE la pensano diversamente: buona cattura.
bobince,

1
"La navigazione della cronologia è per browser Chrome, non per pagine Web" - Concordato
Brian

5

history.lengthè inutile in quanto non mostra se l'utente può tornare indietro nella cronologia. Anche diversi browser utilizzano i valori iniziali 0 o 1, dipende dal browser.

La soluzione funzionante è utilizzare l' $(window).on('beforeunload'evento, ma non sono sicuro che funzionerà se la pagina viene caricata tramite Ajax e utilizza pushState per modificare la cronologia delle finestre.

Quindi ho usato la prossima soluzione:

var currentUrl = window.location.href;
window.history.back();
setTimeout(function(){
    // if location was not changed in 100 ms, then there is no history back
    if(currentUrl === window.location.href){
        // redirect to site root
        window.location.href = '/';
    }
}, 100);

Funziona per me in questo modo: funzione goBackOrTo (targetUrl) {var currentUrl = window.location.href; window.history.go (-1); setTimeout (function () {// se la posizione non è stata modificata in 800 ms, allora non vi è alcuna cronologia se (currentUrl === window.location.href) {// reindirizza al root del sito window.location.href = targetUrl; }}, 800); }
alfonx,

2

Ho trovato il seguente approccio. Utilizza l'evento onbeforeunload per rilevare se il browser inizia a lasciare la pagina o meno. In caso contrario, verrà reindirizzato al fallback.

var goBack = function goBack(fallback){
    var useFallback = true;

    window.addEventListener("beforeunload", function(){
      useFallback = false;
    });

    window.history.back();

    setTimeout(function(){
        if (useFallback){ window.location.href = fallback; }
    }, 100); 
}

È possibile chiamare questa funzione utilizzando goBack("fallback.example.org").


1
Mi piace di più, sono appena passato windows.onbeforeunloadal listener di eventi in window.addEventListener("beforeunload", function (event) { useFallback = false; });modo che non sovrascriva window.onbeforeunload.
MiChAeLoKGB,

2

Basandoci sulla risposta qui e qui . Penso che la risposta più conclusiva sia solo verificare se questa è una nuova pagina in una nuova scheda.

Se la cronologia della pagina è più di una, allora possiamo tornare alla pagina precedente alla pagina corrente. In caso contrario, la scheda è una scheda aperta di recente e dobbiamo creare una nuova scheda.

Diversamente, alle risposte collegate, non stiamo verificando la presenza di un referrerdato che una nuova scheda avrà ancora un referrer.

if(1 < history.length) {
    history.back();
}
else {
    window.close();
}

1
Grazie. Mi hai salvato la giornata :).
Bijay Yadav,

1

C'è un'altra soluzione quasi perfetta, presa da un'altra risposta SO :

if( (1 < history.length) && document.referrer ) {
    history.back();
}
else {
    // If you can't go back in history, you could perhaps close the window ?
    window.close();
}

Qualcuno ha riferito che non funziona durante l'utilizzo target="_blank"ma sembra funzionare per me su Chrome.


0

il browser ha il pulsante Indietro e Avanti. Ho trovato una soluzione su questa domanda. ma influenzerà l'azione di inoltro del browser e causerà bug con alcuni browser.

Funziona così: se il browser apre un nuovo url, che non si è mai aperto, la storia.lunghezza aumenterà.

così puoi cambiare l'hash come

  location.href = '#__transfer__' + new Date().getTime() 

per ottenere un URL mai mostrato, quindi history.length otterrà la lunghezza reale.

  var realHistoryLength = history.length - 1

ma, non sempre funziona bene, e non so perché, specialmente quando l'url salta rapidamente.


0

Stavo cercando di trovare una soluzione e questa è la migliore che ho potuto trovare (ma funziona alla grande ed è la soluzione più semplice che ho trovato anche qui).

Nel mio caso, volevo tornare alla cronologia con un pulsante Indietro, ma se la prima pagina che l'utente ha aperto fosse una sottopagina della mia app, sarebbe tornata alla pagina principale.

La soluzione è stata, non appena l'app è stata caricata, ho appena fatto una sostituzione sullo stato della cronologia:

history.replaceState( {root: true}, '', window.location.pathname + window.location.hash)

In questo modo, devo solo controllare history.state.rootprima di tornare indietro. Se vero, faccio invece sostituire una cronologia:

if(history.state && history.state.root)
    history.replaceState( {root: true}, '', '/')
else
    history.back() 

Non credo ci siano altri casi di buon uso. Forse non è una buona idea Se vuoi controllare la cronologia al di fuori della tua app.
Maxwell sc

-1
var fallbackUrl = "home.php";
if(history.back() === undefined)
    window.location.href = fallbackUrl;

sembra super facile ?! è testato sui vari browser?
benzkji,

in Chrome history.back()è undefinedsolo nella pagina vuota
gregmatys

-2

Soluzione

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  }
}

spiegazione

window.location.pathnameti darà l'URI corrente. Ad esempio https://domain/question/1234/i-have-a-problemdarà /question/1234/i-have-a-problem. Vedere la documentazione su window.location per ulteriori informazioni.

Successivamente, la chiamata a split()ci darà tutti i frammenti di quell'URI. quindi se prendiamo il nostro precedente URI, avremo qualcosa di simile ["", "question", "1234", "i-have-a-problem"]. Vedere la documentazione su String.prototype.split () per ulteriori informazioni.

La chiamata a filter()è qui per filtrare la stringa vuota generata dalla barra all'indietro. In pratica restituirà solo l'URI del frammento che ha una lunghezza maggiore di 1 (stringa non vuota). Quindi avremmo qualcosa di simile ["question", "1234", "i-have-a-question"]. Questo avrebbe potuto essere scritto così:

'use strict';
window.location.pathname.split('/').filter(function(fragment) {
  return fragment.length > 0;
});

Vedere la documentazione su Array.prototype.filter () e il compito di Destructuring per ulteriori informazioni.

Ora, se l'utente tenta di tornare indietro mentre è https://domain/attivo, non attiveremo l'istruzione if, quindi non attiveremo il window.history.back()metodo in modo che l'utente rimanga nel nostro sito Web. Questo URL sarà equivalente al []quale ha una lunghezza di 0ed 0 > 0è falso. Quindi, silenziosamente fallendo. Naturalmente, puoi registrare qualcosa o eseguire un'altra azione se lo desideri.

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  } else {
    alert('You cannot go back any further...');
  }
}

limitazioni

Naturalmente, questa soluzione non funzionerà se il browser non supporta l' API Cronologia . Controlla la documentazione per saperne di più prima di utilizzare questa soluzione.


-5

Non sono sicuro che funzioni ed è completamente non testato, ma prova questo:

<script type="text/javascript">

    function goBack() {
        history.back();
    }

    if (history.length > 0) { //if there is a history...
        document.getElementsByTagName('button')[].onclick="goBack()"; //assign function "goBack()" to all buttons onClick
    } else {
        die();
    }
</script>

E da qualche parte in HTML:

<button value="Button1"> //These buttons have no action
<button value="Button2">

MODIFICARE:

Quello che puoi anche fare è cercare quali browser supportano la funzione back (penso che tutti lo facciano) e utilizzare l'oggetto standard di rilevamento browser JavaScript trovato e descritto a fondo in questa pagina . Quindi puoi avere 2 pagine diverse: una per i "buoni browser" compatibile con il pulsante Indietro e una per i "cattivi browser" che dice loro di andare ad aggiornare il loro browser


2
history.backè una funzione. Vuoi verificare se history.length > 0poi è tornato indietro conhistory.back()
pixl coder

3
Anche []su un NodeList non ha senso e non è possibile assegnare una stringa a un gestore eventi.
Bobince,

-8

Controlla se window.history.lengthè uguale a 0.


6
Non è un buon modo, dal momento che history.length non ti dice dove sei nella storia ...
Ron Reiter,

@Ron Reiter: Sì, penso che la risposta migliore e altri commenti a questa domanda lo abbiano già stabilito che oltre un anno fa ...
Cristian Sanchez,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.