OnBeforeUnload iletişim kutusunu nasıl geçersiz kılabilir ve kendim ile nasıl değiştirebilirim?


347

Bir sayfadan ayrılmadan önce kullanıcıları kaydedilmemiş değişiklikler konusunda uyarmam gerekiyor (oldukça yaygın bir sorun).

window.onbeforeunload=handler

Bu çalışır, ancak kendi metnimi saran rahatsız edici standart bir mesajla varsayılan bir iletişim kutusu oluşturur. Ben tamamen standart mesajı değiştirmek gerekir, bu yüzden benim metin açık, ya da (daha iyi) jQuery kullanarak kalıcı bir iletişim kutusu ile tüm iletişim yerine.

Şimdiye kadar başarısız oldum ve cevabı olan başka birini bulamadım. Hatta mümkün mü?

Sayfamdaki Javascript:

<script type="text/javascript">   
   window.onbeforeunload=closeIt;
</script>

CloseIt () işlevi:

function closeIt()
{
  if (changes == "true" || files == "true")
  {
      return "Here you can append a custom message to the default dialog.";
  }
}

JQuery ve jqModal kullanarak (özel bir onay iletişim kutusunu kullanarak) bu tür bir şey denedim:

$(window).beforeunload(function() {
        confirm('new message: ' + this.href + ' !', this.href);
        return false;
    });

ki bu da işe yaramıyor - yük öncesi olayına bağlanamıyorum.


1
Mevcut kodunuza ve bu kodun ne ürettiğine bir örnek verebilir misiniz?
Owen

Owen doğru. Ve bunun sebebi güvenlik. Bir sayfanın kaldırılmasını önlemek, web formlarında ve benzeri durumlarda yararlıdır, ancak kullanıcıyı bir sayfada kalmaya kandırmak için kötü niyetli bir site tarafından kolayca kullanılabilir. Bu nedenle web tarayıcıları standart mesajı uygular ve özel metin eklemek için bu mekanizmaya sahiptir.
pluckyglen

daha fazla bilgi için buraya bakın: stackoverflow.com/questions/140460
Ben McIntyre


1
kromda

Yanıtlar:


301

İçin varsayılan diyalogu değiştiremezsiniz onbeforeunload, bu nedenle en iyi bahsiniz onunla çalışmak olabilir.

window.onbeforeunload = function() {
    return 'You have unsaved changes!';
}

İşte Microsoft'tan buna bir referans :

Window.event öğesinin returnValue özelliğine bir dize atandığında, kullanıcılara geçerli sayfada kalma ve kendisine atanan dizeyi tutma seçeneği sunan bir iletişim kutusu görüntülenir. "Bu sayfadan uzaklaşmak istediğinizden emin misiniz? ... iletişim kutusunda görüntülenen varsayılan ifade, devam etmek için Tamam'a veya geçerli sayfada kalmak için İptal'e basın." Kaldırılamaz veya değiştirilemez.

Sorun şu şekilde gözüküyor:

  1. Arandığında onbeforeunload, işleyicinin dönüş değerini olarak alacaktır window.event.returnValue.
  2. Daha sonra döndürülen değeri bir dize olarak ayrıştırır (boş değilse).
  3. Yana falsebir dize olarak ayrıştırılır, diyalog kutusu uygun geçecek olan ateş alır true/ false.

Sonuç, atama bir yol olarak görünmüyor olduğu falseiçin onbeforeunloadvarsayılan diyalog engellemek için.

JQuery hakkında ek notlar:

  • Olayı jQuery'de ayarlamak sorunlu olabilir , çünkü diğer onbeforeunloadolaylar da gerçekleşebilir. Yalnızca unload etkinliğinizin gerçekleşmesini istiyorsanız bunun için düz ol JavaScript'e bağlı kalacağım.
  • jQuery için bir kısayol yoktur, onbeforeunloadbu nedenle genel bindsözdizimini kullanmanız gerekir .

    $(window).bind('beforeunload', function() {} );

Edit 09/04/2018 : Yüksüz iletişim kutularındaki özel mesajlar, krom-51'den beri kullanımdan kaldırıldı (cf: sürüm notu )


20
Sonunda verilen JQuery örneğinin firefox'ta çalışmamasını buldum. Bunun yerine basit bir şekilde sadık kalın: window.onbeforeunload = function () {...}
jb.

21
Firefox'un yakın zamanda değiştirildiği ve iletişim kutusundaki metnin özelleştirilemeyeceği bir not: bugzilla.mozilla.org/show_bug.cgi?id=588292
David Hammond

