Bagaimana saya bisa mengganti dialog OnBeforeUnload dan menggantinya dengan saya sendiri?

346

Saya perlu memperingatkan pengguna tentang perubahan yang belum disimpan sebelum mereka meninggalkan halaman (masalah yang cukup umum).

window.onbeforeunload=handler

Ini berfungsi tetapi ini memunculkan dialog default dengan pesan standar yang menjengkelkan yang membungkus teks saya sendiri. Saya perlu mengganti pesan standar sepenuhnya, jadi teks saya jelas, atau (bahkan lebih baik) mengganti seluruh dialog dengan dialog modal menggunakan jQuery.

Sejauh ini saya telah gagal dan saya belum menemukan orang lain yang tampaknya memiliki jawaban. Apakah itu mungkin?

Javascript di halaman saya:

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

Fungsi closeIt ():

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

Menggunakan jQuery dan jqModal Saya telah mencoba hal semacam ini (menggunakan dialog konfirmasi khusus):

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

yang juga tidak berfungsi - Sepertinya saya tidak dapat mengikat ke acara beforeunload.

daging
sumber
1
dapatkah Anda memberikan contoh kode Anda saat ini dan apa yang dihasilkannya?
Owen
Owen benar. Dan, alasan di balik ini adalah keamanan. Mencegah halaman dari pembongkaran berguna dalam formulir web dan semacamnya, tetapi dapat dengan mudah dieksploitasi oleh situs jahat untuk menipu pengguna agar tetap berada di halaman. Itu sebabnya browser web menerapkan pesan standar dan memiliki mekanisme ini untuk menyisipkan teks khusus.
pluckyglen
lihat di sini untuk info lebih lanjut: stackoverflow.com/questions/140460
Ben McIntyre
1
tidak mungkin di chrome, referensi: stackoverflow.com/questions/37782104/…
Abhijeet

Jawaban:

299

Anda tidak dapat mengubah dialog default untuk onbeforeunload, jadi taruhan terbaik Anda mungkin bekerja dengannya.

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

Ini referensi untuk ini dari Microsoft:

Ketika sebuah string ditugaskan ke properti returnValue dari window.event, sebuah kotak dialog muncul yang memberi pengguna pilihan untuk tetap di halaman saat ini dan mempertahankan string yang ditugaskan untuk itu. Pernyataan default yang muncul di kotak dialog, "Apakah Anda yakin ingin bernavigasi dari halaman ini? ... Tekan OK untuk melanjutkan, atau Batal untuk tetap berada di halaman saat ini.", Tidak dapat dihapus atau diubah.

Masalahnya tampaknya:

  1. Ketika onbeforeunloaddipanggil, ia akan mengambil nilai balik dari pawang sebagai window.event.returnValue.
  2. Kemudian akan menguraikan nilai kembali sebagai string (kecuali jika itu nol).
  3. Karena falsediuraikan sebagai string, kotak dialog akan menyala, yang kemudian akan melewati true/ false.

Hasilnya, ada tampaknya tidak menjadi cara menugaskan falseuntuk onbeforeunloaduntuk mencegah dari dialog default.

Catatan tambahan pada jQuery:

  • Pengaturan acara di jQuery mungkin bermasalah, karena itu memungkinkan onbeforeunloadacara lain terjadi juga. Jika Anda hanya ingin acara bongkar terjadi, saya akan tetap berpegang teguh pada JavaScript untuk itu.
  • jQuery tidak memiliki pintasan onbeforeunloadsehingga Anda harus menggunakan bindsintaksis generik .

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

Sunting 09/04/2018 : pesan khusus di dialog onbeforeunload sudah tidak digunakan lagi sejak chrome-51 (lih: catatan rilis )

