Jak wyświetlić „Czy na pewno chcesz opuścić tę stronę?” kiedy dokonano zmian?

267

Tutaj, w Stackoverflow, jeśli zacząłeś wprowadzać zmiany, to próbujesz opuścić stronę, pojawia się przycisk potwierdzenia javascript i pyta: „Czy na pewno chcesz opuścić tę stronę?” blee bla bloo ...

Czy ktoś już to zaimplementował, jak mogę śledzić, czy zmiany zostały popełnione? Wierzę, że mógłbym to zrobić sam, staram się nauczyć dobrych praktyk od was, ekspertów.

Próbowałem następujące, ale nadal nie działa:

<html>
<body>
    <p>Close the page to trigger the onunload event.</p>
    <script type="text/javascript">
        var changes = false;        
        window.onbeforeunload = function() {
            if (changes)
            {
                var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
                if (confirm(message)) return true;
                else return false;
            }
        }
    </script>

    <input type='text' onchange='changes=true;'> </input>
</body>
</html>

Czy ktoś może opublikować przykład?

Shimmy Weitzhandler
źródło
3
Aby twój przykład działał, zmień funkcję na: myFunction () {window.onbeforeunload = "message"; } następnie zmień dane wejściowe: <input type = 'text' onchange = 'myFunction ();'> </input>
Keith
Powiązane: stackoverflow.com/q/821011/435605
AlikElzin-kilaka

Odpowiedzi:

367

Aktualizacja (2017)

Współczesne przeglądarki rozważają teraz wyświetlanie niestandardowego komunikatu jako zagrożenia bezpieczeństwa, dlatego został on usunięty ze wszystkich. Przeglądarki wyświetlają teraz tylko ogólne wiadomości. Ponieważ nie musimy się już martwić ustawieniem wiadomości, jest to tak proste, jak:

// Enable navigation prompt
window.onbeforeunload = function() {
    return true;
};
// Remove navigation prompt
window.onbeforeunload = null;

Przeczytaj poniżej, aby zapoznać się ze starszą obsługą przeglądarek.

Aktualizacja (2013)

Oryginalna odpowiedź jest odpowiednia dla IE6-8 i FX1-3.5 (na co celowaliśmy w 2009 roku, kiedy została napisana), ale jest raczej nieaktualna i nie będzie działać w większości obecnych przeglądarek - wyszedłem poniżej w celach informacyjnych.

Nie window.onbeforeunloadjest traktowane konsekwentnie przez wszystkie przeglądarki. Powinno to być odwołanie do funkcji, a nie ciąg znaków (jak podano w pierwotnej odpowiedzi), ale zadziała to w starszych przeglądarkach, ponieważ wydaje się, że większość z nich sprawdza, czy coś jest przypisane onbeforeunload(w tym funkcja, która zwraca null).

Ustawiono window.onbeforeunloadodwołanie do funkcji, ale w starszych przeglądarkach należy ustawić returnValuezdarzenie zamiast po prostu zwracać ciąg:

var confirmOnPageExit = function (e) 
{
    // If we haven't been passed the event get the window.event
    e = e || window.event;

    var message = 'Any text will block the navigation and display a prompt';

    // For IE6-8 and Firefox prior to version 4
    if (e) 
    {
        e.returnValue = message;
    }

    // For Chrome, Safari, IE8+ and Opera 12+
    return message;
};

Nie możesz tego confirmOnPageExitzrobić i sprawdzić zero, jeśli chcesz, aby użytkownik kontynuował bez wiadomości. Nadal musisz usunąć zdarzenie, aby niezawodnie włączyć i wyłączyć:

// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;

// Turn it off - remove the function entirely
window.onbeforeunload = null;

Oryginalna odpowiedź (opracowana w 2009 r.)

Żeby to włączyć:

window.onbeforeunload = "Are you sure you want to leave?";

Aby to wyłączyć:

window.onbeforeunload = null;

Pamiętaj, że to nie jest normalne wydarzenie - nie możesz się z nim związać w standardowy sposób.

Aby sprawdzić wartości? To zależy od twoich ram weryfikacji.