15
Peki o zaman facebook nasıl özel bir iletişim kutusu sağlar? örneğin, mesajlar sayfasına gidin, arkadaşınızın mesajını yanıtlayın ve ardından gönder'i tıklamadan önce başka bir bağlantıyı tıklamayı deneyin. özel bir iletişim kutusu açılır penceresi göreceksiniz
Varun

20
@Varun - eski haberler, ancak Facebook muhtemelen tüm çapalarının tıklama olayına işleyicileri koyuyor, ancak URL'yi tarayıcıda yeniden yazar veya pencereyi kapatırsanız, kontrolleri olmayan standart yönteme geri döner.
Tabloo Quijico

1
@Varun Ben de imkansız yollarını cevap olarak işaret ve 150 upvotes var bu cevap olduğu için şaşırdım ... Az önce fark, FB özel mesaj sadece kendi sitesindeki bağlantıları aracılığıyla kullanılabilir. - Sadece uzağa gidersen ...
Sébastien Richer

28

JQuery kullanarak ve IE8, Chrome ve Firefox'ta test edilen benim için işe yarayan şey:

$(window).bind("beforeunload",function(event) {
    if(hasChanged) return "You have unsaved changes";
});

IE ve diğer tarayıcı davranışları arasında farklılıklar olduğu için herhangi bir bilgi istemi gerekmiyorsa hiçbir şey döndürmemek önemlidir.


İlginç, event.returnValueIE'de "onaylanmış" tek yöntemdir. IE , "Bu özelliğin değeri, işlev tarafından döndürülen değerlere (örneğin, Microsoft JScript dönüş deyimi gibi) göre önceliklidir. .. return(etkinlikten) ile garantili bir korelasyon görmek güzel olurdu event.returnValue.

21

Bazı durumlarda kutuyla ilgili yapabileceğiniz herhangi bir şey olmasa da, bir bağlantıyı tıklatarak birini engelleyebilirsiniz. Benim için, bu çoğu senaryo için çabaya değerdi ve bir yedek olarak, boşaltma olayından ayrıldım.

Standart jQuery İletişim Kutusu yerine Boxy kullandım, burada bulabilirsiniz: http://onehackoranother.com/projects/jquery/boxy/

$(':input').change(function() {
    if(!is_dirty){
        // When the user changes a field on this page, set our is_dirty flag.
        is_dirty = true;
    }
});

$('a').mousedown(function(e) {
    if(is_dirty) {
        // if the user navigates away from this page via an anchor link, 
        //    popup a new boxy confirmation.
        answer = Boxy.confirm("You have made some changes which you might want to save.");
    }
});

window.onbeforeunload = function() {
if((is_dirty)&&(!answer)){
            // call this if the box wasn't shown.
    return 'You have made some changes which you might want to save.';
    }
};

Başka bir etkinliğe ekleyebilir ve ne tür bir çapa tıklatıldığına daha fazla filtre uygulayabilirsiniz, ancak bu benim için çalışıyor ve ne yapmak istediğimi ve başkalarının kullanması veya iyileştirmesi için bir örnek olarak hizmet ediyor. Bu çözümü isteyenler için bunu paylaşacağımı düşündüm.

Ben bu yüzden olduğu gibi çalışmayabilir, bu yüzden kodu kesti.


return 'Kaydetmek isteyebileceğiniz bazı değişiklikler yaptınız.' benim için çalışmadı. İletiyi 'alert_message' diyen bir değişkende saklamak zorunda kaldım ve warning_message döndürdüm. Sonra sadece benim için çalıştı !.
Suganya

IE, Chrome, Firefox'ta test yaptınız mı?
Kiquenet

9

1) Yüklemeden önce kullanın, onun yüklemesini kullanmayın.

2) Önemli olan, bir iade ifadesinin yürütülmesinden kaçınmaktır. Bununla, işleyicinizden dönmekten kaçınmak istemiyorum. Tamam, ancak bunu işlevin sonuna ulaştığınızdan ve bir return deyimi yürütmediğinizden emin olarak yaparsınız. Bu koşullar altında yerleşik standart iletişim kutusu oluşmaz.

3) onbeforeunload kullanırsanız, sunucudan toparlanmak için unbeforeunload işleyicinizde bir ajax çağrısı çalıştırabilirsiniz, ancak bu eşzamanlı olmalıdır ve beklemeden önce boşaltma işleyicinizde yanıtı beklemek ve işlemek zorundasınız (yine de (2) durumu). Bunu yapıyorum ve iyi çalışıyor. Senkronize bir ajax çağrısı yaparsanız, yanıt geri gelene kadar her şey beklemeye alınır. Sunucudan gelen yanıtı umursamadığınızı düşünerek eşzamansız bir işlem yaparsanız, sayfa kaldırma işlemi devam eder ve ajax çağrınız bu işlem tarafından iptal edilir - çalışıyorsa uzak bir komut dosyası da dahil.