Owen
sumber
20
Saya telah menemukan bahwa contoh JQuery yang diberikan pada akhirnya tidak bekerja di firefox. Tetap dengan cara sederhana sebagai gantinya: window.onbeforeunload = function () {...}
jb.
21
Hanya catatan bahwa Firefox baru-baru ini diubah sehingga teks dalam dialog bahkan tidak dapat dikustomisasi: bugzilla.mozilla.org/show_bug.cgi?id=588292
David Hammond
15
Tapi bagaimana cara facebook menyediakan kotak dialog khusus? misalnya, buka halaman pesan, balas pesan teman Anda dan kemudian sebelum mengklik kirim, coba klik tautan lain. Anda akan melihat popup dialog khusus
Varun
20
@Varun - berita lama tetapi Facebook mungkin menempatkan penangan pada acara klik semua jangkar mereka, tetapi jika Anda menulis ulang URL di browser atau menutup jendela, itu kembali ke metode standar yang tidak dapat mereka kendalikan.
Tabloo Quijico
1
@ Varun Saya juga terkejut bahwa jawaban ini yang tidak mungkin ditandai sebagai jawaban dan memiliki 150 upvotes ... Baru disadari, pesan khusus FB hanya tersedia melalui tautan di dalam situs mereka. Tidak jika Anda hanya menavigasi ...
Sébastien Richer
28

Apa yang berhasil bagi saya, menggunakan jQuery dan diuji di IE8, Chrome dan Firefox, adalah:

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

Penting untuk tidak mengembalikan apa pun jika tidak ada prompt yang diperlukan karena ada perbedaan antara IE dan perilaku browser lainnya di sini.

Grebe
sumber
Menarik, event.returnValueadalah satu-satunya metode "yang disetujui" di IE. IE selanjutnya mengatakan "Nilai properti ini lebih diutamakan daripada nilai yang dikembalikan oleh fungsi, seperti melalui pernyataan pengembalian Microsoft JScript." .. akan menyenangkan untuk melihat korelasi yang dijamin antara return(dari acara) dan event.returnValue..
21

Meskipun tidak ada yang dapat Anda lakukan tentang kotak dalam beberapa keadaan, Anda dapat mencegat seseorang yang mengklik tautan. Bagi saya, ini sepadan dengan usaha untuk sebagian besar skenario dan sebagai mundur, saya telah meninggalkan acara unload.

Saya telah menggunakan Boxy alih-alih Dialog jQuery standar, itu tersedia di sini: 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.';
    }
};

Anda dapat melampirkan ke acara lain, dan memfilter lebih lanjut tentang jenis jangkar apa yang diklik, tetapi ini berfungsi untuk saya dan apa yang ingin saya lakukan dan berfungsi sebagai contoh bagi orang lain untuk digunakan atau ditingkatkan. Kupikir aku akan membagikan ini untuk mereka yang menginginkan solusi ini.

Saya telah memotong kode, jadi ini mungkin tidak berfungsi sebagaimana mestinya.

Dan Power
sumber
return 'Anda telah membuat beberapa perubahan yang mungkin ingin Anda simpan.' tidak bekerja untuk saya. Saya harus menyimpan pesan dalam variabel yang mengatakan 'warning_message' dan saya mengembalikan warning_message. Maka hanya itu yang bekerja untuk saya !.
Suganya
apakah Anda menguji di IE, Chrome, Firefox?
Kiquenet
9

1) Gunakan onbeforeunload, bukan onunload.

2) Yang penting adalah untuk menghindari mengeksekusi pernyataan pengembalian. Maksud saya, dengan ini, untuk menghindari kembali dari pawang Anda. Anda kembali baik-baik saja, tetapi Anda melakukannya dengan memastikan bahwa Anda mencapai akhir fungsi dan JANGAN menjalankan pernyataan kembali. Dalam kondisi ini, dialog standar bawaan tidak terjadi.

3) Anda dapat, jika menggunakan onbeforeunload, menjalankan panggilan ajax di handler unbeforeunload Anda untuk merapikan server, tetapi itu harus yang sinkron, dan Anda harus menunggu dan menangani balasan di handler onbeforeunload Anda (masih menghormati kondisi (2) di atas). Saya melakukan ini dan itu berfungsi dengan baik. Jika Anda melakukan panggilan ajax sinkron, semuanya tertahan hingga respons kembali. Jika Anda melakukan yang tidak sinkron, berpikir bahwa Anda tidak peduli dengan balasan dari server, halaman dibongkar terus dan panggilan ajax Anda dibatalkan oleh proses ini - termasuk skrip jarak jauh jika sedang berjalan.

