Zapobiegaj jakiejkolwiek formie odświeżania strony za pomocą jQuery / Javascript


93

Gdy użytkownik jest na mojej stronie, nie chcę, aby odświeżał stronę.

  1. W dowolnym momencie użytkownik kliknie F5lub odświeży przycisk na górze. Powinien otrzymać ostrzeżenie

    Nie możesz odświeżyć strony.

  2. Również jeśli użytkownik otworzy nową kartę i spróbuje uzyskać dostęp do tego samego adresu URL w poprzedniej karcie, powinien otrzymać alert

    Nie możesz otworzyć tej samej strony w 2 kartach

W każdym razie mogę to zrobić za pomocą JavaScript lub jQuery? Punkt pierwszy jest naprawdę ważny.


Możesz wykrywać za pomocą interfejsu Broadcast Channel API ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) i wysyłać wiadomości do komunikacji między kartami. W związku z tym, używając tego możesz wykryć wiele kart z tym samym adresem URL i zablokować inne karty.
aeXuser264

Odpowiedzi:


195

# 1 można wdrożyć za pośrednictwem window.onbeforeunload.

Na przykład:

<script type="text/javascript">
    window.onbeforeunload = function() {
        return "Dude, are you sure you want to leave? Think of the kittens!";
    }
</script>

Użytkownik zostanie poproszony o wyświetlenie komunikatu i otrzyma opcję pozostania na stronie lub kontynuowania podróży. To staje się coraz bardziej powszechne. Stack Overflow robi to, jeśli spróbujesz opuścić stronę podczas pisania postu. Nie możesz całkowicie powstrzymać użytkownika przed ponownym załadowaniem, ale możesz sprawić, że zabrzmi to naprawdę przerażająco, jeśli to zrobi.

# 2 jest mniej więcej niemożliwe. Nawet jeśli śledzisz sesje i loginy użytkowników, nadal nie będziesz w stanie zagwarantować, że poprawnie wykryłeś drugą kartę. Na przykład może mam otwarte jedno okno, a następnie je zamykam. Teraz otwieram nowe okno. Prawdopodobnie zauważysz to jako drugą kartę, mimo że już zamknąłem pierwszą. Teraz twój użytkownik nie może uzyskać dostępu do pierwszego okna, ponieważ je zamknął, i nie może uzyskać dostępu do drugiego okna, ponieważ mu odmawiasz.

W rzeczywistości system internetowy mojego banku bardzo się stara, aby zrobić numer 2, a sytuacja opisana powyżej ma miejsce cały czas. Zwykle muszę czekać, aż sesja po stronie serwera wygaśnie, zanim będę mógł ponownie korzystać z systemu bankowego.


1
Tylko uwaga, że ​​zdarzenie onbeforeunload nie jest dostępne w wersjach przeglądarki Opera.
WillyCornbread

1
Czy można coś zrobić, jeśli użytkownik zdecyduje się pozostać na stronie?
riship89

5
Zrobiłem sztuczkę dla mnie, chociaż powinieneś zamiast tego użyć window.addEventListener (patrz developer.mozilla.org/en-US/docs/Web/Events/beforeunload ), aby uzyskać zgodność z różnymi przeglądarkami i zapobiec problemom z bibliotekami.
Julien Bérubé

Wiem, że to pytanie jest stare, ale gdyby naprawdę chcieli zapobiec wielu sesjom, czy mogliby użyć WebSockets?
Meghan,

1
@Sean - Tak ... jeśli naprawdę chcesz zapobiec wielu sesjom. WebSocket może realizować stanową, dwukierunkową komunikację. Klient (prawdopodobnie) nie stanie się nagle kimś innym, gdy WebSocket jest podłączony, więc powinieneś być w stanie przypisać token do tego użytkownika i wyczyścić go po zamknięciu gniazda. Ale hakuje oczekiwane zachowanie klienta użytkownika, więc prawdopodobnie jest to zły UX. Przychodzi mi do głowy bardzo niewiele przypadków, w których coś takiego byłoby odpowiednie (może gra online - aby uniemożliwić komuś zalogowanie się jako dwa pazury śmierci na 37 poziomie ...).
Seth

34

Nie możesz uniemożliwić użytkownikowi odświeżania, ani też nie powinieneś próbować. Powinieneś wrócić do tego , dlaczego potrzebujesz tego rozwiązania, jaki jest tutaj główny problem? Zacznij tam i znajdź inny sposób rozwiązania problemu. Być może wyjaśniłeś, dlaczego uważasz, że musisz to zrobić, pomogłoby to w znalezieniu takiego rozwiązania.

Łamanie podstawowych funkcji przeglądarki nigdy nie jest dobrym pomysłem, ponad 99,999999999% internetu działa i odświeża się za pomocą F5, jest to oczekiwanie użytkownika, którego nie należy łamać.


Problem w tym, że strona to aplikacja siebel. a kiedy użytkownik jest w sesji i odświeża się, tworzona jest nowa sesja, a aplikacja ulega awarii. więc potrzebuję, aby użytkownik nie mógł odświeżyć.
pankaj

20
@pankaj - Należy to naprawić na stronie aplikacji i na przykład pliki cookie, aby użytkownik udostępnił sesję na kartach.
Nick Craver

