बिना परिवर्तन किए वेब पेज को छोड़ने से पहले उपयोगकर्ता को चेतावनी दें


341

मेरे आवेदन में प्रपत्रों के साथ कुछ पृष्ठ हैं।

मैं फॉर्म को इस तरह से कैसे सुरक्षित कर सकता हूं कि यदि कोई व्यक्ति ब्राउज़र टैब को दूर करता है या बंद करता है, तो उन्हें इस बात की पुष्टि करने के लिए प्रेरित किया जाना चाहिए कि क्या वे वास्तव में सहेजे गए डेटा के साथ फॉर्म छोड़ना चाहते हैं?



3
यहाँ इस सवाल का जवाब आपके पास होना चाहिए: stackoverflow.com/questions/1244535/…
Nexerus


जवाबों:


556

लघु, गलत उत्तर:

आप इस घटना को संभालने beforeunloadऔर एक गैर-अशक्त स्ट्रिंग वापस करके ऐसा कर सकते हैं :

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.
});

इस दृष्टिकोण के साथ समस्या यह है कि एक फॉर्म सबमिट करना भी अनलोड घटना को फायर कर रहा है । यह उस ध्वज को जोड़कर आसानी से तय किया जाता है जिसे आप एक फ़ॉर्म सबमिट कर रहे हैं:

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.
    });
};

फिर सबमिट करते समय सेटर को कॉल करना:

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

लेकिन पढ़िए ...

लंबा, सही उत्तर:

जब उपयोगकर्ता आपके प्रपत्रों में कुछ भी नहीं बदला है, तो आप भी यह संदेश नहीं दिखाना चाहते । एक समाधान beforeunload"गंदे" ध्वज के संयोजन में घटना का उपयोग करना है , जो केवल प्रांप्ट को ट्रिगर करता है यदि यह वास्तव में प्रासंगिक है।

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.
    });
};

अब isDirtyविधि को लागू करने के लिए , विभिन्न दृष्टिकोण हैं।

आप jQuery और प्रपत्र क्रमांकन का उपयोग कर सकते हैं , लेकिन इस दृष्टिकोण में कुछ खामियां हैं। पहले आपको किसी भी रूप में काम करने के लिए कोड को बदलना $("form").each()होगा ( करेंगे), लेकिन सबसे बड़ी समस्या यह है कि jQuery का serialize()नाम केवल गैर-अक्षम तत्वों पर काम करेगा, इसलिए किसी भी अक्षम या अनाम तत्व को बदलने से गंदे झंडे को ट्रिगर नहीं किया जाएगा। इसके लिए वर्कअराउंड हैं , जैसे नियंत्रण को सक्षम करने, अनुक्रमित करने और फिर से फिर से नियंत्रण अक्षम करने के बजाय आसानी से नियंत्रण बनाना।

इसलिए घटनाओं को जाने का रास्ता लगता है। आप keypresses के लिए सुनने की कोशिश कर सकते हैं । इस घटना के कुछ मुद्दे हैं:

  • चेकबॉक्स, रेडियो बटन, या अन्य तत्वों पर ट्रिगर नहीं किया जाएगा जो माउस इनपुट के माध्यम से बदल रहे हैं।
  • कुंजी की तरह अप्रासंगिक कुंजी के लिए ट्रिगर करेगा Ctrl
  • जावास्क्रिप्ट कोड के माध्यम से निर्धारित मूल्यों पर ट्रिगर नहीं होगा।
  • संदर्भ मेनू के माध्यम से पाठ को काटने या चिपकाने पर ट्रिगर नहीं होगा।
  • वर्चुअल इनपुट जैसे डेटापिकर्स या चेकबॉक्स / रेडियोबॉटन ब्यूटिफायर के लिए काम नहीं करेंगे जो जावास्क्रिप्ट के माध्यम से छिपे हुए इनपुट में उनके मूल्य को बचाते हैं।

changeघटना भी जावा स्क्रिप्ट कोड से सेट मूल्यों पर ट्रिगर नहीं करता आभासी आदानों के लिए काम नहीं करेगा, तो भी।