W jQuery może to być coś (bardzo prosty przykład):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});
Keith
źródło
4
To byłoby coś w stylu: $ ('input: text'). Change (function () {window.onbeforeunload = $ ('input: text [value! = ""]'). Length> 0? "Warning": null ;});
Keith,
1
Dla prostego sprawdzenia lub możesz dodać bardziej złożone sprawdzanie poprawności przy każdej zmianie
Keith,
1
warto zauważyć, że metoda „returnValue” jest jedyną metodą określoną w standardzie, więc nie dotyczy tylko IE6-8, ale wszystkich przeglądarek zgodnych ze standardami (w tym przypadku nie obejmuje Chrome, Safari i Opery).
rmcclellan
3
Użyłem, aby zatrzymać alert przy przesyłaniu formularza $("#submit_button").click(function() { window.onbeforeunload = null; });. Pierwotnie użyłem zdarzenia onclick przycisku, ale oprócz tego, że nie jest tak fajny, to również nie działało z IE8.
Andy Beverley
1
@ AlikElzin-kilaka nie możesz. Jeśli chcesz zmienić wyskakujący tekst, musisz utworzyć własne niestandardowe wyskakujące okienko, ale to nie może zablokować window.onbeforeunloadzdarzenia.
Keith
38

onbeforeunloadMicrosoft-izm jest najbliższa rzecz mamy do standardowego rozwiązania, ale należy pamiętać, że wsparcie przeglądarka jest nierówna; np. dla Opery działa tylko w wersji 12 i późniejszych (wciąż w wersji beta od tego pisania).

Ponadto, aby uzyskać maksymalną zgodność , musisz zrobić coś więcej niż po prostu zwrócić ciąg znaków, jak wyjaśniono w sieci Mozilla Developer Network .

Przykład: Zdefiniuj następujące dwie funkcje włączania / wyłączania monitu nawigacyjnego (patrz przykład MDN):

function enableBeforeUnload() {
    window.onbeforeunload = function (e) {
        return "Discard changes?";
    };
}
function disableBeforeUnload() {
    window.onbeforeunload = null;
}

Następnie zdefiniuj taki formularz:

<form method="POST" action="" onsubmit="disableBeforeUnload();">
    <textarea name="text"
              onchange="enableBeforeUnload();"
              onkeyup="enableBeforeUnload();">
    </textarea>
    <button type="submit">Save</button>
</form>

W ten sposób użytkownik zostanie ostrzeżony o odejściu tylko wtedy, gdy zmienił pole tekstowe, i nie będzie monitowany, gdy faktycznie prześle formularz.

Søren Løvborg
źródło
1
W oparciu o witrynę Mozill, najnowsze przeglądarki pulpitu obsługują teraz: developer.mozilla.org/en/DOM/window.onbeforeunload
Hengjie
Microsoft-ism to świetny termin.
Luke Taylor
18

Z JQuery jest to całkiem łatwe. Ponieważ możesz powiązać z zestawami.

Nie wystarczy wykonać onbeforeunload, chcesz uruchomić nawigację tylko wtedy, gdy ktoś zaczął edytować rzeczy.

Sam Saffron
źródło
2
Wydaje się, że nie można trafić na posty na blogu @jonstjohn. Może będzie kumplem i skieruje nas w dobrym kierunku? : D
FLGMwt
14
=> 500 Błąd wewnętrzny. Dlatego linki są przestarzałe w SO. Doceniony, dopóki nie zostanie naprawiony.
Loïc
Ta strona jest niedostępna
Mateusz
2
Chociaż ten link może odpowiedzieć na pytanie, lepiej jest dołączyć tutaj istotne części odpowiedzi i podać link w celach informacyjnych. Odpowiedzi zawierające tylko łącze mogą stać się nieprawidłowe, jeśli połączona strona ulegnie zmianie.
bwest
2
Oryginalny link z Jonem St John został złamany, więc zaktualizowałem go do Wayback Maszyna wersję. Treść linku można znaleźć na wielu innych stronach, ale myślę, że lepiej było „zachować” ten dodany przez Sama
Alvaro Montoro
14

jquerys 'beforeunload' działał dla mnie świetnie

