अनर्गल परिवर्तन का पता लगाना


94

मुझे एक एएसपी .नेट अनुप्रयोग में "अनसोल्ड चेंजेस" प्रॉम्प्ट को लागू करने की आवश्यकता है। यदि कोई उपयोगकर्ता वेब फ़ॉर्म पर नियंत्रण को संशोधित करता है, और सहेजने से पहले नेविगेट करने का प्रयास करता है, तो एक प्रॉम्प्ट उन्हें चेतावनी दे सकता है कि उनके पास सहेजे नहीं गए परिवर्तन हैं, और उन्हें वर्तमान पृष्ठ पर रद्द करने और रहने का विकल्प देता है। यदि उपयोगकर्ता ने किसी भी नियंत्रण को नहीं छुआ है, तो संकेत को प्रदर्शित नहीं करना चाहिए।

आदर्श रूप से मैं इसे जावास्क्रिप्ट में लागू करना चाहूंगा, लेकिन इससे पहले कि मैं अपना कोड रोल करने का रास्ता तय करूं, क्या इसे प्राप्त करने के लिए कोई मौजूदा रूपरेखा या अनुशंसित डिज़ाइन पैटर्न हैं? आदर्श रूप से मैं कुछ ऐसा चाहूंगा जिसे आसानी से न्यूनतम बदलाव के साथ कई पृष्ठों में पुन: उपयोग किया जा सके।


मुझे उसी में दिलचस्पी है, बस asp.net के लिए नहीं, लेकिन मुझे लगता है कि वहाँ एक सामान्य समाधान है।
माइकल निले

नीचे दिए गए समाधान को सादे HTML / जावास्क्रिप्ट में उपयोग किया जा सकता है। एचटीएमएल टैग में विशेषताओं के लिए बस "कोडबेहिंद" को बदलें।
वेन

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

जवाबों:


96

JQuery का उपयोग करना:

var _isDirty = false;
$("input[type='text']").change(function(){
  _isDirty = true;
});
// replicate for other input types and selects

आवश्यकतानुसार onunload/ onbeforeunloadविधियों के साथ मिलाएं ।

टिप्पणियों से, निम्नलिखित सभी इनपुट फ़ील्ड्स, कोड को डुप्लिकेट किए बिना:

$(':input').change(function () {

का उपयोग करना $(":input")सभी इनपुट, टेक्स्टारिया, चयन और बटन तत्वों को संदर्भित करता है।


32
Upvote क्योंकि मैंने इस समाधान का उपयोग किया है लेकिन थोड़ा आसान तरीका है। यदि आप उपयोग करते हैं: $ (': इनपुट')। परिवर्तन (फ़ंक्शन () {फिर जो सभी इनपुट फ़ील्ड के लिए काम करता है, आपको अन्य इनपुट प्रकारों के लिए दोहराने की आवश्यकता नहीं है। $ (": इनपुट") सभी इनपुट, टेक्सटारिया का चयन करता है। , चयन और बटन तत्व।
कोडकंबर

5
मुझे लगता है कि फ़ायरफ़ॉक्स में यह समस्या हो सकती है। यदि कोई उपयोगकर्ता फ़ॉर्म को संशोधित करता है, तो ब्राउज़र रीफ़्रेश-बटन पर क्लिक करता है, तो पृष्ठ फिर से लोड किया जाएगा और फ़ायरफ़ॉक्स उपयोगकर्ताओं को पिछली प्रविष्टियों के साथ फ़ॉर्म को पॉप्युलेट करेगा - परिवर्तन-घटना को फायर किए बिना। अब फॉर्म गंदा होगा, लेकिन झंडा तब तक सेट नहीं किया जाएगा, जब तक उपयोगकर्ता दूसरा एडिट नहीं करता।
Oskar Berggren 16

8
बस एक संकेत है। यदि फ़ॉर्म गंदा है, तो इसका मतलब यह नहीं है कि इसमें वास्तव में परिवर्तित डेटा है। बेहतर प्रयोज्य के लिए आपको वास्तव में पुराने डेटा की तुलना नए के साथ करनी होगी;)
स्लाव फोमिन II

ध्यान रखें कि changeटेक्स्ट-इनपुट के लिए एक बार फोकस छोड़ने / खोने पर inputट्रिगर होता है , जबकि प्रत्येक कीस्ट्रोक के लिए ट्रिगर होता है। (मैं आमतौर पर changeJQuery के साथ प्रयोग करते हैं one(), ताकि कई घटनाओं को रोका जा सके।)
SpazzMarticus

46

पहेली का एक टुकड़ा:

/**
 * Determines if a form is dirty by comparing the current value of each element
 * with its default value.
 *
 * @param {Form} form the form to be checked.
 * @return {Boolean} <code>true</code> if the form is dirty, <code>false</code>
 *                   otherwise.
 */
function formIsDirty(form) {
  for (var i = 0; i < form.elements.length; i++) {
    var element = form.elements[i];
    var type = element.type;
    if (type == "checkbox" || type == "radio") {
      if (element.checked != element.defaultChecked) {
        return true;
      }
    }
    else if (type == "hidden" || type == "password" ||
             type == "text" || type == "textarea") {
      if (element.value != element.defaultValue) {
        return true;
      }
    }
    else if (type == "select-one" || type == "select-multiple") {
      for (var j = 0; j < element.options.length; j++) {
        if (element.options[j].selected !=
            element.options[j].defaultSelected) {
          return true;
        }
      }
    }
  }
  return false;
}

और दूसरा :

window.onbeforeunload = function(e) {
  e = e || window.event;  
  if (formIsDirty(document.forms["someForm"])) {
    // For IE and Firefox
    if (e) {
      e.returnValue = "You have unsaved changes.";
    }
    // For Safari
    return "You have unsaved changes.";
  }
};

यह सब लपेटो, और तुम्हें क्या मिलता है?

var confirmExitIfModified = (function() {
  function formIsDirty(form) {
    // ...as above
  }

  return function(form, message) {
    window.onbeforeunload = function(e) {
      e = e || window.event;
      if (formIsDirty(document.forms[form])) {
        // For IE and Firefox
        if (e) {
          e.returnValue = message;
        }
        // For Safari
        return message;
      }
    };
  };
})();

confirmExitIfModified("someForm", "You have unsaved changes.");

आप संभवतः beforeunloadईवेंट हैंडलर के पंजीकरण को भी बदलना चाहते हैं LIBRARY_OF_CHOICE


फ़ायरफ़ॉक्स 9.0.1 में मुझे कोई संदेश नहीं मिला। मेरे पास एक डिफ़ॉल्ट संदेश है, "क्या आप सुनिश्चित हैं कि आप पृष्ठ को छोड़ना चाहते हैं? कुछ डेटा खो सकता है" (यह मेरे गैर-अंग्रेजी ब्राउज़र संदेश का अनुवाद कम या ज्यादा है)
रोमेन गाइडॉउक्स

1
यह स्क्रिप्ट कमाल की है, लेकिन मेरे लिए इसने मेरे फॉर्म सबमिट करने पर चेतावनी संदेश भी प्रदर्शित किया। मैंने इसे ऑनक्लिक ( onclick="window.onbeforeunload=null")
जोस्ट

1
मुझे एक गंदा बिट सेट करने के बजाय डिफ़ॉल्ट वाल्यू आदि गुणों की तुलना करने का दृष्टिकोण पसंद है। इसका मतलब यह है कि यदि कोई फ़ील्ड बदलता है, तो उसे वापस बदल देता है, तो प्रपत्र गंदे के रूप में रिपोर्ट नहीं करेगा।
15

धन्यवाद, यह बहुत अच्छा है। क्या आप हमें बता सकते हैं कि कैसे jquery के लिए पंजीकरण करें? जब तक मेरे पास एक ही html पृष्ठ पर यह स्क्रिप्ट नहीं है, तब तक यह आग नहीं करता है। अगर मेरे पास यह एक बाहरी .js फ़ाइल के अंदर है, तो यह काम नहीं करता है।
शिव नारु

17

.Aspx पृष्ठ में, आपको यह बताने के लिए एक जावास्क्रिप्ट फ़ंक्शन की आवश्यकता है कि फॉर्म की जानकारी "गंदी" है या नहीं

<script language="javascript">
    var isDirty = false;

    function setDirty() {
        isDirty = true;
    }

    function checkSave() {
        var sSave;
        if (isDirty == true) {
            sSave = window.confirm("You have some changes that have not been saved. Click OK to save now or CANCEL to continue without saving.");
            if (sSave == true) {
                document.getElementById('__EVENTTARGET').value = 'btnSubmit';
                document.getElementById('__EVENTARGUMENT').value = 'Click';  
                window.document.formName.submit();
            } else {
                 return true;
            }
        }
    }
</script>
<body class="StandardBody" onunload="checkSave()">

और कोडबेहिंड में, ट्रिगर्स को इनपुट फ़ील्ड के साथ-साथ सबमिशन / रद्द बटन पर रीसेट करें…।

btnSubmit.Attributes.Add("onclick", "isDirty = 0;");
btnCancel.Attributes.Add("onclick", "isDirty = 0;");
txtName.Attributes.Add("onchange", "setDirty();");
txtAddress.Attributes.Add("onchange", "setDirty();");
//etc..

9

निम्नलिखित किसी भी onchange घटना को पकड़ने के लिए ब्राउज़र के onbeforeunload फ़ंक्शन और jquery का उपयोग करता है। आईटी किसी भी सबमिट या रीसेट बटन की तलाश करता है ताकि ध्वज में बदलाव को इंगित करने के लिए रीसेट किया जा सके।

dataChanged = 0;     // global variable flags unsaved changes      

function bindForChange(){    
     $('input,checkbox,textarea,radio,select').bind('change',function(event) { dataChanged = 1})
     $(':reset,:submit').bind('click',function(event) { dataChanged = 0 })
}


function askConfirm(){  
    if (dataChanged){ 
        return "You have some unsaved changes.  Press OK to continue without saving." 
    }
}

window.onbeforeunload = askConfirm;
window.onload = bindForChange;

जब मैं एक चेक बॉक्स रखता था तो हाय कॉलिन रीसेट काम नहीं करता था, शुरू में मैंने इसे चेक किया और फिर से अनचेक किया लेकिन सतर्कता बरती जा रही है, जब उपयोगकर्ता चेक बॉक्स को अनचेक करता है तो मैं कैसे रीसेट कर सकता हूं
डेवलपर

8

जवाब देने के लिए सभी का शुक्रिया। मैंने JQuery और प्रोटेक्ट-डेटा प्लग-इन का उपयोग करके एक समाधान लागू करना समाप्त कर दिया । यह मुझे एक पृष्ठ पर सभी नियंत्रणों पर स्वचालित रूप से निगरानी लागू करने की अनुमति देता है।

हालाँकि, कुछ एएसपी के साथ काम कर रहे हैं, खासकर जब।

  • जब कोई उपयोगकर्ता रद्द विकल्प चुनता है, तो doPostBack फ़ंक्शन जावास्क्रिप्ट त्रुटि को फेंक देगा। मुझे मैन्युअल रूप से इसे दबाने के लिए doPostBack के भीतर .submit कॉल के चारों ओर एक ट्राइ-कैच डालना पड़ा।

  • कुछ पृष्ठों पर, एक उपयोगकर्ता एक कार्रवाई कर सकता है जो एक ही पृष्ठ पर एक पोस्टबैक करता है, लेकिन एक बचत नहीं है। यह किसी भी जावास्क्रिप्ट लॉजिक रीसेटिंग में परिणत होता है, इसलिए यह सोचता है कि पोस्टबैक के बाद कुछ भी नहीं बदला है जब कुछ हो सकता है। मुझे एक छिपे हुए टेक्स्टबॉक्स को लागू करना था जो पेज के साथ वापस पोस्ट हो जाता है, और इसका उपयोग साधारण बूलियन मान रखने के लिए किया जाता है जो यह दर्शाता है कि डेटा गंदा है। यह पोस्टबैक के बाद बनी रहती है।

  • आप डायलॉग को ट्रिगर नहीं करने के लिए पेज पर कुछ पोस्टबैक चाह सकते हैं, जैसे कि सेव बटन। इस स्थिति में, आप JQuery का उपयोग OnClick फ़ंक्शन को जोड़ने के लिए कर सकते हैं, जो null में window.onbeforeunload सेट करता है।

उम्मीद है कि यह किसी और के लिए मददगार हो, जिसे कुछ इसी तरह लागू करना है।


7

सामान्य समाधान दिए गए पृष्ठ में कई रूपों का समर्थन करना ( बस अपनी परियोजना में कॉपी और पेस्ट करें )

$(document).ready(function() {
    $('form :input').change(function() {
        $(this).closest('form').addClass('form-dirty');
    });

    $(window).bind('beforeunload', function() {
        if($('form:not(.ignore-changes).form-dirty').length > 0) {
            return 'You have unsaved changes, are you sure you want to discard them?';
        }
    });

    $('form').bind('submit',function() {
        $(this).closest('form').removeClass('form-dirty');
        return true;
    });
});

नोट: यह समाधान सामान्य एकीकृत समाधान बनाने के लिए दूसरों के समाधान से संयुक्त है।

विशेषताएं:

  • बस अपने ऐप में कॉपी और पेस्ट करें।
  • एकाधिक रूपों का समर्थन करता है।
  • आप शैली को गंदा कर सकते हैं या कार्रवाई कर सकते हैं, क्योंकि उनके पास "फॉर्म-गंदा" वर्ग है।
  • आप 'रूप-परिवर्तन' वर्ग को जोड़कर कुछ रूपों को बाहर कर सकते हैं।

यह अच्छी तरह से काम करता है, लेकिन मैं _isDirtyएरॉन पॉवेल द्वारा वर्णित चर के साथ जोड़े गए वर्गों को प्रतिस्थापित करता हूं । मुझे जावास्क्रिप्ट में चर के बजाय HTML से कक्षाएं जोड़ने और हटाने की आवश्यकता नहीं दिखी।
मार्टिन

1
यहाँ html वर्गों का उपयोग करने का विचार प्रत्येक प्रपत्र के साथ 'गंदे' विशेषता को संलग्न करना है क्योंकि आप सामान्य अनुप्रयोग-ws js / html समाधान बनाने के लिए चर का उपयोग नहीं कर सकते हैं।
मद्धिसवान

1
दूसरे शब्दों में, एक चर का उपयोग केवल एक ही रूप में काम करेगा, अन्यथा आपको गंदे झंडे की एक सरणी की आवश्यकता होगी जो समाधान को और अधिक जटिल बना देगा।
मद्धिसवान

1
उस बिंदु को समझाने के लिए धन्यवाद। मेरी जरूरत केवल एक ही फॉर्म पेज के साथ थी।
मार्टिन

6

निम्नलिखित समाधान प्रोटोटाइप के लिए काम करता है (एफएफ, आईई 6 और सफारी में परीक्षण)। यह एक जेनेरिक फॉर्म ऑब्जर्वर (जो आग का रूप लेता है: फॉर्म के किसी भी क्षेत्र को संशोधित किए जाने पर बदल जाता है) का उपयोग करता है, जिसे आप अन्य सामान के लिए भी उपयोग कर सकते हैं।

/* use this function to announce changes from your own scripts/event handlers.
 * Example: onClick="makeDirty($(this).up('form'));"
 */
function makeDirty(form) {
    form.fire("form:changed");
}

function handleChange(form, event) {
    makeDirty(form);
}

/* generic form observer, ensure that form:changed is being fired whenever
 * a field is being changed in that particular for
 */
function setupFormChangeObserver(form) {
    var handler = handleChange.curry(form);

    form.getElements().each(function (element) {
        element.observe("change", handler);
    });
}

/* installs a form protector to a form marked with class 'protectForm' */
function setupProtectForm() {
    var form = $$("form.protectForm").first();

    /* abort if no form */
    if (!form) return;

    setupFormChangeObserver(form);

    var dirty = false;
    form.observe("form:changed", function(event) {
        dirty = true;
    });

    /* submitting the form makes the form clean again */
    form.observe("submit", function(event) {
        dirty = false;
    });

    /* unfortunatly a propper event handler doesn't appear to work with IE and Safari */
    window.onbeforeunload = function(event) {
        if (dirty) {
            return "There are unsaved changes, they will be lost if you leave now.";
        }
    };
}

document.observe("dom:loaded", setupProtectForm);

6

यहाँ एक जावास्क्रिप्ट / jquery समाधान है जो सरल है। यह उपयोगकर्ता द्वारा "पूर्ववत" के लिए खाता है, यह अनुप्रयोग में आसानी के लिए एक फ़ंक्शन के भीतर समझाया गया है, और यह सबमिट करने पर निराश नहीं करता है। बस फ़ंक्शन को कॉल करें और अपने फॉर्म की आईडी पास करें।

यह फ़ंक्शन पृष्ठ को लोड करने के बाद एक बार प्रपत्र को क्रमबद्ध करता है, और उपयोगकर्ता द्वारा पृष्ठ छोड़ने से पहले फिर से। यदि दो फॉर्म स्टेट्स अलग हैं, तो प्रॉम्प्ट दिखाया गया है।

इसे आज़माएं: http://jsfiddle.net/skibulk/Ydt7Y/

function formUnloadPrompt(formSelector) {
    var formA = $(formSelector).serialize(), formB, formSubmit = false;

    // Detect Form Submit
    $(formSelector).submit( function(){
        formSubmit = true;
    });

    // Handle Form Unload    
    window.onbeforeunload = function(){
        if (formSubmit) return;
        formB = $(formSelector).serialize();
        if (formA != formB) return "Your changes have not been saved.";
    };
}

$(function(){
    formUnloadPrompt('form');
});

2
मैंने आपके दृष्टिकोण की कोशिश की। यह क्रोम और फ़ायरफ़ॉक्स के लिए काम करता है, लेकिन यह Ipad मिनी पर सफारी के लिए काम नहीं कर सकता है ..
दिमित्री के

4

मैंने हाल ही में एक ओपन सोर्स jQuery प्लगइन में योगदान दिया है जिसे गंदाफॉर्म कहा जाता है ।

प्लगइन को गतिशील रूप से जोड़े गए HTML के साथ काम करने के लिए डिज़ाइन किया गया है, कई रूपों का समर्थन करता है, वस्तुतः किसी भी डायलॉग फ्रेमवर्क का समर्थन कर सकता है, पहले से डायलॉग ब्राउज़र पर वापस आता है, कस्टम एडिटर्स से एक गंदे स्थिति को प्राप्त करने के लिए एक प्लग करने योग्य सहायक फ्रेमवर्क है (एक LittleMCE प्लगइन शामिल है) , iFrames के भीतर काम करता है, और गंदी स्थिति को इच्छा पर सेट या रीसेट किया जा सकता है।

https://github.com/snikch/jquery.dirtyforms


4

JQuery का उपयोग करने के साथ परिवर्तन का पता लगाना बहुत सरल है:

var formInitVal = $('#formId').serialize(); // detect form init value after form is displayed

// check for form changes
if ($('#formId').serialize() != formInitVal) {
    // show confirmation alert
}

2

मैंने सबसे अधिक संपादन तत्वों को शामिल करने के लिए, और कुछ तत्वों को छोड़कर, जिसमें गंदे झंडे को सेट करने के लिए "srSearch" कहा जाता है) के साथ स्लूस के सुझाव का विस्तार किया।

<script type="text/javascript">
        var _isDirty = false;
        $(document).ready(function () {            

            // Set exclude CSS class on radio-button list elements
            $('table.srSearch input:radio').addClass("srSearch");

            $("input[type='text'],input[type='radio'],select,textarea").not(".srSearch").change(function () {
                _isDirty = true;
            });
        });

        $(window).bind('beforeunload', function () {
            if (_isDirty) {
                return 'You have unsaved changes.';
            }
        });        


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


1

यह वही है जो फ्लेगिक्स। जेएस प्लगइन fleegix.form.diff(http://js.fleegix.org/plugins/form/diff ) के लिए बनाया गया था। लोड का उपयोग करके फॉर्म की प्रारंभिक स्थिति को सीरियलाइज़ करें fleegix.form.toObject(http://js.fleegix.org/ref#fleegix.form.toObject ) और इसे एक वैरिएबल में सेव करें, फिर वर्तमान स्थिति की तुलना fleegix.form.diffअनलोड पर करके करें। बहुत आसान।


0

एक विधि , चर का उपयोग करने के लिए सरणियों का उपयोग करके ताकि परिवर्तनों को ट्रैक किया जा सके।

यहां परिवर्तनों का पता लगाने के लिए एक बहुत ही सरल तरीका है , लेकिन बाकी उतना सुरुचिपूर्ण नहीं है।

एक और तरीका है जो Farfetched Blog से काफी सरल और छोटा है :

<body onLoad="lookForChanges()" onBeforeUnload="return warnOfUnsavedChanges()">
<form>
<select name=a multiple>
 <option value=1>1
 <option value=2>2
 <option value=3>3
</select>
<input name=b value=123>
<input type=submit>
</form>

<script>
var changed = 0;
function recordChange() {
 changed = 1;
}
function recordChangeIfChangeKey(myevent) {
 if (myevent.which && !myevent.ctrlKey && !myevent.ctrlKey)
  recordChange(myevent);
}
function ignoreChange() {
 changed = 0;
}
function lookForChanges() {
 var origfunc;
 for (i = 0; i < document.forms.length; i++) {
  for (j = 0; j < document.forms[i].elements.length; j++) {
   var formField=document.forms[i].elements[j];
   var formFieldType=formField.type.toLowerCase();
   if (formFieldType == 'checkbox' || formFieldType == 'radio') {
    addHandler(formField, 'click', recordChange);
   } else if (formFieldType == 'text' || formFieldType == 'textarea') {
    if (formField.attachEvent) {
     addHandler(formField, 'keypress', recordChange);
    } else {
     addHandler(formField, 'keypress', recordChangeIfChangeKey);
    }
   } else if (formFieldType == 'select-multiple' || formFieldType == 'select-one') {
    addHandler(formField, 'change', recordChange);
   }
  }
  addHandler(document.forms[i], 'submit', ignoreChange);
 }
}
function warnOfUnsavedChanges() {
 if (changed) {
  if ("event" in window) //ie
   event.returnValue = 'You have unsaved changes on this page, which will be discarded if you leave now. Click "Cancel" in order to save them first.';
  else //netscape
   return false;
 }
}
function addHandler(target, eventName, handler) {
 if (target.attachEvent) {
  target.attachEvent('on'+eventName, handler);
 } else {
  target.addEventListener(eventName, handler, false);
 }
}
</script>

0

IE में। पहले से ही ठीक से काम नहीं करेगा यह इनपुट के मूल्यों को अद्यतन करेगा।

इसलिए हमें डॉक्यूमेंट के अंदर लोड घटना को बांधने की जरूरत है। पहले से ही फ़ंक्शन जो IE ब्राउज़र के लिए भी संभाल लेगा।

नीचे वह कोड है जिसे आपको डॉक्यूमेंट के अंदर डालना चाहिए।

 $(document).ready(function () {
   $(window).bind("load", function () { 
    $("input, select").change(function () {});
   });
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.