Peringatkan pengguna sebelum meninggalkan halaman web dengan perubahan yang belum disimpan

341

Saya memiliki beberapa halaman dengan formulir di aplikasi saya.

Bagaimana saya bisa mengamankan formulir sedemikian rupa sehingga jika seseorang menavigasi atau menutup tab browser, mereka harus diminta untuk mengonfirmasi bahwa mereka benar-benar ingin meninggalkan formulir dengan data yang belum disimpan?

Khan
sumber
3
Pertanyaan ini di sini seharusnya memiliki jawaban yang Anda cari: stackoverflow.com/questions/1244535/...
Nexerus
1
Terkait: stackoverflow.com/q/821011/435605
AlikElzin-kilaka

Jawaban:

556

Pendek, jawaban yang salah:

Anda dapat melakukan ini dengan menangani beforeunloadacara dan mengembalikan string yang bukan nol :

window.addEventListener("beforeunload", function (e) {
    var confirmationMessage = 'It looks like you have been editing something. '
                            + 'If you leave before saving, your changes will be lost.';

    (e || window.event).returnValue = confirmationMessage; //Gecko + IE
    return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});

Masalah dengan pendekatan ini adalah bahwa mengirimkan formulir juga memecat acara bongkar . Ini diperbaiki dengan mudah dengan menambahkan tanda yang Anda kirimi formulir:

var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Kemudian memanggil setter saat mengirimkan:

<form method="post" onsubmit="setFormSubmitting()">     
    <input type="submit" />
</form>

Tapi baca terus ...

Panjang, jawaban yang benar:

Anda juga tidak ingin menampilkan pesan ini saat pengguna belum mengubah apa pun di formulir Anda . Salah satu solusinya adalah menggunakan beforeunloadacara tersebut dalam kombinasi dengan flag "kotor", yang hanya memicu prompt jika itu benar-benar relevan.

var isDirty = function() { return false; }

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting || !isDirty()) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

Sekarang untuk mengimplementasikan isDirtymetode ini, ada berbagai pendekatan.

Anda dapat menggunakan jQuery dan membentuk serialisasi , tetapi pendekatan ini memiliki beberapa kekurangan. Pertama, Anda harus mengubah kode agar berfungsi pada formulir apa pun ( $("form").each()akan dilakukan), tetapi masalah terbesar adalah bahwa jQuery serialize()hanya akan bekerja pada elemen yang dinamai dan tidak dinonaktifkan, jadi mengubah elemen yang dinonaktifkan atau tidak dinamai tidak akan memicu bendera kotor. Ada solusi untuk itu , seperti membuat kontrol hanya dibaca alih-alih mengaktifkan, membuat serial dan kemudian menonaktifkan kontrol lagi.

Jadi, peristiwa tampaknya merupakan jalan yang harus ditempuh. Anda dapat mencoba mendengarkan penekanan tombol . Acara ini memiliki beberapa masalah:

  • Tidak akan memicu pada kotak centang, tombol radio, atau elemen lain yang sedang diubah melalui input mouse.
  • Akan memicu penekanan tombol yang tidak relevan seperti Ctrlkuncinya.
  • Tidak akan memicu nilai yang ditetapkan melalui kode JavaScript.
  • Tidak akan memicu memotong atau menempelkan teks melalui menu konteks.
  • Tidak akan bekerja untuk input virtual seperti datepickers atau kotak centang / pemancar radiobutton yang menyimpan nilai mereka dalam input tersembunyi melalui JavaScript.

The changeevent juga tidak memicu pada nilai-nilai yang ditetapkan dari kode JavaScript , sehingga juga tidak akan bekerja untuk input virtual.

Mengikat inputacara untuk semua inputs (dan textareas dan selects) pada halaman Anda tidak akan bekerja pada browser lama dan, seperti semua penanganan solusi acara tersebut di atas, tidak mendukung undo. Ketika pengguna mengubah kotak teks dan kemudian membatalkan itu, atau memeriksa dan menghapus centang kotak centang, formulir itu masih dianggap kotor.

Dan ketika Anda ingin menerapkan lebih banyak perilaku, seperti mengabaikan elemen-elemen tertentu, Anda akan memiliki lebih banyak pekerjaan untuk dilakukan.

Jangan menemukan kembali roda:

