Zapobiegaj opuszczaniu strony internetowej za pomocą JavaScript

129

Jak zapobiec opuszczaniu strony internetowej za pomocą JavaScript?

Entuzjastyczne oprogramowanie
źródło
Co powoduje opuszczenie tej strony?
Niyaz
9
Zgodnie z pytaniem, JavaScript sprawia, że ​​nawigacja dalej ...
Shog9
@ Shog9 to może być zamknięcie zakładki i nawigacja. Mój palec wskazujący zrobił to ...
Bob Stein

Odpowiedzi:

159

Używanie onunloadpozwala na wyświetlanie komunikatów, ale nie przerywa nawigacji (bo jest już za późno). Jednak użycie onbeforeunloadspowoduje przerwanie nawigacji:

window.onbeforeunload = function() {
  return "";
}

Uwaga: zwracany jest pusty ciąg, ponieważ nowsze przeglądarki wyświetlają komunikat, taki jak „Wszelkie niezapisane zmiany zostaną utracone”, którego nie można zastąpić.

W starszych przeglądarkach można określić komunikat do wyświetlenia w monicie:

window.onbeforeunload = function() {
  return "Are you sure you want to navigate away?";
}
Jimmie R. Houts
źródło
11
Przeglądarka wyświetli odpowiedni monit. Po prostu użyjwindow.onbeforeunload = function() { return ""; }
KIM Taegyoon
Ale to nie wystarczy. A co z kontrolkami wewnątrz formularza? One też to wywołują.
Fandango68
1
Nowoczesne przeglądarki nie pozwalają na wyświetlanie niestandardowego komunikatu w monicie, ponieważ był on nadużywany przez phisherów i tym podobne.
Flimm
Dzięki @Flimm, zaktualizowałem odpowiedź, więc jest teraz poprawna dla obecnych przeglądarek.
Jimmie R. Houts
@Flimm Chcę zaktualizować stan online użytkownika, gdy użytkownicy online zamykają kartę przeglądarki lub przeglądarkę. Użyłem kodu w rozwiązaniu, ale nie zadziałało. Czy jest na to rozwiązanie?
Nasimba
23

W przeciwieństwie do innych przedstawionych tutaj metod, ten fragment kodu nie będzie spowoduje, że przeglądarka wyświetli ostrzeżenie z pytaniem, czy użytkownik chce wyjść; zamiast tego wykorzystuje zdarzeniową naturę DOM do przekierowania z powrotem do bieżącej strony (i tym samym anulowania nawigacji), zanim przeglądarka będzie miała szansę wyładować go z pamięci.

Ponieważ działa poprzez bezpośrednie zwieranie nawigacji, nie można go używać do zapobiegania zamknięciu strony; jednak można go użyć do wyłączenia funkcji omijania ramek.

(function () {
    var location = window.document.location;

    var preventNavigation = function () {
        var originalHashValue = location.hash;

        window.setTimeout(function () {
            location.hash = 'preventNavigation' + ~~ (9999 * Math.random());
            location.hash = originalHashValue;
        }, 0);
    };

    window.addEventListener('beforeunload', preventNavigation, false);
    window.addEventListener('unload', preventNavigation, false);
})();

Zastrzeżenie: Nigdy nie powinieneś tego robić. Jeśli strona zawiera kod niszczący ramki, uszanuj życzenia autora.

anarchocantyczny
źródło
jak pokazać modalne, jeśli użytkownik chce zamknąć przeglądarkę (kliknij zamknij)? to naprawdę?
15

Skończyło się na tej nieco innej wersji:

var dirty = false;
window.onbeforeunload = function() {
    return dirty ? "If you leave this page you will lose your unsaved changes." : null;
}

W innym miejscu ustawiam flagę dirty na true, gdy formularz jest zanieczyszczony (lub w inny sposób chcę uniemożliwić nawigację). Dzięki temu mogę łatwo kontrolować, czy użytkownik otrzyma monit Potwierdź nawigację.

Wraz z tekstem w wybranej odpowiedzi zobaczysz zbędne monity:

wprowadź opis obrazu tutaj