inputinputtextareaselectअपने पेज पर सभी s (और s ) के लिए इवेंट को बाइंड करना पुराने ब्राउज़र पर काम नहीं करेगा और, जैसा कि ऊपर वर्णित सभी इवेंट हैंडलिंग समाधान पूर्ववत नहीं करता है। जब कोई उपयोगकर्ता एक टेक्स्टबॉक्स बदलता है और फिर उस चेक को अनचेक करता है, या चेकबॉक्स को अनचेक करता है, तो फॉर्म को अभी भी गंदा माना जाता है।

और जब आप अधिक व्यवहार को लागू करना चाहते हैं, जैसे कुछ तत्वों को अनदेखा करना, तो आपके पास और भी अधिक काम करना होगा।

पहिया को मजबूत न करें:

तो इससे पहले कि आप उन समाधानों और सभी आवश्यक वर्कअराउंड को लागू करने के बारे में सोचें, एहसास करें कि आप पहिया को फिर से मजबूत कर रहे हैं और आप दूसरों के लिए पहले से ही हल किए गए समस्याओं में चलने के लिए प्रवण हैं।

यदि आपका आवेदन पहले से ही jQuery का उपयोग करता है, तो आप अपने स्वयं के रोल करने के बजाय परीक्षण किए गए, बनाए रखा कोड का उपयोग कर सकते हैं, और इस सब के लिए एक तीसरे भाग के पुस्तकालय का उपयोग कर सकते हैं। jQuery के आप सुनिश्चित हैं? प्लगइन महान काम करता है, उनके डेमो पेज देखें । यह इस तरह सरल है:

<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>

कस्टम संदेश हर जगह समर्थित नहीं हैं

ध्यान दें कि फ़ायरफ़ॉक्स 4 ने इस संवाद में कस्टम संदेशों का समर्थन नहीं किया। अप्रैल 2016 तक, क्रोम 51 को रोल आउट किया जा रहा है जिसमें कस्टम संदेश भी निकाले जा रहे हैं

इस साइट पर कुछ विकल्प मौजूद हैं, लेकिन मुझे लगता है कि इस तरह का एक संवाद पर्याप्त स्पष्ट है:

क्या आप इस साइट को छोड़ना चाहते हैं?

आपके द्वारा किए गए परिवर्तन सहेजे नहीं जा सकते हैं।

Leave Stay


6
ध्यान दें कि कस्टम स्ट्रिंग्स का उपयोग करना क्रोम में अब काम नहीं करता है; chromestatus.com/feature/5349061406228480
amann

5
हां, यह मेरे उत्तर के अंतिम भाग में वर्णित है।
कोडकेस्टर

2
@Chris वह होगा क्योंकि कोणीय वर्तमान पृष्ठ से दूर नेविगेट नहीं करते हुए पृष्ठ को बदलने के लिए DOM में हेरफेर कर रहा है।
कोडकेस्टर

15
हो चेतावनी दी jQuery areYouSure 2014 (57 पर खुला मुद्दों के बाद से त्याग दिया गया है Github ), यह मेरे अनुभव से कीड़े से भरा है, यह लग सकता है जैसे कि यह पहली बार में काम करता है लेकिन कुछ त्वरित परीक्षण के बाद मैं इसे हमेशा काम नहीं करता एहसास हुआ। यह बिल्कुल भी अनुशंसित नहीं होगा
मार्क

4
@JacopoStanchi मैं दुर्भाग्य से कोई नहीं मिला। और मेरा मतलब है कि मैं काफी दिख रहा था - लेकिन यह 10 जनवरी को वापस आ गया था, इसलिए किसी ने कुछ लिखा होगा, लेकिन मुझे संदेह है। आपकी सबसे अच्छी शर्त यह है कि आप इसे स्वयं लागू करें - यह नहीं है कि आप इतना खेद सुनना चाहते हैं। (लेकिन कम से कम आपको कोई आश्चर्य नहीं होगा जैसे मैंने jQuery का उपयोग करके किया है YouSure।) इसके अलावा कौन जानता है कि आप शायद इसे खुला स्रोत भी बना सकते हैं और आपका कार्यान्वयन दूसरों के साथ साझा किया जाएगा;)
मार्क

75

