2009-05-06 39 views
72

To pytanie jest podobne do Track when user hits back button on the browser, ale nie to samo ... Mam rozwiązanie i zamieszczam je tutaj w celach informacyjnych i opinii. Jeśli ktokolwiek ma lepsze opcje, to ja mam uszy!Jak wykryć, czy użytkownik dotarł do strony za pomocą przycisku Wstecz?

Sytuacja jest taka, że ​​mam stronę z "edycją w miejscu", a la flickr. To znaczy. istnieje "kliknij tutaj, aby dodać opis" DIV, który po kliknięciu zmienia się w TEKSTARIĘ za pomocą przycisków Zapisz i Anuluj. Kliknięcie Zapisz zapisuje dane na serwerze w celu aktualizacji bazy danych i umieszcza nowy opis w DIV zamiast TEXTAREA. Jeśli strona jest odświeżana, nowy opis jest wyświetlany z bazy danych za pomocą opcji "kliknij, aby edytować". W dzisiejszych czasach dość standardowe rzeczy w sieci Web 2.0.

Kwestia jest taka, że ​​jeżeli:

  1. strona jest ładowana bez opisu
  2. opis jest dodawana przez użytkownika
  3. strona jest nawigacja z dala od klikając link
  4. użytkownik klika przycisk powrotu:

To co jest wyświetlane (z pamięci podręcznej przeglądarki) jest wersją strony z t dynamicznie zmodyfikowany DIV zawierający nowy opis.

Jest to dość duży problem, ponieważ użytkownik zakłada, że ​​ich aktualizacja została utracona i nie musi rozumieć, że musi odświeżyć stronę, aby zobaczyć zmiany.

Pytanie brzmi: w jaki sposób można oznaczyć stronę jako zmodyfikowaną po załadowaniu, a następnie wykryć, kiedy użytkownik "wraca" i wymusić odświeżenie w tej sytuacji?

+0

Czym różni się to od pytania, które podałeś? – innaM

+0

pytanie jest podobne, ale myślę, że środowisko, a tym samym odpowiedź jest inna, mógłbym się mylić. Moja interpretacja tego, czym może być problem, który zostałby rozwiązany za pomocą innego rozwiązania, to: użytkownik klika zakładkę na stronie ładowanej przez ajax, a następnie inną kartę i tak dalej. kliknięcie przycisku wstecz spowoduje powrót do innej strony, a nie poprzedniej karty. chcą wrócić do "historii ajaxów" w ramach "historii stron". Mam przynajmniej wrażenie na tym, co powinien zrobić Menedżer Historii Yahoo Browser. Szukałem czegoś bardziej podstawowego. – Tom

+0

Przyjęta odpowiedź zawiera sztuczkę iframe. – innaM

Odpowiedz

2

Jak wspomniano powyżej, znalazłem rozwiązanie i zamieszczam je tutaj w celach informacyjnych i opinii.

Pierwszym etapem rozwiązania jest dodać następujące strony:

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

Zawartość fresh.html nie są ważne, więc następujące powinno wystarczyć:

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

Po stronie klienta kod aktualizuje stronę, musi oznaczać modyfikację w następujący sposób:

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 wykonuje całą pracę: Po wczytaniu wywoła funkcję reload_stale_page, która w razie potrzeby odświeży stronę. Po raz pierwszy jest ładowany (czyli po modyfikacji jest wykonany, funkcja reload_stale_page nie będzie nic robić.)

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

Z mojego (minimalny) badania na tym etapie, to wydaje się działać zgodnie z oczekiwaniami. Czy przeoczyłem coś?

+1

Czy ta przeglądarka jest zależna? –

+0

Nie o tym wiem, ale nie przetestowałem go w pełni. getElementById nie jest obsługiwany w niektórych starszych przeglądarkach, ale można go łatwo zamienić na jquery lub coś w razie potrzeby. – Tom

72

Użyj ukrytego formularza. Dane formularzy są zachowywane (zazwyczaj) w przeglądarkach po przeładowaniu lub naciśnięciu przycisku Wstecz, aby powrócić na stronę.Poniższa idzie w swoją stronę (prawdopodobnie w pobliżu dna):

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

W JavaScript, trzeba będzie następujący:

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

JS że wącha postać musi wykonać po html jest w pełni przeanalizowany, ale możesz umieścić zarówno formularz, jak i js w górnej części strony (js sekunda), jeśli opóźnienie użytkownika jest poważnym problemem.

+5

"Dane formularzy są zachowywane (zazwyczaj) w przeglądarkach" - czy możesz je rozwinąć? czy nie jest on zachowany w niektórych przeglądarkach? lub w niektórych sytuacjach? – Tom

+3

