Verhindern Sie jede Form der Seitenaktualisierung mit jQuery / Javascript


89

Sobald der Benutzer auf meiner Seite ist, möchte ich nicht, dass er die Seite aktualisiert.

  1. Der Benutzer F5drückt jederzeit auf die Schaltfläche "Aktualisieren" oder "Aktualisieren". Er sollte einen Alarm erhalten

    Sie können die Seite nicht aktualisieren.

  2. Auch wenn der Benutzer einen neuen Tab öffnet und versucht, auf dieselbe URL im vorherigen Tab zuzugreifen, sollte er eine Warnung erhalten

    Sie können dieselbe Seite nicht in zwei Registerkarten öffnen

Wie auch immer, ich kann dies mit JavaScript oder jQuery tun? Punkt eins ist wirklich wichtig.


Sie können mithilfe der Broadcast Channel-API ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) erkennen und Nachrichten senden, mit denen zwischen Registerkarten kommuniziert werden soll. Auf diese Weise können Sie mehrere Registerkarten mit derselben URL erkennen und andere Registerkarten blockieren.
aXuser264

Antworten:


189

# 1 kann über implementiert werden window.onbeforeunload.

Beispielsweise:

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

Der Benutzer wird mit der Nachricht aufgefordert und erhält die Option, auf der Seite zu bleiben oder seinen Weg fortzusetzen. Dies wird immer häufiger. Der Stapelüberlauf führt dies aus, wenn Sie versuchen, während der Eingabe eines Beitrags von einer Seite weg zu navigieren. Sie können den Benutzer nicht vollständig vom erneuten Laden abhalten, aber Sie können es wirklich beängstigend klingen lassen, wenn dies der Fall ist.

# 2 ist mehr oder weniger unmöglich. Selbst wenn Sie Sitzungen und Benutzeranmeldungen nachverfolgen würden, könnten Sie nicht garantieren, dass Sie eine zweite Registerkarte korrekt erkannt haben. Zum Beispiel habe ich vielleicht ein Fenster geöffnet und dann geschlossen. Jetzt öffne ich ein neues Fenster. Sie würden das wahrscheinlich als zweiten Tab erkennen, obwohl ich den ersten bereits geschlossen habe. Jetzt kann Ihr Benutzer nicht auf das erste Fenster zugreifen, weil er es geschlossen hat, und er kann nicht auf das zweite Fenster zugreifen, weil Sie es ablehnen.

Tatsächlich ist das Online-System meiner Bank sehr bemüht, Nummer 2 zu erreichen, und die oben beschriebene Situation tritt ständig auf. Normalerweise muss ich warten, bis die serverseitige Sitzung abläuft, bevor ich das Bankensystem wieder verwenden kann.


1
Nur ein Hinweis, dass das Ereignis onbeforeunload in Versionen des Opera-Browsers nicht verfügbar ist.
WillyCornbread

1
Gibt es eine Möglichkeit, etwas zu tun, wenn der Benutzer auf der Seite bleiben möchte?
Riship89

5
Hat den Trick für mich gemacht, obwohl Sie stattdessen window.addEventListener (siehe developer.mozilla.org/en-US/docs/Web/Events/beforeunload ) verwenden sollten, um die Cross-Browser-Kompatibilität zu gewährleisten und Bibliotheksprobleme zu vermeiden.
Julien Bérubé

Ich weiß, dass diese Frage alt ist, aber wenn sie wirklich mehrere Sitzungen verhindern wollten, könnten sie WebSockets verwenden?
Meghan

1
@ Sean - Ja ... wenn Sie wirklich mehrere Sitzungen verhindern wollten. Ein WebSocket kann zustandsbehaftete, bidirektionale Kommunikation durchführen. Der Client wird (wahrscheinlich) nicht plötzlich zu einer anderen Person, während das WebSocket verbunden ist. Sie sollten daher in der Lage sein, diesem Benutzer ein Token zuzuweisen und es zu löschen, sobald der Socket geschlossen wird. Aber es geht um das erwartete Verhalten des Benutzeragenten, also ist es wahrscheinlich eine schlechte UX. Ich kann mir extrem wenige Fälle vorstellen, in denen so etwas angemessen wäre (vielleicht ein Online-Spiel - um zu verhindern, dass sich jemand als zwei Todesklauen der Stufe 37 anmeldet ...).
Seth

35

Sie können nicht verhindern, dass der Benutzer aktualisiert wird, und Sie sollten es auch nicht wirklich versuchen. Sie sollten zurückgehen, warum Sie diese Lösung benötigen. Was ist das Hauptproblem hier?. Beginnen Sie dort und finden Sie einen anderen Weg, um das Problem zu lösen. Vielleicht haben Sie herausgefunden, warum Sie glauben, dass Sie dies tun müssen, um eine solche Lösung zu finden.

Grundlegende Browserfunktionen zu brechen ist niemals eine gute Idee. Über 99,999999999% des Internets funktionieren und werden mit F5 aktualisiert. Dies ist eine Erwartung des Benutzers, die Sie nicht brechen sollten.


Das Problem ist, dass die Seite eine Siebel-Anwendung ist. Wenn sich ein Benutzer in einer Sitzung befindet und auf Aktualisieren klickt, wird eine neue Sitzung erstellt und die App stürzt ab. Daher muss der Benutzer nicht aktualisieren können.
Pankaj