Zagrożenie
źródło
3
W IE, jeśli dirty jest fałszywy, zostanie wyświetlony łańcuch „null”. Po prostu zawiń go w oświadczenie if. Zobacz: stackoverflow.com/questions/11793996/…
Jacob van Lingen
Zgoda @JacobvanLingen, byłaby to najlepsza odpowiedź tutaj i na trzy inne pytania, gdyby kończyła się na undefinedzamiast zerowej. (1) jest warunkowa (2) wymienia „brudny”, najczęstszy uzasadniony powód utrudniania nawigacji i (3) ma zrzut ekranu.
Bob Stein
Czy to zadziała we wszystkich przeglądarkach, jeśli zakończy się z ciągiem undefined, a nie null?
Niebezpieczeństwo
9

Odpowiednik w bardziej nowoczesny i zgodny z przeglądarkami sposób, przy użyciu nowoczesnych interfejsów API addEventListener.

window.addEventListener('beforeunload', (event) => {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '';
});

Źródło: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

Paul Weber
źródło
1
Pamiętaj, aby poprawnie wykorzystać event.returnValue
wielkie
7

W przykładzie Aymana zwracając wartość false, zapobiegasz zamknięciu okna / karty przeglądarki.

window.onunload = function () {
  alert('You are trying to leave.');
  return false;
}
gabor
źródło
2
Chyba że przeglądarką jest Opera, która pomija zdarzenie onunload, jeśli karta / okno / program jest zamykana.
Powerlord
5

Odpowiednik zaakceptowanej odpowiedzi w jQuery 1.11:

$(window).on("beforeunload", function () {
    return "Please don't leave me!";
});

Przykład JSFiddle

Odpowiedź altCognito wykorzystała unloadzdarzenie, które następuje za późno, aby JavaScript przerwał nawigację.

BoffinBrain
źródło
3

Użyj onunload .

Myślę, że w przypadku jQuery działa to tak:

$(window).unload(function() { 
  alert("Unloading"); 
  return falseIfYouWantToButBeCareful();
});
cgp
źródło
Zwrócenie wartości false niestety nie anuluje wyładowania - unloadzdarzenie uruchamia się, gdy użytkownik opuszcza stronę, w przeciwieństwie do tego, beforeunloadktóre uruchamia się tuż przed (i może zostać anulowane)
Jimbo
@altCognito: Dałeś mi dobry pomysł z falseIfYouWantToButBeCareful () Teraz mogę uniknąć domyślnego wyskakującego okienka podawanego przez IE lub FF. Ale dla chromu to nie działa. Patrząc w to.
user367134
3

Ten sugerowany komunikat o błędzie może powielić komunikat o błędzie, który jest już wyświetlany w przeglądarce. W chrome, 2 podobne komunikaty o błędach są wyświetlane jeden po drugim w tym samym oknie.

W chrome tekst wyświetlany po niestandardowej wiadomości to: „Czy na pewno chcesz opuścić tę stronę?”. W przeglądarce Firefox w ogóle nie wyświetla naszego niestandardowego komunikatu o błędzie (ale nadal wyświetla okno dialogowe).

Bardziej odpowiednim komunikatem o błędzie może być:

window.onbeforeunload = function() {
    return "If you leave this page, you will lose any unsaved changes.";
}

Lub styl stackoverflow: „Zacząłeś pisać lub edytować post”.

Curtis Yallop
źródło
2

Jeśli łapiesz przycisk wstecz / dalej w przeglądarce i nie chcesz opuszczać przeglądarki, możesz użyć:

window.addEventListener('popstate', function() {
    if (window.location.origin !== 'http://example.com') {
        // Do something if not your domain
    } else if (window.location.href === 'http://example.com/sign-in/step-1') {
        window.history.go(2); // Skip the already-signed-in pages if the forward button was clicked
    } else if (window.location.href === 'http://example.com/sign-in/step-2') {
        window.history.go(-2); // Skip the already-signed-in pages if the back button was clicked
    } else {
        // Let it do its thing
    }
});

W przeciwnym razie możesz użyć zdarzenia beforeunload , ale komunikat może, ale nie musi, działać w różnych przeglądarkach i wymaga zwrócenia czegoś, co wymusza wbudowany monit.

nieco mniej
źródło