Jadi sebelum Anda berpikir untuk mengimplementasikan solusi-solusi tersebut dan semua solusi yang diperlukan, sadarilah bahwa Anda sedang menciptakan kembali roda dan Anda cenderung mengalami masalah yang sudah dipecahkan orang lain untuk Anda.

Jika aplikasi Anda sudah menggunakan jQuery, Anda juga dapat menggunakan kode yang teruji dan dirawat alih-alih menggulirkan kode Anda sendiri, dan menggunakan perpustakaan bagian ketiga untuk semua ini. jQuery's Are You Sure? plugin berfungsi dengan baik, lihat halaman demo mereka . Sesederhana ini:

<script src="jquery.are-you-sure.js"></script>

<script>
  $(function() {
    $('#myForm').areYouSure(
      {
        message: 'It looks like you have been editing something. '
               + 'If you leave before saving, your changes will be lost.'
      }
    );
  });

</script>

Pesan khusus tidak didukung di mana-mana

Perhatikan bahwa Firefox 4 tidak mendukung pesan khusus dalam dialog ini. Mulai April 2016, Chrome 51 diluncurkan di mana pesan khusus juga dihapus .

Beberapa alternatif ada di tempat lain di situs ini, tetapi saya pikir dialog seperti ini cukup jelas:

Apakah Anda ingin meninggalkan situs ini?

Perubahan yang Anda buat mungkin tidak disimpan.

Leave Stay

CodeCaster
sumber
6
Perhatikan bahwa menggunakan string khusus tidak berfungsi lagi di Chrome; chromestatus.com/feature/5349061406228480
amann
5
Ya, itu dijelaskan di bagian terakhir dari jawaban saya.
CodeCaster
2
@ Chris itu karena Angular memanipulasi DOM untuk mengubah halaman, sementara tidak menavigasi dari dokumen saat ini.
CodeCaster
15
Berhati-hatilah. JQuery areYouSure telah ditinggalkan sejak 2014 (57 masalah terbuka tentang Github ), penuh dengan bug dari pengalaman saya, mungkin sepertinya bekerja pada awalnya tetapi setelah beberapa tes cepat saya menyadari itu tidak selalu berhasil. Tidak akan merekomendasikan ini sama sekali
Mark
4
@ JacopoStanchi Saya sayangnya tidak menemukan apa pun. Dan maksud saya, saya terlihat cukup banyak - tetapi ini kembali pada 10 Januari sehingga seseorang mungkin telah menulis sesuatu tetapi saya meragukannya. Taruhan terbaik Anda adalah menerapkannya sendiri - itu bukan apa yang ingin Anda dengar dengan sangat menyesal. (Tapi setidaknya Anda tidak akan mendapatkan kejutan seperti saya menggunakan jQuery areYouSure.) Plus siapa tahu mungkin Anda bahkan bisa menjadikannya open source dan implementasi Anda akan dibagikan dengan orang lain;)
Mark
75

Lihat JavaScript di acara sebelumnya sebelum memuat . Ini adalah JavaScript non-standar yang diperkenalkan oleh Microsoft, namun ini berfungsi di sebagian besar browser dan dokumentasi mereka yang ada sebelumnya memuat lebih banyak informasi dan contoh.

Paul Annesley
sumber
3
Saya pikir itu sudah menjadi standar sekarang. >> Acara ini awalnya diperkenalkan oleh Microsoft di Internet Explorer 4 dan distandarisasi dalam spesifikasi HTML5.
vee
34

via jquery

$('#form').data('serialize',$('#form').serialize()); // On load save form current state

$(window).bind('beforeunload', function(e){
    if($('#form').serialize()!=$('#form').data('serialize'))return true;
    else e=null; // i.e; if form state change show warning box, else don't show it.
});

Anda dapat menjalankan fungsi Google JQuery Form Serialize, ini akan mengumpulkan semua input formulir dan menyimpannya dalam array. Saya kira penjelasan ini sudah cukup :)

Wasim A.
sumber
6
jangan gunakan #form sebagai id formulir karena jendela akan membuat dan objek bernama form :)
mdikici
1
Periksa di sini apakah itu tidak berfungsi untuk Anda: stackoverflow.com/questions/7080269/…
Leniel Maccaferri
16

Solusi universal tanpa memerlukan konfigurasi yang secara otomatis mendeteksi semua modifikasi input, termasuk elemen yang dapat diedit:

"use strict";
(() => {
const modified_inputs = new Set;
const defaultValue = "defaultValue";
// store default values
addEventListener("beforeinput", (evt) => {
    const target = evt.target;
    if (!(defaultValue in target || defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ("" + (target.value || target.textContent)).trim();
    }
});
// detect input modifications
addEventListener("input", (evt) => {
    const target = evt.target;
    let original;
    if (defaultValue in target) {
        original = target[defaultValue];
    } else {
        original = target.dataset[defaultValue];
    }
    if (original !== ("" + (target.value || target.textContent)).trim()) {
        if (!modified_inputs.has(target)) {
            modified_inputs.add(target);
        }
    } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
    }
});
// clear modified inputs upon form submission
addEventListener("submit", () => {
    modified_inputs.clear();
    // to prevent the warning from happening, it is advisable
    // that you clear your form controls back to their default
    // state after submission
});
// warn before closing if any inputs are modified
addEventListener("beforeunload", (evt) => {
    if (modified_inputs.size) {
        const unsaved_changes_warning = "Changes you made may not be saved.";
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
    }
});
})();
Eli Gray
sumber
1
Kacang keren. Cukup salin tempel kode ini ke halaman pengujian Anda, buat perubahan dan tekan segarkan. Ini akan menampilkan peringatan browser asli yang memperingatkan Anda bahwa Anda memiliki perubahan yang belum disimpan.
TheLegendaryCopyCoder
1
Ini bekerja untuk saya di Chrome 71.0.3578.98 (Bangun Resmi) (64-bit)
JacobRossDev
2
Ini berfungsi dengan sangat baik, tetapi jika Anda menggunakan ini dengan formulir untuk pengiriman, Anda harus menghapus set modifikasi_input terlebih dahulu sebelum jika tidak, Anda akan mendapatkan konfirmasi perubahan lansiran. Saya menambahkan pendengar acara ke formulir saya untuk meminta pengiriman, dan hanya menjalankan fungsi set yang jelas, dengan cara itu modified_inputs jelas ketika sebelumunload pendengar acara berjalan, dan memungkinkan posting untuk melanjutkan.
stepquick
1
Sebenarnya keren salin dan tempel. terima kasih telah menghemat waktu saya. Bekerja untuk saya di Firfox 75.0
Connectify_user
1
Love snippet ini
Rawburner
10

Dibangun di atas ide bagus Wasim A. untuk menggunakan serialisasi. Masalahnya adalah bahwa peringatan itu juga ditampilkan ketika formulir sedang dikirim. Ini sudah diperbaiki di sini.

var isSubmitting = false

$(document).ready(function () {
    $('form').submit(function(){
        isSubmitting = true
    })

    $('form').data('initial-state', $('form').serialize());

    $(window).on('beforeunload', function() {
        if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
            return 'You have unsaved changes which will not be saved.'
        }
    });
})

Ini telah diuji di Chrome dan IE 11.