20
@pankaj - Dies sollte auf der Anwendungswebsite behoben werden, z. B. Cookies, damit der Benutzer die Sitzung über mehrere Registerkarten hinweg teilt.
Nick Craver

9
Ich bin mir nicht sicher, woher du kommst. Unzählige Websites im Internet verhindern eine Browseraktualisierung, wenn Sie ein verschmutztes Formular haben, und machen Sie darauf aufmerksam, dass Sie möglicherweise Ihre Änderungen verlieren. Ich bin mir nicht sicher, warum dies "grundlegende Browserfunktionen verletzt".
Siraris

1
@ Siraris: Genau. Außerdem erstelle ich eine private Anwendung, die der Benutzer auch dann verwenden kann, wenn er sich nicht in seinem privaten Netzwerk befindet. Ich speichere also alles im Browser-Speicher für die Offline-Verwendung, aber wenn er die Seite neu lädt, ist die gesamte Anwendung weg. Es mag nicht sehr "üblich" sein, aber in dieser modernen IT-Welt wird es immer mehr.
cslotty

14

Obwohl es keine gute Idee ist, die F5-Taste zu deaktivieren, können Sie dies in JQuery wie folgt tun.

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

Hoffe das wird helfen!


27
Was ist mit OSX, wo es CMD + R ist? Oder mobil, wo es einen Knopf zum Drücken gibt? Ich sehe dies nicht als Lösung
ItalyPaleAle

14

In den alten Tagen von CGI hatten wir viele Formen, die verschiedene Backend-Aktionen auslösten. Wie Textbenachrichtigungen an Gruppen, Druckaufträge, Datenerfassung usw.

Wenn sich der Benutzer auf einer Seite befand, auf der stand: "Bitte warten Sie ... Führen Sie einen RIESIGEN Job aus, der einige Zeit dauern kann." Sie würden eher REFRESH treffen und das wäre SCHLECHT!

WARUM? Weil es langsamere Jobs auslösen und schließlich das Ganze zum Erliegen bringen würde.

Die Lösung? Erlaube ihnen, ihre Form zu machen. Wenn sie ihr Formular abschicken ... Starten Sie Ihren Job und leiten Sie sie auf eine andere Seite weiter, auf der sie aufgefordert werden, zu warten.

Wo die Seite in der Mitte tatsächlich die Formulardaten enthielt, die zum Starten des Jobs benötigt wurden. Die WAIT-Seite enthält jedoch eine Zerstörung des Javascript-Verlaufs. Sie können diese Warteseite also nach Belieben neu laden, und der ursprüngliche Job wird niemals im Hintergrund gestartet, da diese WAIT-Seite nur die Formulardaten enthält, die für WAIT selbst erforderlich sind.

Hoffe das macht Sinn.

Die Funktion zum Zerstören des Verlaufs verhinderte auch, dass sie auf ZURÜCK klicken und dann ebenfalls aktualisieren konnten.

Es war sehr nahtlos und funktionierte viele Jahre lang großartig, bis der gemeinnützige Verein aufgelöst wurde.

Beispiel: FORMULAREINGABE - Sammeln Sie alle Informationen. Wenn diese gesendet werden, wird Ihr Backend-Job ausgelöst.

ANTWORT vom Formulareintrag - Gibt HTML zurück, das eine Umleitung zu Ihrer statischen Warteseite und / oder POST / GET zu einem anderen Formular (der WAIT-Seite) durchführt.

WARTESEITE - Enthält nur FORM-Daten zur Warteseite sowie Javascript, um den neuesten Verlauf zu zerstören. Wie (-1 ODER -2), um nur die neuesten Seiten zu zerstören, aber sie können trotzdem zu ihrer ursprünglichen FORMULAR-Eintragsseite zurückkehren.

Sobald sie sich auf Ihrer WAIT-Seite befinden, können sie so oft auf REFRESH klicken, wie sie möchten, und es wird niemals der ursprüngliche FORM-Job im Backend erzeugt. Stattdessen sollte Ihre WAIT-Seite eine zeitgesteuerte META-Aktualisierung selbst enthalten, damit sie immer den Status ihres Jobs überprüfen kann. Wenn ihr Auftrag abgeschlossen ist, werden sie von der Warteseite zu einem beliebigen Ort weitergeleitet.

Wenn sie manuell REFRESHEN ... Sie fügen dort einfach eine weitere Überprüfung ihres Jobstatus hinzu.

Hoffentlich hilft das. Viel Glück.


2
Sie haben nicht genug Anerkennung für diese erstaunliche und informative Antwort erhalten. Danke dir!!
ShiningLight


2

Nummer (2) ist möglich, indem eine Socket-Implementierung (wie websocket, socket.io usw.) mit einem benutzerdefinierten Heartbeat für jede Sitzung verwendet wird, an der der Benutzer beteiligt ist. Wenn ein Benutzer versucht, ein anderes Fenster zu öffnen, wird eine JavaScript-Handlerprüfung durchgeführt mit dem Server, wenn es in Ordnung ist, und dann mit einer Fehlermeldung antworten.

Eine bessere Lösung besteht jedoch darin, die beiden Sitzungen nach Möglichkeit wie in Google Docs zu synchronisieren.


2

Problem Nr. 2 kann jetzt mit BroadcastAPI gelöst werden .

Derzeit ist es nur in Chrome, Firefox und Opera verfügbar.

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);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.