$(window).bind('beforeunload', function(){
    if( $('input').val() !== '' ){
        return "It looks like you have input you haven't submitted."
    }
});
Devon Peticolas
źródło
Powiązanie zostało wycofane, a nowszą wersję kodu podobnego do tego można zobaczyć w tej odpowiedzi: stackoverflow.com/a/1889450/908677
Elijah Lofgren
12

dla nowych ludzi, którzy szukają prostego rozwiązania, po prostu wypróbuj Areyousure.js

lawphotog
źródło
11

Jest to łatwy sposób na przedstawienie wiadomości, jeśli do formularza zostaną wprowadzone jakieś dane, i nie wyświetlenie wiadomości, jeśli formularz zostanie przesłany:

$(function () {
    $("input, textarea, select").on("input change", function() {
        window.onbeforeunload = window.onbeforeunload || function (e) {
            return "You have unsaved changes.  Do you want to leave this page and lose your changes?";
        };
    });
    $("form").on("submit", function() {
        window.onbeforeunload = null;
    });
})
Carl G.
źródło
8

Aby rozwinąć i tak już niesamowitą odpowiedź Keitha :

Niestandardowe komunikaty ostrzegawcze

Aby zezwolić na niestandardowe komunikaty ostrzegawcze, możesz zawinąć je w funkcję taką jak ta:

function preventNavigation(message) {
    var confirmOnPageExit = function (e) {
        // If we haven't been passed the event get the window.event
        e = e || window.event;

        // For IE6-8 and Firefox prior to version 4
        if (e)
        {
            e.returnValue = message;
        }

        // For Chrome, Safari, IE8+ and Opera 12+
        return message;
    };
    window.onbeforeunload = confirmOnPageExit;
}

Następnie wywołaj tę funkcję z niestandardowym komunikatem:

preventNavigation("Baby, please don't go!!!");

Włączam ponownie nawigację

Aby ponownie włączyć nawigację, wszystko co musisz zrobić, to ustawić window.onbeforeunloadsię null. Oto jest zawinięty w schludną małą funkcję, którą można wywołać w dowolnym miejscu:

function enableNavigation() {
    window.onbeforeunload = null;
}

Użycie jQuery do powiązania tego w celu utworzenia elementów

Jeśli używasz jQuery, można to łatwo powiązać ze wszystkimi elementami formularza takiego jak ten:

$("#yourForm :input").change(function() {
    preventNavigation("You have not saved the form. Any \
        changes will be lost if you leave this page.");
});

Następnie, aby umożliwić przesłanie formularza:

$("#yourForm").on("submit", function(event) {
    enableNavigation();
});

Dynamicznie modyfikowane formularze:

preventNavigation()i enableNavigation()może być powiązany z dowolnymi innymi funkcjami, takimi jak dynamiczne modyfikowanie formularza lub klikanie przycisku wysyłającego żądanie AJAX. Zrobiłem to, dodając do formularza ukryty element wejściowy:

<input id="dummy_input" type="hidden" />

Następnie za każdym razem, gdy chcę uniemożliwić użytkownikowi nawigację, uruchamiam zmianę na tym wejściu, aby mieć pewność, że preventNavigation()zostanie wykonany:

function somethingThatModifiesAFormDynamically() {

    // Do something that modifies a form

    // ...
    $("#dummy_input").trigger("change");
    // ...
}
Mikrofon
źródło
3

Tutaj wypróbuj to działa w 100%

<html>
<body>
<script>
var warning = true;
window.onbeforeunload = function() {  
  if (warning) {  
    return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";  
    }  
}

$('form').submit(function() {
   window.onbeforeunload = null;
});
</script>
</body>
</html>
Braydon
źródło
3

Te standardowe stwierdza , że skłoniło mogą być kontrolowane poprzez anulowanie beforeunload zdarzenie lub ustawienie wartości zwracanej do wartości innej niż NULL . Stwierdza również, że autorzy powinni użyć Event.preventDefault () zamiast returnValue, a komunikatu wyświetlanego użytkownikowi nie można dostosowywać .

Od 69.0.3497.92 Chrome nie spełnia normy. Jednak zgłoszono zgłoszenie błędu i recenzję trwa . Chrome wymaga ustawienia returnValue przez odwołanie do obiektu zdarzenia, a nie wartości zwracanej przez moduł obsługi.