Eerik Sven Puudist
sumber
Wasim A dan Eerik Sven Puudist - Terima kasih saya menggunakan id untuk formulir dan id untuk tombol simpan saya karena semua tombol saya adalah tipe kirim <form action = "" id = "marksform" method = "POST"> <td> <input type = "submit" name = "submit_button" id = "save" value = "Save"> </td> <td> <input type = "submit" name = "submit_button" value = "Next"> </td> dan sedikit lebih banyak semua jenis kirim Karena itu diganti .Submit (dengan klik spesifik $ ('# save') .klik (fungsi () {isSubmitting = true}) Gunakan '#markform' sebagai ganti 'form'
Jayanta
7

Berdasarkan jawaban sebelumnya, dan dibuat dari berbagai tempat di stack overflow, berikut ini adalah solusi yang saya temukan yang menangani kasus ketika Anda benar-benar ingin mengirimkan perubahan:

window.thisPage = window.thisPage || {};
window.thisPage.isDirty = false;

window.thisPage.closeEditorWarning = function (event) {
    if (window.thisPage.isDirty)
        return 'It looks like you have been editing something' +
               ' - if you leave before saving, then your changes will be lost.'
    else
        return undefined;
};

$("form").on('keyup', 'textarea', // You can use input[type=text] here as well.
             function () { 
                 window.thisPage.isDirty = true; 
             });

$("form").submit(function () {
    QC.thisPage.isDirty = false;
});
window.onbeforeunload = window.thisPage.closeEditorWarning;

Perlu dicatat bahwa IE11 tampaknya mensyaratkan bahwa closeEditorWarningfungsi kembali undefineduntuk tidak menunjukkan peringatan.

Jonathan
sumber
Solusi ini tidak memverifikasi bahwa nilai apa pun diubah dari keadaan aslinya, karenanya membatalkan jika pengguna memasukkan teks dan menghapus yang memasukkan teks sebelum mencoba menavigasi.
Brett Weber
Poin bagus, @ BrettWeber. Anda dapat memodifikasi closeEditorWarning dalam kasus itu, dan memiliki "if (window.thisPage.isDirty && uiHasChanged ())", di mana uiHasChanged adalah fungsi yang mengetahui status asli dari server, dan memeriksa semua perbedaan, tetapi solusi ini ditujukan untuk sebuah kasus di mana saya tidak secara khusus ingin melakukan semua pekerjaan ekstra itu, dan ini hanya memiliki positif palsu ketika penekanan tombol yang sebenarnya telah dibuat di textareas, yang saya rasa merupakan kompromi yang masuk akal. :)
Jonathan
Tidak QC.thisPage.isDirty = false;seharusnya window.thisPage.isDirty = false;? Dengan begitu, itu akan memeriksa apakah Anda mengirimkan formulir dan tidak menunjukkan peringatan. Tampaknya bekerja untuk pengujian saya. Juga, sebagian besar formulir memiliki inputbukan textarea. Saya menggunakan yang berikut ini yang bekerja dengan cukup baik:$("form").on('keyup', 'textarea,input,select', function () {
Mike
7

Satu kalimat berikut telah bekerja untuk saya.

window.onbeforeunload = s => modified ? "" : null;

Hanya disetel modifiedke true atau false, tergantung pada kondisi aplikasi Anda.

spencer.sm
sumber
2
Beberapa saran: Kembalikan pesan khusus alih-alih string kosong karena beberapa peramban akan menampilkannya (misalnya Tepi), dan kembali undefineddaripada nullkarena IE akan mencetak 'nol' jika modifiedsalah.
Kevin Lee
1
bagaimana dengan perangkat seluler? Pemahaman saya adalah bahwa perangkat iOS tidak menghormati onbeun sebelumnya.
jaybro
4

Kode berikut berfungsi dengan baik. Anda harus mencapai perubahan input elemen formulir melalui atribut id:

var somethingChanged=false;
            $('#managerForm input').change(function() { 
                somethingChanged = true; 
           }); 
            $(window).bind('beforeunload', function(e){
                if(somethingChanged)
                    return "You made some changes and it's not saved?";
                else 
                    e=null; // i.e; if form state change show warning box, else don't show it.
            });
        });
metzelder
sumber
3
var unsaved = false;
$(":input").change(function () {         
    unsaved = true;
});

function unloadPage() {         
    if (unsaved) {             
        alert("You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?");
    }
} 
window.onbeforeunload = unloadPage;
Ankit
sumber
Saya memasukkannya dalam file terpisah dan saya memasukkannya dengan <script src = "warnOnChange.js"> </script> tetapi tidak ada yang terjadi ketika saya memodifikasi textfield dan kemudian saya menjalankan perintah header.
Fabrizio Bartolomucci
2

Anda dapat menggunakan serialize () untuk membuat string teks yang disandikan URL dengan membuat serialisasi nilai formulir dan memeriksa apakah formulir telah berubah sebelumunload

$(document).ready(function(){
    var form = $('#some-form'),
        original = form.serialize()

    form.submit(function(){
        window.onbeforeunload = null
    })

    window.onbeforeunload = function(){
        if (form.serialize() != original)
            return 'Are you sure you want to leave?'
    }
})

Lihat tautan ini https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form Ditulis oleh Vladimir Sidorenko

Vennila M
sumber
1
Berhasil, tetapi seperti dijawab oleh kode kastor, ada beberapa kekurangan dengan metode ini, lihat penjelasan ini stackoverflow.com/a/7317311/10555981
Pradeep
Sudah ada beberapa jawaban yang digunakan serialize(), dan memang, ada kekurangannya.
CodeCaster
Ini harus menjadi jawaban yang benar, sangat mudah digunakan dan berfungsi seperti yang diharapkan.
Jodyshop
1

Menambahkan ke ide @codecaster Anda dapat menambahkan ini ke setiap halaman dengan formulir (dalam kasus saya, saya menggunakannya secara global sehingga hanya pada formulir yang memiliki peringatan ini) ubah fungsinya menjadi

