2008-10-01 22 views
79

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

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

+0

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

+0

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

+0

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

उत्तर

83

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

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

के रूप में आवश्यक onunload/onbeforeunload तरीकों के साथ मिलाएं।

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

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

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

+30

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

+2

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

+5

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

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

और codebehind में, इनपुट क्षेत्रों के लिए चलाता जोड़ने फिर सेट करता है और साथ ही है प्रस्तुत करने पर/सरणियों का उपयोग कर चर धारण करने के लिए इतना परिवर्तन ट्रैक किया जा सकता रद्द बटन ....

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

One method,।

detect changes पर एक बहुत ही सरल विधि है, लेकिन शेष सुरुचिपूर्ण नहीं है।

एक और तरीका है जो काफी सरल और छोटा है, 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> 
41

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

/** 
* 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; 
} 

And another:

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

आप शायद भी LIBRARY_OF_CHOICE की घटना पंजीकरण का उपयोग करने के beforeunload ईवेंट हैंडलर के पंजीकरण बदलने के लिए चाहता हूँ।

+0

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

+0

क्या यह सूची बॉक्स के लिए काम करता है (ली टैग)? – Phil

+0

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

7

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

हालांकि कुछ चेतावनी हैं, खासकर जब एएसपी से निपटने पर।नेट एप्लिकेशन:

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

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

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

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

1

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

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

निम्नलिखित किसी भी बदलाव ईवेंट को कैप्चर करने के लिए ब्राउज़र के ऑनबेरनलोड लोड और 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; 
+0

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

2

मैं ऊपर Slace के सुझाव पर विस्तार, सबसे संपादन योग्य तत्वों और भी छोड़कर कुछ तत्वों के कारण गंदा ध्वज स्थापित किया जाना से ("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.'; 
      } 
     });   

4

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

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

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

5

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

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

इसे आजमाएं: 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

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

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;

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

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

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

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

विशेषताएं:

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

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

+0

एचटीएमएल कक्षाओं का उपयोग करने का विचार प्रत्येक फॉर्म के साथ 'गंदे' विशेषता को संलग्न करना है क्योंकि आप सामान्य एप्लिकेशन-विज़ जेएस/एचटीएमएल समाधान बनाने के लिए चर का उपयोग नहीं कर सकते हैं। – MhdSyrwan

+0

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

0

आईई दस्तावेज़ में। पहले से ही ठीक से काम नहीं करेगा यह इनपुट के मानों को अपडेट करेगा।

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

नीचे कोड है जो आपको दस्तावेज़ के अंदर रखना चाहिए। पहले से ही फ़ंक्शन।

$(document).ready(function() { 
    $(window).bind("load", function() { 
    $("input, select").change(function() {}); 
    }); 
}); 
संबंधित मुद्दे