जावास्क्रिप्ट onbeforeununload घटना की जाँच करें । यह Microsoft द्वारा पेश किया गया गैर-मानक जावास्क्रिप्ट है, हालांकि यह अधिकांश ब्राउज़रों में काम करता है और उनके ऑनबॉर्फ़न प्रलेखन में अधिक जानकारी और उदाहरण हैं।


3
मुझे लगता है कि यह अब मानक बन गया है। >> इवेंट मूल रूप से Microsoft द्वारा Internet Explorer 4 में पेश किया गया था और HTML5 विनिर्देशन में मानकीकृत था।
vee

34

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.
});

आप Google JQuery फॉर्म को सीरियलाइज़ कर सकते हैं, यह सभी फॉर्म इनपुट एकत्र करेगा और इसे सरणी में बचाएगा। मुझे लगता है कि यह व्याख्या पर्याप्त है :)


6
फॉर्म आईडी के रूप में #फॉर्म का उपयोग न करें क्योंकि विंडो फॉर्म नाम की वस्तु और वस्तु
बनाएगी

1
यहां देखें कि क्या यह आपके लिए काम नहीं कर रहा है: stackoverflow.com/questions/7080269/…
लेनिल मैकाफेर्री

16

सार्वभौमिक समाधान जिसमें बिना विन्यास की आवश्यकता होती है, जो सभी इनपुट संशोधन को स्वचालित रूप से पहचानता है, जिसमें संतोषप्रद तत्व शामिल हैं:

"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;
    }
});
})();

1
ठंडी फलियां। बस इस कोड को अपने परीक्षण पृष्ठ पर चिपकाएँ, एक बदलाव करें और ताज़ा करें। यह एक देशी ब्राउज़र अलर्ट प्रदर्शित करेगा जो आपको चेतावनी देता है कि आपके पास सहेजे नहीं गए परिवर्तन हैं।
लैलेंडरीकोपीकोडर

1
इसने मेरे लिए क्रोम पर 71.0.3578.98 (आधिकारिक बिल्ड) (64-बिट)
याकूब रॉसदेव

2
यह वास्तव में अच्छी तरह से काम करता है, लेकिन यदि आप इसे प्रस्तुत करने के लिए फ़ॉर्म के साथ उपयोग कर रहे हैं, तो आपको पहले संशोधित किए गए_inputs को साफ़ करना होगा अन्यथा आपको एक पुष्टि परिवर्तन चेतावनी मिलेगी। मैंने सबमिट करने के लिए कॉल करने के लिए अपने फॉर्म में एक इवेंट श्रोता को जोड़ा, और बस सेट फ़ंक्शन को स्पष्ट रूप से चलाया, इस तरह से जब मॉडिफाइड इवेंट श्रोता चलता है, तो संशोधित_इनपुट स्पष्ट है, और पोस्ट को जारी रखने की अनुमति देता है।
स्टेपक्विक

1
कूल वास्तव में कॉपी और पेस्ट करें। मेरा समय बचाने के लिए धन्यवाद। मेरे लिए Firfox 75.0 में काम
Connectify_user

1
इस स्निपेट को प्यार करें
रॉबर्नर

10

क्रमांकन का उपयोग करने के लिए वसीम ए के उत्कृष्ट विचार के शीर्ष पर निर्मित । वहां समस्या यह थी कि जब फॉर्म जमा किया जा रहा था तब चेतावनी भी दिखाई गई थी। यह यहां तय किया गया है।

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.'
        }
    });
})

यह क्रोम और IE 11 में परीक्षण किया गया है।