if ( formSubmitting || document.getElementsByTagName('form').length == 0) 

Juga masukkan formulir kirim termasuk login dan di batal tombol tautan sehingga ketika orang menekan membatalkan atau mengirimkan formulir tidak akan memicu peringatan juga di setiap halaman dengan formulir ...

<a class="btn btn-danger btn-md" href="back/url" onclick="setFormSubmitting()">Cancel</a>
Esteban Fuentealba
sumber
1

Anda dapat memeriksa penjelasan terperinci di sini: http://techinvestigations.redexp.in/comparison-of-form-values-on-load-and-before-close/ perbandingan-of-form-values-on-load-and -sebelum tutup

Kode utama:

function formCompare(defaultValues, valuesOnClose) {

    // Create arrays of property names
    var aPropsFormLoad = Object.keys(defaultValues);
    var aPropsFormClose = Object.keys(valuesOnClose);

    // If number of properties is different,
    // objects are not equivalent
    if (aPropsFormLoad.length != aPropsFormClose.length) {
        return false;
    }

    for (var i = 0; i < aPropsFormLoad.length; i++) {
        var propName = aPropsFormLoad[i];

        // If values of same property are not equal,
        // objects are not equivalent
        if (defaultValues[aPropsFormLoad]+"" !== valuesOnClose[aPropsFormLoad]+"") {
            return false;
        }
    }

    // If we made it this far, objects
    // are considered equivalent
    return true;

}

//add polyfill for older browsers, as explained on the link above

//use the block below on load
    for(i=0; i < document.forms[0].elements.length; i++){
    console.log("The field name is: " + document.forms[0].elements[i].name +
        " and it’s value is: " + document.forms[0].elements[i].value );
    aPropsFormLoad[i] = document.forms[0].elements[i].value;
    }

//create a similar array on window unload event.

//and call the utility function
    if (!formCompare(aPropsOnLoad, aPropsOnClose))
    {
    //perform action: 
    //ask user for confirmation or
    //display message about changes made
    }
Kanika Sud
sumber
1

Jawaban singkat:

let pageModified = true

window.addEventListener("beforeunload", 
  () => pageModified ? 'Close page without saving data?' : null
)
Daniel Garmoshka
sumber
1

Solusi oleh Eerik Sven Puudist ...

var isSubmitting = false;

$(document).ready(function () {
    $('form').submit(function(){
        isSubmitting = true
    })

    $('form').data('initial-state', $('form').serialize());

    $(window).on('beforeunload', function() {
        if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
            return 'You have unsaved changes which will not be saved.'
        }
    });
})

... secara spontan melakukan pekerjaan untuk saya dalam lingkungan berorientasi objek yang kompleks tanpa perubahan apa pun yang diperlukan.

Satu-satunya perubahan yang saya terapkan adalah merujuk ke formulir konkret (hanya satu formulir per file) yang disebut "formForm" ('form' -> '#formForm'):

<form ... id="formForm" name="formForm" ...>

Yang dilakukan dengan sangat baik adalah kenyataan bahwa tombol kirim sedang "dibiarkan sendiri".

Selain itu, ini juga berfungsi untuk saya dengan Firefox versi terbaru (per 7 Februari 2019).

mtjmohr
sumber
1

Diuji solusi universal Eli Grey, hanya bekerja setelah saya menyederhanakan kode

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

  })();

Modifikasi miliknya dihapus penggunaan target[defaultValue]dan hanya digunakan target.dataset[defaultValue]untuk menyimpan nilai default nyata.

Dan saya menambahkan pendengar acara 'tersimpan' di mana acara 'disimpan' akan dipicu oleh Anda sendiri pada tindakan tabungan Anda berhasil.

Tapi solusi 'universal' ini hanya berfungsi di browser, tidak bekerja di tampilan web aplikasi, misalnya, browser wechat.

Untuk membuatnya berfungsi di browser wechat (sebagian) juga, perbaikan lagi:

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }

      if(modified_inputs.size){
        const event = new Event('needSave')
        window.dispatchEvent(event);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

    const ua = navigator.userAgent.toLowerCase();

    if(/MicroMessenger/i.test(ua)) {
      let pushed = false

      addEventListener('needSave', evt => {
        if(!pushed) {
          pushHistory();

          window.addEventListener("popstate", function(e) {
            if(modified_inputs.size) {
              var cfi = confirm('确定要离开当前页面嘛?' + JSON.stringify(e));
              if (cfi) {
                modified_inputs.clear()
                history.go(-1)
              }else{
                e.preventDefault();
                e.stopPropagation();
              }
            }
          }, false);
        }

        pushed = true
      });
    }

    function pushHistory() {
      var state = {
        title: document.title,
        url: "#flag"
      };
      window.history.pushState(state, document.title, "#flag");
    }
  })();