9
Nie wiem, skąd się stąd wybierasz. Niezliczone witryny w Internecie uniemożliwiają odświeżenie przeglądarki, jeśli masz brudny formularz, ostrzegając Cię o tym, że możesz utracić wprowadzone zmiany. Nie wiem, dlaczego to „łamie podstawowe funkcje przeglądarki”.
Siraris,

1
@Siraris: Dokładnie. Dodatkowo tworzę prywatną aplikację, z której użytkownik powinien korzystać nawet wtedy, gdy nie ma go w swojej prywatnej sieci. Więc przechowuję wszystko w pamięci przeglądarki do użytku offline, ale jeśli ponownie załaduje stronę, cała aplikacja zniknie. Może nie jest to zbyt „normalne”, ale we współczesnym świecie IT będzie coraz bardziej.
cslotty

16

Chociaż nie jest dobrym pomysłem wyłączenie klawisza F5, możesz to zrobić w JQuery, jak poniżej.

<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };

$(document).ready(function(){
     $(document).on("keydown", disableF5);
});
</script>

Mam nadzieję, że to pomoże!


28
A co z OSX, gdzie jest CMD + R? Lub telefon komórkowy, gdzie jest przycisk do naciśnięcia? Nie widzę tego jako rozwiązania
WłochyPaleAle

14

W dawnych czasach CGI mieliśmy wiele form, które wyzwalały różne działania zaplecza. Takie jak powiadomienia tekstowe do grup, zadania drukowania, hodowla danych itp.

Jeśli użytkownik był na stronie, na której było napisane „Proszę czekać… Wykonywanie OGROMNEJ pracy, która może zająć trochę czasu.”. Byli bardziej skłonni do uderzenia REFRESH i to byłoby ZŁE!

CZEMU? Ponieważ spowodowałoby to wolniejsze prace i ostatecznie ugrzęzło całą sprawę.

Rozwiązanie? Pozwól im zrobić swoją formę. Po przesłaniu formularza ... Rozpocznij pracę, a następnie skieruj ich na inną stronę, która każe im czekać.

Gdzie strona w środku faktycznie zawierała dane formularza potrzebne do rozpoczęcia zadania. Strona CZEKAJ zawiera jednak zniszczenie historii javascript. Dzięki temu mogą PONOWNIE ZAŁADOWAĆ tę stronę oczekiwania, ile chcą, i nigdy nie spowoduje to uruchomienia oryginalnego zadania w tle, ponieważ ta strona CZEKAJ zawiera tylko dane formularza potrzebne do samego CZEKANIA.

Mam nadzieję, że to ma sens.

Funkcja niszczenia historii uniemożliwiła im również kliknięcie WSTECZ, a następnie odświeżenie.

Było bardzo płynne i działało świetnie przez WIELE lat, aż organizacja non-profit została zlikwidowana.

Przykład: ZGŁOSZENIE FORMULARZA - Zbierz wszystkie informacje, a po przesłaniu uruchomi to zadanie backendu.

ODPOWIEDŹ od wpisu formularza - zwraca kod HTML, który wykonuje przekierowanie do statycznej strony oczekiwania i / lub POST / GET do innego formularza (strona CZEKAJ).

POCZEKAJ STRONĘ - zawiera tylko dane FORMULARZA związane ze stroną oczekiwania, a także javascript do zniszczenia najnowszej historii. Na przykład (-1 LUB -2), aby zniszczyć tylko najnowsze strony, ale nadal umożliwia im powrót do oryginalnej strony wejściowej FORMULARZA.

Gdy znajdą się na stronie CZEKAJ, mogą kliknąć ODŚWIEŻ tyle, ile chcą, i nigdy nie spowoduje to odrodzenia oryginalnego zadania FORMULARZA na zapleczu. Zamiast tego strona CZEKAJ powinna obejmować odświeżanie czasowe META, aby zawsze mogła sprawdzić status swojego zadania. Po zakończeniu pracy są przekierowywani ze strony oczekiwania na dowolne miejsce.

Jeśli zrobią to ręcznie, ODŚWIEŻ… Po prostu dodają tam jeszcze jedno sprawdzenie statusu ich pracy.

Mam nadzieję, że to pomoże. Powodzenia.


2
Nie masz wystarczającego uznania za tę niesamowitą i pouczającą odpowiedź. Dziękuję Ci!!
ShiningLight


2

Numer (2) jest możliwy dzięki zastosowaniu implementacji gniazda (takiej jak websocket, socket.io itp.) Z niestandardowym pulsem dla każdej sesji, w której jest zaangażowany użytkownik. Jeśli użytkownik próbuje otworzyć inne okno, masz kontrolę obsługi javascript z serwerem, jeśli wszystko jest w porządku, a następnie odpowiedz komunikatem o błędzie.

Jednak lepszym rozwiązaniem jest zsynchronizowanie dwóch sesji, jeśli to możliwe, jak w Google Docs.


2

Problem nr 2 można teraz rozwiązać za pomocą BroadcastAPI .

W tej chwili jest dostępny tylko w Chrome, Firefox i Opera.

var bc = new BroadcastChannel('test_channel');

bc.onmessage = function (ev) { 
    if(ev.data && ev.data.url===window.location.href){
       alert('You cannot open the same page in 2 tabs');
    }
}

bc.postMessage(window.location.href);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.