वसीम ए और एरिक स्वेन पूडिस्ट - थैंक्स मैंने अपने सेव बटन के लिए फॉर्म और आईडी के लिए आईडी का उपयोग किया था क्योंकि मेरे सभी बटन टाइप सबमिट थे <form action = "" id = "markform" विधि = "POST"> <td> </ type टाइप = "सबमिट" नाम = "सबमिट_बटन" आईडी = "सहेजें" मूल्य = "सहेजें"> </ td> <td> <इनपुट प्रकार = "सबमिट" नाम = "सबमिट_बटन" मान = "अगला"> </ td> और कुछ अधिक सभी प्रकार इसलिए .Submit (प्रतिस्थापित विशिष्ट क्लिक $ ( '# बचाने') द्वारा सबमिट करें क्लिक करें (function () {isSubmitting = true}) का प्रयोग करें '#marksform' के बजाय 'फॉर्म' की।
जयंत

7

पिछले उत्तरों के आधार पर, और स्टैक ओवरफ्लो में विभिन्न स्थानों से एक साथ cobbled, यहां वह समाधान है जिसके साथ मैं आया हूं जो उस मामले को संभालता है जब आप वास्तव में अपने परिवर्तनों को प्रस्तुत करना चाहते हैं:

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;

यह ध्यान देने योग्य है कि IE11 के लिए आवश्यक है कि closeEditorWarningफ़ंक्शन undefinedइसके लिए लौटता है ताकि अलर्ट न दिखाए।


यह समाधान सत्यापित नहीं करता है कि किसी भी मान को उनकी मूल स्थिति से बदल दिया गया है, इस मामले में अमान्य है कि उपयोगकर्ता इनपुट पाठ और हटाए जाने का प्रयास करने से पहले उस इनपुट पाठ को हटा देता है।
ब्रेट वेबर

अच्छी बात है, @ ब्रेट वेबर। आप उस मामले में closeEditorWarning को संशोधित कर सकते हैं, और "अगर (window.thisPage.isDirty && uiHasChanged ())", जहां uiHasChanged एक फ़ंक्शन है जो सर्वर से मूल स्थिति के बारे में जानता है, और सभी अंतरों की जांच करता है, लेकिन यह समाधान के लिए था एक ऐसा मामला जहां मैं विशेष रूप से वह सब अतिरिक्त काम नहीं करना चाहता था, और यह केवल झूठी सकारात्मकता है, जब पाठ्यपुस्तकों में वास्तविक कीपर्स बनाए गए हैं, जो मुझे लगा कि एक उचित समझौता है। :)
योनातन

नहीं QC.thisPage.isDirty = false;होना चाहिएwindow.thisPage.isDirty = false; ? इस तरह, यह जाँच करेगा कि क्या आप फ़ॉर्म जमा कर रहे हैं और चेतावनी नहीं दिखा रहे हैं। मेरे परीक्षणों के लिए काम करने लगा। इसके अलावा, अधिकांश रूपों के inputबजाय एक है textarea। मैंने निम्नलिखित का उपयोग किया जो अच्छी तरह से काम करता है:$("form").on('keyup', 'textarea,input,select', function () {
माइक

7

निम्नलिखित एक-लाइनर ने मेरे लिए काम किया है।

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

बस सेट modifiedकरने के लिए सच या झूठी अपने आवेदन की स्थिति पर निर्भर करता है।


2
कुछ सुझाव: वापसी एक कस्टम संदेश के बजाय कुछ ब्राउज़रों के रूप में एक खाली स्ट्रिंग यह (उदाहरण के लिए एज) प्रदर्शित करते हैं, और वापस आ जाएगी undefinedबजाय nullके रूप में आईई 'अशक्त' प्रिंट होगा अगर modifiedगलत है।
केविन ली

1
मोबाइल उपकरणों के बारे में कैसे? मेरी समझ यह है कि आईओएस डिवाइस ऑनब्रोफ्रनलोड का सम्मान नहीं करते हैं।
jaybro

4

निम्नलिखित कोड महान काम करता है। आपको आईडी विशेषता के माध्यम से अपने प्रपत्र तत्वों के इनपुट परिवर्तन तक पहुँचने की आवश्यकता है:

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.
            });
        });

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;

मैंने इसे एक अलग फाइल में डाला और मैंने इसे <script src = "warnOnChange.js"> </ script> के साथ शामिल किया, लेकिन जब मैं एक टेक्स्टफील्ड को संशोधित करता हूं और तब मैं एक हेडर कमांड निष्पादित करता हूं।
फेब्रीज़ियो बार्टोलोमुची

2

आप प्रपत्र मानों को क्रमबद्ध करके URL एन्कोडेड टेक्स्ट स्ट्रिंग बनाने के लिए क्रमबद्ध () का उपयोग कर सकते हैं और जाँच सकते हैं कि क्या फ़ॉर्म पहले लोड हो चुका है

$(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?'
    }
})

इस लिंक का संदर्भ लें https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form द्वारा लिखित व्लादिमीर सिदोरेंको


