2009-05-06 39 views
72

Questa domanda è simile a Track when user hits back button on the browser, ma non è la stessa ... Ho una soluzione e la sto postando qui per riferimento e feedback. Se qualcuno ha delle opzioni migliori, sono tutto orecchie!Come posso rilevare se un utente ha accesso a una pagina utilizzando il pulsante Indietro?

La situazione è che ho una pagina con una "modifica sul posto", a la flickr. Cioè c'è un DIV "clicca qui per aggiungere una descrizione", che quando si fa clic si trasforma in un TEXTAREA con i pulsanti Salva e Annulla. Cliccando su Salva posta i dati sul server per aggiornare il database e inserisce la nuova descrizione nel DIV al posto di TEXTAREA. Se la pagina viene aggiornata, la nuova descrizione viene visualizzata dal database con un'opzione "clic per modificare". Al giorno d'oggi, roba standard del web 2.0.

Il problema è che se:

  1. la pagina viene caricata senza la descrizione
  2. una descrizione viene aggiunto dall'utente
  3. la pagina è navigato da cliccando su un link
  4. la l'utente fa clic sul pulsante Indietro

Quindi ciò che viene visualizzato (dalla cache del browser) è la versione della pagina senza t il DIV dinamicamente modificato contenente la nuova descrizione.

Questo è un problema abbastanza grande in quanto l'utente si presuppone che il loro aggiornamento è stato perso e non comprenderà necessariamente che hanno bisogno di aggiornare la pagina per vedere le modifiche.

Quindi, la domanda è: come si può contrassegnare una pagina come modificata dopo che è stata caricata, e quindi rilevare quando l'utente "torna ad esso" e forzare un aggiornamento in quella situazione?

+0

Com'è diverso dalla domanda che hai citato? – innaM

+0

la domanda è simile, ma penso che l'ambiente e quindi la risposta sia diversa, potrei sbagliarmi. la mia interpretazione di quale problema può essere risolto con l'altra soluzione è: l'utente fa clic su una scheda su una pagina caricata da ajax, quindi su un'altra scheda e così via. facendo clic sul pulsante Indietro si ritornerebbe a una pagina diversa, non alla scheda precedente. vogliono tornare indietro attraverso la "storia dell'ajax" all'interno della "cronologia della pagina". almeno questa è la mia impressione su cosa dovrebbe fare il gestore della cronologia di Yahoo Browser. Ero dopo qualcosa di un po 'più di base. – Tom

+0

La risposta accettata presenta il tuo trucco iframe. – innaM

risposta

2

Come già detto, ho trovato una soluzione e la sto postando qui per riferimento e feedback.

La prima fase della soluzione è di aggiungere quanto segue alla pagina:

<!-- 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> 

Il contenuto di fresh.html non sono importanti, quindi la seguente dovrebbe essere sufficiente:

<!-- fresh.html --> 
<HTML><BODY></BODY></HTML> 

Quando lato client il codice aggiorna la pagina, è necessario contrassegnare la modifica come segue:

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 fa tutto il lavoro: quando viene caricato chiama la funzione reload_stale_page che aggiornerà la pagina se necessario. La prima volta che viene caricato (cioè dopo la modifica viene effettuata, la funzione reload_stale_page non farà nulla.)

<!-- stale.html --> 
<HTML><BODY> 
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT> 
</BODY></HTML> 

Dal mio (minima) test in questa fase, questo sembra funzionare come desiderato. Ho trascurato qualcosa?

+1

Questo browser dipende? –

+0

Non che io sappia, ma non l'ho provato completamente. getElementById non è supportato in alcuni browser più vecchi, ma è facile sostituirlo con jquery o qualcosa del genere se necessario. – Tom

72

Utilizzare un modulo nascosto. I dati del modulo vengono conservati (in genere) nei browser quando si ricarica o si preme il pulsante Indietro per tornare a una pagina.Quanto segue va nella tua pagina (probabilmente vicino alla parte inferiore):

<form name="ignore_me"> 
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" /> 
</form> 

In Javascript, è necessario quanto segue:

var dirty_bit = document.getElementById('page_is_dirty'); 
if (dirty_bit.value == '1') window.location.reload(); 
function mark_page_dirty() { 
    dirty_bit.value = '1'; 
} 

il JS che annusa il modulo deve eseguire dopo il codice HTML è completamente analizzato, ma è possibile inserire sia il modulo che il js inline nella parte superiore della pagina (secondo js) se la latenza dell'utente è un problema serio.

+5

