Sayfadan çıkış etkinliğini durdur


117

Sistemimdeki bir sayfayı düzenlerken, bir kullanıcı başka bir web sitesine gitmeye karar verebilir ve bunu yaparken kaydetmediği tüm düzenlemeleri kaybedebilir.

Başka bir sayfaya gitme girişimlerini durdurmak ve mevcut çalışmalarını kaybedebilecekleri için kullanıcıdan bunun olmasını istediğinden emin olmasını isterim.

Gmail bunu çok benzer bir şekilde yapar. Örneğin, yeni bir e-posta oluşturun, mesaj gövdesine yazmaya başlayın ve adres çubuğuna yeni bir konum girin (örneğin twitter.com veya başka bir şey). "Emin misiniz?"

Bunun nasıl çoğaltılacağına dair fikirler? IE8'i hedefliyorum, ancak FF ve Chrome ile de uyumlu olmak istiyorum.


Yanıtlar:


154

Ghommey'in cevabına benzer, ancak bu aynı zamanda IE ve Firefox'un eski sürümlerini de destekler.

window.onbeforeunload = function (e) {
  var message = "Your confirmation message goes here.",
  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = message;
  }

  // For Safari
  return message;
};

1
İlk satırı açıklayabilir misiniz (var message = ...)? Bu virgül ve ikinci ifadenin ne yaptığını bilmiyorum.
mtmurdock

7
@mtmurdock Bu, birden çok değişkeni bildirmek için yalnızca Javascript sözdizimi. var foo, bar;ile aynıvar foo; var bar;
T Nguyen

4
@mtmurdock, İkinci ifade " var e = e || window.event;" vasıtalar ayarlanır E parametresi eşit e (eğer en truthy) ya da window.event değilse truthy. E parametresinin boş olması doğru olmayacaktır .
T Nguyen

3
@Blieque addEventListener IE8'de desteklenmiyor. Soruyu bile okumadan insanların cevaplarını düzenlemeyin.
Eli Gray

2
Artık Chrome'da çalışmıyor (kullanımdan kaldırıldı): developers.google.com/web/updates/2016/04/…
Micha Schwab

25

Bu makaleye bakın. Aradığınız özellik unbeforeunload

basit kod:

  <script language="JavaScript">
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  }
</script>

2
Bu kullanıcının "Bu sayfada kal" yerine "Bu sayfadan ayrıl" seçeneğini seçtiğini belirlemenin bir yolu var mı?
Shilpa Soni

@ShilpaSoni, kısa bir süre sonra bir boşaltma etkinliği alırsınız, developer.mozilla.org/en-US/docs/Web/API/Window/unload_event, ancak senkronize bir yol olduğunu düşünmüyorum.
scipilot

6

Sinir bozucu bir onay açılır penceresi yerine , kaydedilmemiş verileri sunucuya başarıyla göndermeyi yönetmek için sadece biraz (milisaniye) bırakmayı geciktirmek güzel olurdu, bunu sitem için konsola kukla metin yazarak yönettim:

window.onbeforeunload=function(e){
  // only take action (iterate) if my SCHEDULED_REQUEST object contains data        
  for (var key in SCHEDULED_REQUEST){   
    postRequest(SCHEDULED_REQUEST); // post and empty SCHEDULED_REQUEST object
    for (var i=0;i<1000;i++){
      // do something unnoticable but time consuming like writing a lot to console
      console.log('buying some time to finish saving data'); 
    };
    break;
  };
}; // no return string --> user will leave as normal but data is send to server

Düzenleme: Ayrıca bkz. Synchronous_AJAX ve bunun jquery ile nasıl yapılacağı


Pop-up'a bu alternatifi beğendim. Önerin için teşekkürler Remi.
Chris Ballance

2
bu kesinlikle hiç mantıklı değil -1. javascript iş parçacığı değildir, yaptığınız şey bir postRequest yapmak ve sonra sitenin hesaplamasını kimsenin hiçbir şey yapmasına izin vermeden duraklatmaktır (bu arada, hesaplama duraklamasından önce gönderilmiş olan postRequest dahil).
fmsf

Ve işte tam da bu yüzden işe yarıyor: gerçekten de istek sonrası, hesaplama duraklamasından önce gönderilmişti, ancak sayfanın kalmadan önce bu küçük engellenmesi, tarayıcı istemcisinin (javascript değil) bu isteği doğru bir şekilde göndermesini gerçekten bitirmesi için yeterli zaman sağlıyor. . Sadece isteği gönderdiğimde (engellemeden) ve hemen ardından sayfadan ayrıldığımda, isteğin her zaman gönderilmediğini fark ettim.
Remi

6
Bunu üretimde kullanmazdım. console.log çapraz tarayıcı değildir; her postRequest, öncekilerin gecikmesinden muzdariptir (bu aynı zamanda sayfanın, döngü * planlanmış istekleriniz süresince orada asılı kalacağı anlamına gelir); istekler paralel olarak başlatılmaz; isteklerinizi gerçekten göndermeniz garanti edilmez. Bu sorunla yüzleşmek zorunda kalsaydım, tek bir istek varsa, senkronize bir ajax isteğiyle giderdim. Birden çok istekle, eşzamansız ajax istekleri ve isteklerin geri aramalarından sonuçları (başarı veya hata) kontrol eden bir döngü kullanırdım.
framp

Console.log'un çapraz tarayıcı olmadığını ve Senkronize Ajax isteğinin gerçekten tercih edilen çözüm olması gerektiğini bilmiyordum (tek bir istek için). Bahsedilen SCHEDULED_REQUEST, bir veri tamponu gibi sunucuya gönderilmesi gereken acil olmayan bilgileri biriktiren, birden çok isteği etkin bir şekilde birleştiren bir nesnedir (elbette bu isteklerin url'si aynıdır). Kaldırmadan önce Senkronize Ajax isteği kullanmak, söylediğiniz gibi tarayıcılar arası sorunu çözmelidir. Değerli yorumunuz için teşekkürler!
Remi

0

Gerekli tüm verileri tamamlamamış kullanıcılarım var.

<cfset unloadCheck=0>//a ColdFusion precheck in my page generation to see if unload check is needed
var erMsg="";
$(document).ready(function(){
<cfif q.myData eq "">
    <cfset unloadCheck=1>
    $("#myInput").change(function(){
        verify(); //function elsewhere that checks all fields and populates erMsg with error messages for any fail(s)
        if(erMsg=="") window.onbeforeunload = null; //all OK so let them pass
        else window.onbeforeunload = confirmExit(); //borrowed from Jantimon above;
    });
});
<cfif unloadCheck><!--- if any are outstanding, set the error message and the unload alert --->
    verify();
    window.onbeforeunload = confirmExit;
    function confirmExit() {return "Data is incomplete for this Case:"+erMsg;}
</cfif>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.