1
इसने काम किया, लेकिन जैसा कि कोड कॉस्टर द्वारा उत्तर दिया गया है, इस विधि के साथ कुछ खामियां हैं, इस स्पष्टीकरण को देखें stackoverflow.com/a/7317311/10555981
प्रदीप

वहाँ पहले से ही जवाब के एक जोड़े का उपयोग कर रहे हैं serialize(), और वास्तव में, इसकी कमियां हैं।
कोडकोस्टर

यह सही उत्तर होना चाहिए, उपयोग करने के लिए बहुत सरल और अपेक्षा के अनुरूप काम करता है।
२३:०४ पर जोड्सहॉप

1

@Codecaster के टी विचार को जोड़कर आप इसे हर पेज पर एक फॉर्म के साथ जोड़ सकते हैं (मेरे मामले में मैं इसे वैश्विक रूप से उपयोग करता हूं, इसलिए केवल फॉर्म में यह चेतावनी होगी) अपने फ़ंक्शन को बदलने के लिए

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

साथ ही फॉर्म जमा करें और लॉगिन बटन को रद्द करें और लिंक बटन में जमा करें, ताकि जब व्यक्ति रद्द करें या फॉर्म सबमिट करें तो हर पेज पर एक फॉर्म के साथ चेतावनी भी ट्रिगर न हो ...

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

1

आप यहाँ विस्तृत विवरण के लिए जाँच कर सकते हैं: http://techinvestigations.redexp.in/comparison-of-form-values-on-load-and-before-close/ तुलना के- फार्म मूल्यों-ऑन-लोड और -before-पास

मुख्य कोड:

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
    }


1

एरिक स्वेन पूडिस्ट द्वारा समाधान ...

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.'
        }
    });
})

... अनायास मेरे लिए एक जटिल वस्तु-उन्मुख सेटिंग में मेरे लिए आवश्यक बदलाव के बिना काम किया।

मेरे द्वारा लागू किया गया एकमात्र परिवर्तन ठोस रूप (प्रति फ़ाइल केवल एक फ़ॉर्म) को "फ़ॉर्मफ़ॉर्म" ('फ़ॉर्म' -> '#फॉर्मफ़ॉर्म') कहा जाता है:

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

विशेष रूप से अच्छी तरह से किया गया तथ्य यह है कि सबमिट बटन "अकेला छोड़ दिया" जा रहा है।

इसके अतिरिक्त, यह फ़ायरफ़ॉक्स के अंतिम संस्करण (7 फरवरी, 2019 तक) के लिए भी मेरे लिए काम करता है।


1

एली ग्रे के सार्वभौमिक समाधान का परीक्षण किया गया, केवल मैंने कोड को सरल बनाने के बाद काम किया

  '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;
      }
    });

  })();

उसके संशोधनों को हटा दिया जाता है target[defaultValue]और केवल उपयोग होता हैtarget.dataset[defaultValue] वास्तविक डिफ़ॉल्ट मान को संग्रहीत लिए जाता है।

और मैंने एक 'सहेजे गए' ईवेंट श्रोता को जोड़ा, जहाँ आपके द्वारा सहेजे गए एक्शन के सफल होने पर 'सेव' ईवेंट को स्वयं ट्रिगर किया जाएगा।

लेकिन यह 'यूनिवर्सल' समाधान केवल ब्राउज़रों में काम करता है, ऐप के वेबव्यू में काम नहीं करता है, उदाहरण के लिए, वीचैट ब्राउज़र।

यह wechat ब्राउज़रों में काम करने के लिए (आंशिक रूप से), फिर से एक और सुधार:

  '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");
    }
  })();

0

मैंने इसे अलग तरह से साझा किया, यहां साझा किया ताकि किसी को सहायता मिल सके, केवल क्रोम के साथ परीक्षण किया गया।

मैं उपयोगकर्ता को टैब बंद करने से पहले चेतावनी देना चाहता था, अगर कुछ बदलाव हो।

<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.";
    }        
};