Sadece FYI Herkes bu ^ Chrome okuma unbeforeunload senkron AJAX çağrıları
morganwebdev

4

return;Mesaj yerine bir yer koymayı deneyin . Bu benim için çoğu tarayıcıyı çalıştırıyor. (Bu yalnızca iletişim kutusunun hediyelerini gerçekten engeller)

window.onbeforeunload = function(evt) {            
        //Your Extra Code
        return;
}

3
return null iletişim kutusunun açılmasını engeller
Brett Weber

1
return null iletişim kutusunun açılmasını engellemez. Chrome'da denedim ve durum böyle değil.
Ray

2
Ray'ın IE'deki yorumunu da doğrulayabilirim. Geri döndürüldüğünde null"null" metnini içeren bir iletişim kutusu açılır. Ancak, return void(0);iletişim kutusu açılmaz.
MCattle

1
Yükleme öncesi işlevinin içine herhangi bir dönüş ifadesi koyulmadığı takdirde iletişim kutusu açılmaz.
OuuGiii


3

Kullanıcı tarafından hangi düğmeye (ok veya iptal) basıldığını tespit edebilirsiniz, çünkü onun yükleme işlevi yalnızca kullanıcı sayfadan ayrılmayı seçtiğinde çağrılır. Bu işlevde olasılıklar sınırlıdır, çünkü DOM çöker. Javascript çalıştırabilirsiniz, ancak ajax POST hiçbir şey yapmaz, bu nedenle otomatik çıkış için bu yöntemi kullanamazsınız. Ama bunun bir çözümü var. Window.open ('logout.php') onun yükleme işlevinde yürütülür, böylece kullanıcı yeni bir pencere açıklığı ile oturumu kapatır.

function onunload = (){
    window.open('logout.php');
}

Bu kod, kullanıcı sayfadan ayrıldığında veya etkin pencereyi kapattığında ve 'logout.php' tarafından çıkış yapan kullanıcı tarafından çağrılır. Çıkış php koddan oluştuğunda yeni pencere hemen kapanır:

window.close();

Yükleme öncesi ve boşaltma işlevlerinde eşzamanlı bir yazı kullanabilirsiniz. Özellikle sunucudan geri veri gerekiyorsa. Bu bloklar içindeki hiçbir zaman uyumsuz kod, sayfanın kaldırılmasıyla tamamlanamayabilir.
jemiloii

3

Aynı sorunla karşı karşıya kaldım, mesajımla kendi iletişim kutusunu almak için iyiydim, ancak karşılaştığım sorun şuydu: 1) Sadece yakın tıklama için istediğim tüm navigasyonlarda mesaj veriyordu. 2) Kullanıcı iptal etmeyi seçerse kendi onay mesajımla hala tarayıcının varsayılan iletişim kutusunu gösterir.

Ana sayfamda yazdığım bulduğum çözüm kodu aşağıdadır.

function closeMe(evt) {
    if (typeof evt == 'undefined') {
        evt = window.event; }
    if (evt && evt.clientX >= (window.event.screenX - 150) &&
        evt.clientY >= -150 && evt.clientY <= 0) {
        return "Do you want to log out of your current session?";
    }
}
window.onbeforeunload = closeMe;


1

"Bağlama" komutu "one" ın özel sürümünü kullanmaya ne dersiniz? Olay işleyici ilk kez yürütüldüğünde, olay işleyici olarak otomatik olarak kaldırılır.

$(window).one("beforeunload", BeforeUnload);

eminim bu .on ("beforeunload"
Sergiu Mindras

2
@SergiuMindras hayır, bu .one()- etkinliğin yalnızca bir kez gerçekleşmesini dinlemek için bir olay dinleyicisi ekler: "Öğeler için bir etkinliğe bir işleyici ekleyin. İşleyici, etkinlik türü başına öğe başına en fazla bir kez yürütülür." api.jquery.com/one
Sean

0

Açısal 9 yaklaşımı:

constructor() {
    window.addEventListener('beforeunload', (event: BeforeUnloadEvent) => {
     if (this.generatedBarcodeIndex) {
      event.preventDefault(); // for Firefox
      event.returnValue = ''; // for Chrome
      return '';
     }
     return false;
    });
   }

Tarayıcılar desteği ve özel mesajın kaldırılması:

  • Chrome, 51 dakika içinde özel mesaj desteğini kaldırdı
  • Opera, 38 dakika içinde özel mesaj desteğini kaldırdı
  • Firefox, 44.0 dakikada ver özel mesaj desteğini kaldırdı
  • Safari, 9.1 dakika süresinde özel mesaj desteğini kaldırdı
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.