Jeff Tian
sumber
0

Saya melakukannya secara berbeda, berbagi di sini sehingga seseorang dapat memperoleh bantuan, hanya diuji dengan Chrome.

Saya ingin memperingatkan pengguna sebelum menutup tab hanya jika ada beberapa perubahan.

<input type="text" name="field" value="" class="onchange" />

var ischanged = false;

$('.onchange').change(function () {
    ischanged = true;
});

window.onbeforeunload = function (e) {
    if (ischanged) {
        return "Make sure to save all changes.";
    }        
};

Berfungsi dengan baik, tetapi ada masalah lain, ketika saya mengirimkan formulir saya mendapatkan peringatan yang tidak diinginkan, saya melihat banyak solusi di atasnya, ini karena sebelumnya memuat api sebelum serangan itu sebabnya kami tidak bisa menangani dalam acara pengiriman seperti onbeforeunload = null, tapi onclick acara tombol kirim menyala sebelum kedua acara ini, jadi saya memperbarui kode

var isChanged = false;
var isSubmit = false;

window.onbeforeunload = function (e) {
    if (isChanged && (!isSubmit)) {
        return "Make sure to save all changes.";
    }        
};

$('#submitbutton').click(function () {
    isSubmit = true;
});

$('.onchange').change(function () {
    isChanged = true;
});
sairfan
sumber
-5

Pertama-tama, sebagian besar browser memiliki fungsi ini secara default. Dan mengapa Anda membutuhkan ini sama sekali? Mengapa tidak menyinkronkan formulir? Maksud saya, simpan pada perubahan apa pun tanpa menunggu pengiriman dari pengguna. Seperti halnya Google Kontak. Tentu saja jika hanya semua bidang yang wajib diisi. Pengguna tidak suka ketika mereka memaksa untuk mengisi sesuatu tanpa kesempatan untuk berpikir apakah mereka membutuhkannya. :)

YS
sumber
apakah Anda benar tetapi formulir saya dihasilkan secara dinamis dan bidang tidak dalam kendali saya sehingga bagi saya tidak mungkin untuk melacak semua bidang dan mengirim permintaan melalui ajax, jika Anda memiliki sesuatu dalam pikiran silakan berbagi dengan saya.
Khan
Oke mungkin tidak perlu untuk tujuan Anda tetapi masih bisa diterapkan. Jika elemen formulir ada di layar, Anda dapat melampirkan penangan acara Anda sendiri dan mendapatkan data apa pun yang Anda inginkan. Kemudian gunakan AJAX untuk menyimpan data ke tempat yang Anda suka. Bahkan jika formulir memiliki ID atau nama kelas yang dibuat secara acak, Anda dapat menggunakan XPath jika Anda dapat mengantisipasi struktur formulir. Itu XML / HTML kan? Jadi Anda bahkan dapat memiliki JAD dengan orang-orang yang bertanggung jawab atas formulir yang dihasilkan secara dinamis dan berbicara tentang bagaimana XSTL dapat menguntungkan Anda berdua dalam proyek ini. Hanya pemikiran ...
SimonDever
1
save it on any change without waiting any submitting from userAnda tidak selalu ingin melakukan ini. Terkadang pengguna ingin membuat banyak perubahan dan kemudian meninjau dan mengonfirmasi bahwa mereka ingin menyimpannya.
BadHorsie
1
Saya tidak menyarankan untuk mengirimkan formulir. Data dapat disimpan dalam penyimpanan lokal, dalam beberapa cache atau bahkan dikirimkan dengan beberapa bendera konsep. Ada banyak metode untuk perilaku ini. Ini jauh lebih baik daripada memberi tahu pengguna bahwa dia tidak menyelesaikan formulir dan jika dia tidak mau dan akan menutup jendela dia harus mengisinya lagi lain kali. "Ayolah, kawan, jangan malas, kereta / bus / pesawat / dll. Tidak masalah juga karena kami tidak peduli kamu lupa charger dari laptop kamu, cukup isi formulir sialan ini!"
YuS