"I dati del modulo vengono conservati (in genere) nei browser" - sei in grado di espanderli? non è conservato in alcuni browser? o in alcune situazioni? – Tom

+3

In realtà, vorrei elencare tutti i modi in cui posso pensare di sbagliare. (1) Opera mantiene lo stato completo della pagina e non eseguirà di nuovo il js. (2) Se le impostazioni della cache sono ottimizzate per forzare il caricamento della pagina dal server su back-button, i dati del modulo potrebbero andare persi, il che va bene ai fini di questa domanda. (3) I browser del telefono hanno una cache molto più piccola e il browser potrebbe aver già abbandonato la pagina dalla cache (non è un problema per questi scopi). –

+9

In alcuni browser i tag nascosti non vengono conservati. Quindi potresti usare il tag di testo nascosto invece di usare il tag di input nascosto. \t sajith

11

Questo articolo lo spiega. Vedere il codice qui sotto: 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> 
+1

Questa è una buona risposta, funziona negli ultimi Chrome 40/Firefox 35. Tuttavia, IE11 non supporta tali eventi. –

+0

Secondo http://caniuse.com/#feat=page-transition-events gli eventi di transizione della pagina sono effettivamente supportati in IE11 + Mentre parliamo, l'88% della copertura globale della funzione – Cristian

1

si può risolvere utilizzando l'evento onbeforeunload:

window.onbeforeunload = function() { }

Avere una funzione di gestore di eventi vuoto onbeforeunload significa pagina sarà ricostruito ogni volta che si accede. I javascript verranno rieseguiti, gli script sul lato server verranno rieseguiti, la pagina verrà creata come se l'utente la stesse colpendo per la prima volta, anche se l'utente è arrivato alla pagina semplicemente premendo il pulsante Indietro o Avanti. .

Ecco il codice completo di un esempio:

<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>

provare, vai via questa pagina e poi tornare con "Indietro" o pulsanti "Avanti" nel browser.

Funziona perfettamente con IE, FF e Chrome.

Ovviamente si può fare tutto ciò che si desidera all'interno della funzione myfun.

Maggiori informazioni: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

+1

non funziona in Safari. – mcphersonjr

1

Utilizzando questa pagina, in particolare incorporando il commento di @sajith circa la risposta da @ Nick Bianco e questa pagina: 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(); 
    } 
}); 
2

È possibile utilizzare localStorage o sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp) per impostare un flag (invece di utilizzare un modulo nascosto).

+0

la sua soluzione, ma come si fa se si vuole rilevare questo ogni volta, quando ho aperto il sito e chiuso, ho bisogno di rilevare solo quando ho aperto e tornare prima di chiudere – Elbaz

0

ho incontrato un problema simile oggi e ho risolto con localStorage (qui con un po 'di 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 fondamentalmente:

A pagina 1, quando l'utente invia Nel form, impostiamo un valore "steps" in localStorage per indicare quale passo l'utente ha intrapreso. Allo stesso tempo, lanciamo una funzione con timeout che controllerà se questo valore è stato modificato (ad esempio 10 volte/secondo).

A pagina 2, cambiamo immediatamente detto valore.

Quindi, se l'utente utilizza il pulsante Indietro e il browser ripristina la pagina 1 nello stato esatto in cui lo avevamo lasciato, la funzione checksSteps è ancora in esecuzione e in grado di rilevare che il valore in localStorage è stato modificato (e può prendere le misure appropriate). Una volta che questo controllo ha completato il suo scopo, non è necessario continuare a eseguirlo, quindi non usiamo più setTimeout.

0

Ecco una versione jQuery. Mi è capitato di doverlo utilizzare alcune volte a causa del modo in cui Safari desktop/mobile gestisce la cache quando un utente preme il pulsante Indietro.

$(window).bind("pageshow", function(event) { 
    if (event.originalEvent.persisted) { 
     // Loading from cache 
    } 
}); 
15

Ecco una soluzione moderna molto semplice a questo vecchio 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 è attualmente supportato da tutti i principali browser.

+0

non avevo sentito parlare di questo.Ho appena trovato questa documentazione (https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation) e sarei interessato a sentirti elaborato (es. Perché la necessità di 'window.performance && window .performance.navigation.type' invece di solo 'window.performance.navigation.TYPE_BACK_FORWARD'?). – Ryan

+1

'window.performance.navigation.TYPE_BACK_FORWARD' è una costante che è sempre uguale a 2. Quindi è usata solo per il confronto. – Bassem

+0

Performance.navigation supportato su tutti i dispositivi tranne andorid e opera mini ma nessun problema è molto bello (https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation) – Elbaz

Problemi correlati