अच्छा काम करता है, लेकिन एक और-अन्य मुद्दा मिला है, जब मैं फॉर्म जमा करता हूं तो मुझे अवांछित चेतावनी मिलती है, मैंने इस पर बहुत सारे वर्कअराउंड देखे, यह इसलिए है क्योंकि ऑनबसुमिट लोड होने से पहले ऑनब्यूमिट फायर करता है कि हम इसे ऑनसुबमिट इवेंट में क्यों नहीं संभाल सकते onbeforeunload = null, लेकिन इन दोनों घटनाओं से पहले सबमिट बटन आग की घटना पर क्लिक करें, इसलिए मैंने कोड अपडेट किया

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;
});

-5

सबसे पहले, अधिकांश ब्राउज़रों में यह फ़ंक्शन डिफ़ॉल्ट रूप से होता है। और आपको इसकी आवश्यकता क्यों है? फॉर्म को सिंक क्यों नहीं रखा जाना चाहिए? मेरा मतलब है, उपयोगकर्ता से किसी भी सबमिट किए बिना प्रतीक्षा किए किसी भी परिवर्तन पर इसे सहेजें। जैसे Google संपर्क करते हैं। निश्चित रूप से यदि केवल सभी क्षेत्र अनिवार्य हैं। उपयोगकर्ताओं को यह पसंद नहीं है कि जब वे जरूरत पड़ने पर सोचने के लिए दूर जाने के बिना कुछ भरने के लिए मजबूर करते हैं, तो उन्हें इसकी आवश्यकता होती है। :)


क्या आप सही हैं, लेकिन मेरे रूप गतिशील रूप से उत्पन्न हुए हैं और क्षेत्र मेरे नियंत्रण में नहीं हैं, इसलिए मेरे लिए यह संभव नहीं है कि सभी क्षेत्र का पता लगाएं और अजाक्स के माध्यम से अनुरोध भेजें, अगर आपके मन में कुछ है तो कृपया मेरे साथ साझा करें।
खान

ठीक है यह आपके उद्देश्यों के लिए आवश्यक नहीं हो सकता है लेकिन यह अभी भी लागू करने में सक्षम है। यदि फ़ॉर्म तत्व स्क्रीन पर हैं, तो आप अपने स्वयं के ईवेंट हैंडलर संलग्न कर सकते हैं और अपने इच्छित डेटा प्राप्त कर सकते हैं। फिर AJAX का उपयोग उस डेटा को सहेजने के लिए करें जहाँ आप कभी चाहें भले ही रूपों में आईडी या वर्ग नाम बेतरतीब ढंग से उत्पन्न हुए हों, आप XPaths का उपयोग कर सकते हैं यदि आप प्रपत्र की संरचना का अनुमान लगा सकते हैं। यह XML / HTML सही है? तो आप गतिशील रूप से उत्पन्न फ़ॉर्म के लिए ज़िम्मेदार लोगों के साथ एक JAD भी कर सकते हैं और इस बात पर बात कर सकते हैं कि इस परियोजना पर XSTL आप दोनों को कैसे लाभान्वित कर सकता है। बस एक विचार ...
साइमनड्राइव

1
save it on any change without waiting any submitting from userआप हमेशा ऐसा नहीं करना चाहते हैं। कभी-कभी उपयोगकर्ता कई बदलाव करना चाहते हैं और फिर समीक्षा करते हैं और पुष्टि करते हैं कि वे इसे बचाना चाहते हैं।
BadHorsie

1
मैंने फॉर्म जमा करने का सुझाव नहीं दिया। डेटा को स्थानीय कैश में बचाया जा सकता है, कुछ कैश में या फिर कुछ ड्राफ्ट फ्लैग के साथ जमा किया जा सकता है। इस व्यवहार के लिए कई तरीके हैं। यह उपयोगकर्ता को सचेत करने की तुलना में बहुत बेहतर है कि उसने फॉर्म समाप्त नहीं किया है और यदि वह नहीं करेगा और खिड़की को बंद कर देगा तो उसे अगली बार फिर से भरना होगा। "चलो, यार, आलसी मत बनो, तुम्हारी ट्रेन / बस / प्लेन / आदि। इससे कोई फर्क नहीं पड़ता कि हमें इस बात की परवाह नहीं है कि तुम अपने लैपटॉप से ​​चार्जर भूल गए, बस इस लानत फॉर्म को भर दो!"
युएस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.