pengguna1164763
sumber
Hanya FYI ada orang yang membaca ini ^ Chrome sudah menolak panggilan AJAX yang sinkron di unbeforeunload
morganwebdev
4

Cobalah menempatkan return;bukan pesan .. ini berfungsi sebagian besar browser untuk saya. (Ini hanya benar-benar mencegah hadiah dialog)

window.onbeforeunload = function(evt) {            
        //Your Extra Code
        return;
}
Donald Powell
sumber
3
return null akan mencegah dialog dibuka
Brett Weber
1
return null TIDAK akan mencegah dialog dari pembukaan. Saya mencobanya di Chrome dan bukan itu masalahnya.
Ray
2
Saya dapat mengkonfirmasi komentar Ray di IE juga. Kembali nullakan membuka dialog dengan teks "null". Namun, return void(0);tidak akan membuka dialog.
MCattle
1
Dengan tidak memasukkan pernyataan kembali apa pun di dalam fungsi beforeunload, dialog tidak akan terbuka.
OuuGiii
3

Anda dapat mendeteksi tombol mana (ok atau batal) yang ditekan oleh pengguna, karena fungsi onunload dipanggil hanya ketika pengguna memilih meninggalkan halaman. Meskipun dalam fungsi ini kemungkinan terbatas, karena DOM sedang runtuh. Anda dapat menjalankan javascript, tetapi POST ajax tidak melakukan apa-apa karena itu Anda tidak dapat menggunakan metode ini untuk logout otomatis. Tetapi ada solusi untuk itu. Window.open ('logout.php') dijalankan di fungsi onunload, sehingga pengguna akan keluar dengan membuka jendela baru.

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

Kode ini dipanggil saat pengguna meninggalkan halaman atau menutup jendela aktif dan pengguna keluar dengan 'logout.php'. Jendela baru ditutup segera ketika logout php terdiri dari kode:

window.close();
Tamas Cseh
sumber
Anda dapat menggunakan pos sinkron di fungsi beforeunload dan unload. Apalagi jika Anda membutuhkan data kembali dari server. Kode async apa pun di dalam blok tersebut mungkin tidak dapat diselesaikan pada saat halaman dibongkar.
jemiloii
3

Saya menghadapi masalah yang sama, saya baik-baik saja untuk mendapatkan kotak dialog sendiri dengan pesan saya, tetapi masalah yang saya hadapi adalah: 1) Ia memberi pesan pada semua navigasi yang saya inginkan hanya untuk klik dekat. 2) dengan pesan konfirmasi saya sendiri jika pengguna memilih membatalkannya masih menampilkan kotak dialog default browser.

Berikut ini adalah kode solusi yang saya temukan, yang saya tulis di halaman Master saya.

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;
Imran Rizvi
sumber
1
 <script type="text/javascript">
        window.onbeforeunload = function(evt) {
            var message = 'Are you sure you want to leave?';
            if (typeof evt == 'undefined') {
                evt = window.event;
            }       
            if (evt) {
                evt.returnValue = message;
            }
            return message;
        } 
    </script>

lihat dari http://www.codeprojectdownload.com

Krishna Patel
sumber
1

Bagaimana dengan menggunakan versi khusus dari perintah "bind" "one". Setelah event handler dieksekusi pertama kali, itu secara otomatis dihapus sebagai event handler.

$(window).one("beforeunload", BeforeUnload);
Riga
sumber
cukup yakin ini .on ("beforeunload"
Sergiu Mindras
2
@SergiuMindras tidak, itu .one()- yang melampirkan pendengar acara untuk mendengarkan acara hanya terjadi sekali: "Lampirkan pawang ke suatu acara untuk elemen. Pawang dijalankan paling banyak sekali per elemen per jenis acara." api.jquery.com/one
Sean Kendle
0

Pendekatan sudut 9:

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

Dukungan browser dan penghapusan pesan khusus:

  • Chrome menghapus dukungan untuk pesan khusus dalam ver 51 menit
  • Opera menghapus dukungan untuk pesan khusus dalam ver 38 menit
  • Firefox menghapus dukungan untuk pesan khusus dalam ver 44.0 mnt
  • Safari menghapus dukungan untuk pesan khusus di ver 9.1 min
Istvan Dembrovszky
sumber