jquery beforeunload podczas zamykania (nie opuszczania) strony?

83

Jak wyświetlić komunikat „Czy na pewno chcesz opuścić tę stronę?” gdy użytkownik faktycznie próbuje zamknąć stronę (kliknij przycisk X w oknie lub karcie przeglądarki), a nie gdy próbuje opuścić stronę (kliknij inny link).

Mój klient chce, aby pojawił się komunikat, gdy użytkownik spróbuje zamknąć stronę „Czy na pewno chcesz opuścić tę stronę? W koszyku nadal znajdują się produkty”.

Niestety $(window).bind('beforeunload')nie uruchamia się tylko wtedy, gdy użytkownik zamyka stronę.

jQuery:

function checkCart() { 
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        $(window).bind('beforeunload', function(){
          return 'leave?';
        });
       }
    }
  })
}
Kryzys
źródło
1
Nie możesz. Nie możesz programowo odróżnić zamknięcia przeglądarki lub opuszczenia strony przez użytkownika.
meagar
@Cris Whats wystąpił błąd?
Padmanathan J
Twoja wiadomość zawiera kod wskazujący na uruchomioną operację Ajax. Czy jest kilka z nich, które musimy wziąć pod uwagę? (ponieważ poza tym kodem, nie wspomniałeś o tym wyraźnie)
Cyril N.,
nie możesz stwierdzić, czy okno jest zamknięte lub przejść do innego adresu URL, weź pod uwagę, gdy używasz przeglądarki z wieloma kartami, nie ma różnicy, ale jeśli używasz nawigacji hash (np. twoja_domena.com/#path=/index / news & id = 1 ), możesz nim zarządzać, wrzucać javascript podczas nawigacji
alphakevin

Odpowiedzi:

145

Możesz to zrobić za pomocą JQuery .

Na przykład ,

<a href="your URL" id="navigate"> click here </a>

Twoja JQuerywola,

$(document).ready(function(){

    $('a').on('mousedown', stopNavigate);

    $('a').on('mouseleave', function () {
           $(window).on('beforeunload', function(){
                  return 'Are you sure you want to leave?';
           });
    });
});

function stopNavigate(){    
    $(window).off('beforeunload');
}

Aby otrzymać powiadomienie o opuszczeniu ,

$(window).on('beforeunload', function(){
      return 'Are you sure you want to leave?';
});

$(window).on('unload', function(){

         logout();

});

To rozwiązanie działa we wszystkich przeglądarkach i przetestowałem je.

Istota ludzka
źródło
2
Jest to dobre rozwiązanie (prawdopodobnie też powinieneś obserwować onsubmit), ale nie będzie działać w przypadku przycisków przeglądarki Wstecz i Dalej. Przewiduję, że nie ma na to idealnego rozwiązania.
noseratio
kod jest w porządku. Chcę uruchomić funkcję logout (), jeśli użytkownik kliknie przycisk „Opuść tę stronę”. Ale jak mogę sprawdzić, czy użytkownik kliknął „Opuść tę stronę”, czy nie?
Bit_hunter
1
To $(window).on('unload', function()nie jest wykonywane w Safari.
Aarohi Kulkarni
1
Zapali się, beforeunloadjeśli przeglądarka zamyka się z powodu zamknięcia systemu operacyjnego?
techie_28
4
Nie możesz już dostarczać niestandardowych wiadomości w Chrome lub Firefox (ponieważ chcą zapobiec oszustwom): developers.google.com/web/updates/2016/04/…
Adam
12

Wypróbuj JavaScript w swoim Ajax

window.onbeforeunload = function(){
  return 'Are you sure you want to leave?';
};

Link referencyjny

Przykład 2:

document.getElementsByClassName('eStore_buy_now_button')[0].onclick = function(){
    window.btn_clicked = true;
};
window.onbeforeunload = function(){
    if(!window.btn_clicked){
        return 'You must click "Buy Now" to make payment and finish your order. If you leave now your order will be canceled.';
    }
};

Tutaj będzie ostrzegać użytkownika za każdym razem, gdy opuszcza stronę, dopóki nie kliknie przycisku.

DEMO: http://jsfiddle.net/DerekL/GSWbB/show/

Padmanathan J
źródło
12

Kredyt powinien znaleźć się tutaj: jak wykryć, czy link został kliknięty po uruchomieniu window.onbeforeunload?

Zasadniczo rozwiązanie dodaje detektor, który wykrywa, czy łącze lub okno spowodowało uruchomienie zdarzenia unload.

var link_was_clicked = false;
document.addEventListener("click", function(e) {
   if (e.target.nodeName.toLowerCase() === 'a') {
      link_was_clicked = true;
   }
}, true);

window.onbeforeunload = function(e) {
    if(link_was_clicked) {
        return;
    }
    return confirm('Are you sure?');
}
Andy Merhaut
źródło
2

Jak wskazano tutaj https://stackoverflow.com/a/1632004/330867 , możesz to zaimplementować poprzez „filtrowanie” tego, co powoduje wyjście z tej strony.

Jak wspomniano w komentarzach, oto nowa wersja kodu w drugim pytaniu, która obejmuje również żądanie AJAX, które złożyłeś w swoim pytaniu:

var canExit = true;

// For every function that will call an ajax query, you need to set the var "canExit" to false, then set it to false once the ajax is finished.

function checkCart() {
  canExit = false;
  $.ajax({
    url : 'index.php?route=module/cart/check',
    type : 'POST',
    dataType : 'json',
    success : function (result) {
       if (result) {
        canExit = true;
       }
    }
  })
}

$(document).on('click', 'a', function() {canExit = true;}); // can exit if it's a link
$(window).on('beforeunload', function() {
    if (canExit) return null; // null will allow exit without a question
    // Else, just return the message you want to display
    return "Do you really want to close?";
});

Ważne : Nie powinieneś mieć zdefiniowanej zmiennej globalnej (tutaj canExit), to jest tutaj dla prostszej wersji.

Zauważ, że nie możesz całkowicie zastąpić wiadomości potwierdzającej (przynajmniej w Chrome). Wiadomość, którą zwrócisz, zostanie dołączona tylko do wiadomości podanej przez Chrome. Oto powód: Jak mogę zastąpić okno dialogowe OnBeforeUnload i zastąpić je własnym?

Cyryl N.
źródło
3
Od jQuery 1.7 .livejest przestarzałe. Zamiast tego $(document).on('click', 'a', ...) należy użyć. .onjest ogólnie preferowanym sposobem w stosunku do starych funkcji, więc tak .bindby było $('form').on('submit', ...).
t.niese
Jestem pewien, że ta odpowiedź to koniec z przeglądarkami. Ktoś to przetestował?
A. Wolff
Jak wspomniano, tylko skopiowałem / wkleiłem kod. Zmienię odpowiedź w najnowszej wersji
Cyril N.
Dziękuję, ale niestety potwierdzenie nie pojawia się po zamknięciu karty.
Cris,
.. i duży błąd, który popełniłem (kliknij zamiast beforeunload jako zdarzenie dokumentu).
Cyril N.
-1

Spróbuj tego, ładując dane za pomocą ajaxi wyświetlając za pomocą instrukcji return.

<script type="text/javascript">
function closeWindow(){

    var Data = $.ajax({
        type : "POST",
        url : "file.txt",  //loading a simple text file for sample.
        cache : false,
        global : false,
        async : false,
        success : function(data) {
            return data;
        }

    }).responseText;


    return "Are you sure you want to leave the page? You still have "+Data+" items in your shopping cart";
}

window.onbeforeunload = closeWindow;
</script>
raduns
źródło
1
Nie jest dobrym pomysłem zmuszanie użytkownika do czekania na odpowiedź synchronicznego połączenia AJAX za każdym razem, gdy kliknie łącze w Twojej witrynie.
mattalxndr