Obowiązkiem autora jest sprawdzenie, czy dokonano zmian; można tego dokonać za pomocą zmiennej lub upewniając się, że zdarzenie jest obsługiwane tylko wtedy, gdy jest to konieczne.

window.addEventListener('beforeunload', function (e) {
    // Cancel the event as stated by the standard.
    e.preventDefault();
    // Chrome requires returnValue to be set.
    e.returnValue = '';
});
    
window.location = 'about:blank';

Trevor Karjanis
źródło
2

Kiedy użytkownik zacznie wprowadzać zmiany w formularzu, zostanie ustawiona flaga logiczna. Jeśli użytkownik następnie spróbuje opuścić stronę, zaznacz tę flagę w oknie. Załaduj zdarzeniu . Jeśli flaga jest ustawiona, wyświetlasz komunikat, zwracając go jako ciąg. Zwrócenie wiadomości jako ciągu spowoduje wyświetlenie okna dialogowego potwierdzenia zawierającego wiadomość.

Jeśli używasz ajax do zatwierdzania zmian, możesz ustawić flagę na falsepo zatwierdzeniu zmian (tj. W zdarzeniu powodzenia ajax).

Kirtan
źródło
1

Możesz dodać onchangezdarzenie w polu tekstowym (lub dowolnym innym polu), które ustawia zmienną w JS. Gdy użytkownik próbuje zamknąć stronę (window.onunload), sprawdzasz wartość tej zmiennej i odpowiednio wyświetlasz alert.

Makram Saleh
źródło
1
Nie możesz tego zrobić - alerti confirmsą blokowane podczas window.onbeforeunloadi window.onunload(przynajmniej w wersji Chrome na moim komputerze, ale prawdopodobnie także w każdej przeglądarce, aby kiedykolwiek obsługiwać te programy obsługi).
Mark Amery
1

Na podstawie wszystkich odpowiedzi w tym wątku napisałem następujący kod i zadziałał on dla mnie.

Jeśli masz tylko niektóre tagi wejściowe / tekstowe, które wymagają sprawdzenia zdarzenia onunload, możesz przypisać atrybuty danych HTML5 jako data-onunload="true"

na przykład

<input type="text" data-onunload="true" />
<textarea data-onunload="true"></textarea>

i JavaScript (jQuery) może wyglądać następująco:

$(document).ready(function(){
    window.onbeforeunload = function(e) {
        var returnFlag = false;
        $('textarea, input').each(function(){
            if($(this).attr('data-onunload') == 'true' && $(this).val() != '')
                returnFlag = true;
        });

        if(returnFlag)
            return "Sure you want to leave?";   
    };
});
Gala Sagar
źródło
2
Zobacz także „Z niektórych powodów przeglądarki oparte na Webkit nie są zgodne ze specyfikacją okna dialogowego” w dokumentacji MDN przed uruchomieniem ładowania .
Arjan
1

oto mój html

<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>

 <body onload="myFunction()">
    <h1 id="belong">
        Welcome To My Home
    </h1>
    <p>
        <a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
    </p>
</body>

I w ten sposób zrobiłem coś podobnego w javaScript

var myGlobalNameHolder ="";

function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
    myGlobalNameHolder = myString;
    if (myString != null) {
        document.getElementById("replaceME").innerHTML =
        "Hello " + myString + ". Welcome to my site";

        document.getElementById("belong").innerHTML =
        "A place you belong";
    }   
}

// create a function to pass our event too
function myFunction2(event) {   
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
    x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}
Justin Stone
źródło
0

Można to łatwo zrobić poprzez ustawienie ChangeFlag true, na onChange przypadku TextArea . Użyj javascript, aby wyświetlić okno dialogowe potwierdzenia na podstawie wartości ChangeFlag . Odrzuć formularz i przejdź do żądanej strony, jeśli potwierdzenie zwraca true, w przeciwnym razie nic nie rób .

po prostu trudne
źródło
-1

Dla znacznika body istnieje parametr „onunload”, z którego można wywoływać funkcje javascript. Jeśli zwróci fałsz, uniemożliwi nawigację.

stribika
źródło
13
Na szczęście to nie działa. W przeciwnym razie nie chciałbym odwiedzać strony zawierającej <body onunload="return false;">.
Søren Løvborg