Właściwie, pozwól mi wymienić wszystkie sposoby, które mogę wymyślić, aby pójść źle. (1) Opera zachowuje pełny stan strony i nie będzie ponownie wykonywać js. (2) Jeśli ustawienia pamięci podręcznej zostaną zmodyfikowane, aby wymusić załadowanie strony z serwera na przycisku wstecz, dane formularzy mogą zostać utracone, co jest dobre dla celów tego pytania. (3) Przeglądarki telefoniczne mają znacznie mniejszą pamięć podręczną, a przeglądarka mogła już usunąć stronę z pamięci podręcznej (nie stanowi problemu dla tych celów). –

+9

W niektórych przeglądarkach ukryte znaczniki nie są zachowywane. Więc możesz użyć ukrytego tagu tekstowego zamiast ukrytego tagu wejściowego. \t sajith

11

Ten artykuł wyjaśnia to. Zobacz poniższy kod: 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

To dobra odpowiedź, działa w najnowszym Chrome 40/Firefox 35. Jednak IE11 nie obsługuje tych zdarzeń. –

+0

Według http://caniuse.com/#feat=page-transition-events zdarzenia przejścia strony są rzeczywiście obsługiwane w IE11 + Jak już mówimy, 88% globalnego zasięgu funkcji – Cristian

1

można go rozwiązać za pomocą zdarzenia onbeforeunload:

window.onbeforeunload = function() { }

mającą onbeforeunload pusty funkcję menedżera wydarzenie oznacza stronę zostanie ponownie zbudowany za każdym razem, gdy będzie dostępny. JavaScript uruchomi się ponownie, skrypty po stronie serwera zostaną ponownie uruchomione, strona zostanie zbudowana tak, jakby użytkownik kliknął ją po raz pierwszy, nawet jeśli użytkownik dotarł do strony po prostu naciskając przycisk wstecz lub do przodu .

Oto pełny kod przykładu:

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

Spróbuj, opuścisz tę stronę, a następnie wrócić za pomocą „Wstecz” i „Forward” przyciski w przeglądarce.

Działa dobrze w IE, FF i Chrome.

Oczywiście możesz robić, co chcesz, wewnątrz funkcji myfun.

Więcej informacji: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

+1

nie działa w Safari. – mcphersonjr

1

Korzystanie z tej strony, zwłaszcza włączenie komentarz przez @sajith o odpowiedź przez @Nick White i tej strony: 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

Można użyć localStorage lub sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp), aby ustawić flagę (zamiast ukrytego formularza).

+0

to miłe obejście, ale jak to zrobić, jeśli chce wykryć to za każdym razem, kiedy otworzyłem stronę i zamknąłem ją, muszę wykryć, kiedy otwieram i wracam przed zamknięciem – Elbaz

0

jakie napotkasz podobny problem dzisiaj i rozwiązać go z localStorage (tutaj z odrobiną 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 zasadniczo:

na stronie 1, gdy użytkownik podnosi w formularzu ustawiamy wartość "steps" w localStorage, aby wskazać, jaki krok zrobił użytkownik. Jednocześnie uruchamiamy funkcję z limitem czasu, która sprawdzi, czy ta wartość została zmieniona (na przykład 10 razy/sekundę).

Na stronie 2 natychmiast zmieniamy tę wartość.

Tak więc, jeśli użytkownik użyje przycisku Wstecz, a przeglądarka przywróci stronę 1 w dokładnie tym samym stanie, w jakim ją zostawiliśmy, funkcja checkSteps nadal działa i jest w stanie wykryć, że wartość w localStorage została zmieniona (i może podjąć odpowiednie działanie). Kiedy ta kontrola wypełni swój cel, nie ma potrzeby kontynuowania jej działania, więc po prostu nie używamy setTimeout.

0

Oto wersja jQuery. Zdałem sobie sprawę, że muszę go używać kilka razy ze względu na sposób, w jaki Safari Desktop/Mobile obsługuje pamięć podręczną, gdy użytkownik naciśnie przycisk Wstecz.

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

Oto bardzo proste nowoczesne rozwiązanie tego starego problemu.

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 jest obecnie obsługiwany przez wszystkie główne przeglądarki.

+0

Nie słyszałem o tym.Właśnie znalazłem tę dokumentację (https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation) i chciałbym usłyszeć, jak pracujesz (np. Dlaczego potrzeba 'window.performance && window .performance.navigation.type' zamiast tylko 'window.performance.navigation.TYPE_BACK_FORWARD'?). – Ryan

+1

'window.performance.navigation.TYPE_BACK_FORWARD' jest stałą, która jest zawsze równa 2. Jest więc używana tylko do porównania. – Bassem

+0

Performance.navigation obsługiwane na wszystkich urządzeniach z wyjątkiem andorid i opera mini, ale bez problemu jest bardzo ładne (https://developer.mozilla.org/en-US/docs/Web/API/Performance/navigation) – Elbaz

Powiązane problemy