पता लगाने के लिए सामान्य तरीका है कि क्या html फॉर्म संपादित किया गया है


94

मेरे पास एक tabbed html फॉर्म है। एक टैब से दूसरे में नेविगेट करने पर, वर्तमान टैब का डेटा (डीबी पर) कायम है, भले ही डेटा में कोई बदलाव न हो।

मैं केवल फॉर्म को संपादित करने के लिए दृढ़ता को कॉल करना चाहूंगा। फॉर्म में किसी भी तरह का नियंत्रण हो सकता है। फ़ॉर्म को गंदा करने से कुछ पाठ लिखने की ज़रूरत नहीं है, बल्कि कैलेंडर नियंत्रण में एक तारीख का चयन भी योग्य होगा।

इसे प्राप्त करने का एक तरीका डिफ़ॉल्ट रूप से रीड-ओनली मोड में फॉर्म को प्रदर्शित करना होगा और एक 'एडिट' बटन होगा और यदि उपयोगकर्ता एडिट बटन पर क्लिक करता है तो डीबी को कॉल किया जाता है (एक बार फिर, चाहे डेटा संशोधित किया गया हो (वर्तमान में जो मौजूद है, यह एक बेहतर सुधार है)।

मैं जानना चाहता हूं कि जेनेरिक जावास्क्रिप्ट फ़ंक्शन कैसे लिखना है जो यह जांच करेगा कि क्या किसी भी नियंत्रण मूल्य को संशोधित किया गया है?


क्रेग बकलर द्वारा साइटप्वाइंट पर एक दिलचस्प समाधान पोस्ट किया गया है। विशेष रुचि से, समाधान jQuery पर निर्भर नहीं करता है, और क्रॉस ब्राउज़र संगत है।
मैजिकएंडी

जवाबों:


158

शुद्ध जावास्क्रिप्ट में, यह एक आसान काम नहीं होगा, लेकिन jQuery इसे करना बहुत आसान बनाता है:

$("#myform :input").change(function() {
   $("#myform").data("changed",true);
});

फिर सहेजने से पहले, आप जांच सकते हैं कि क्या इसे बदल दिया गया था:

if ($("#myform").data("changed")) {
   // submit the form
}

ऊपर के उदाहरण में, फॉर्म में "myform" के बराबर एक आईडी है।

यदि आपको कई रूपों में इसकी आवश्यकता है, तो आप इसे आसानी से एक प्लगइन में बदल सकते हैं:

$.fn.extend({
 trackChanges: function() {
   $(":input",this).change(function() {
      $(this.form).data("changed", true);
   });
 }
 ,
 isChanged: function() { 
   return this.data("changed"); 
 }
});

तो आप बस कह सकते हैं:

$("#myform").trackChanges();

और जांचें कि क्या कोई फॉर्म बदल गया है:

if ($("#myform").isChanged()) {
   // ...
}

13
यह अच्छा और सरल है। हालाँकि यदि कोई उपयोगकर्ता एक प्रपत्र इनपुट बदलता है और फिर परिवर्तन को बदलता है (उदाहरण के लिए दो बार चेकबॉक्स पर क्लिक करके), तो प्रपत्र को संशोधित माना जाएगा। चाहे वह स्वीकार्य हो या न हो, संदर्भ पर निर्भर करता है। एक विकल्प के लिए देखें stackoverflow.com/questions/10311663/…
jlh

1
लाइव इनपुट के लिए कुछ बदलावों की जरूरत है trackChanges: function () { $(document).on('change', $(this).find(':input'), function (e) { var el = $(e.target); $(el).closest('form').data("changed", true); });
दिमुधु

36

मामले में JQuery प्रश्न से बाहर है। Google पर एक त्वरित खोज में MD5 और SHA1 हैश एल्गोरिदम के जावास्क्रिप्ट कार्यान्वयन पाए गए। यदि आप चाहते थे, तो आप सभी फॉर्म इनपुट को मिला सकते हैं और उन्हें हैश कर सकते हैं, फिर उस मान को मेमोरी में स्टोर कर सकते हैं। जब उपयोगकर्ता किया जाता है। सभी मूल्यों को फिर से मिलाएं और हैश करें। 2 हैश की तुलना करें। यदि वे समान हैं, तो उपयोगकर्ता ने कोई प्रपत्र फ़ील्ड नहीं बदला है। यदि वे अलग हैं, तो कुछ संपादित किया गया है, और आपको अपनी दृढ़ता कोड को कॉल करने की आवश्यकता है।


2
यह वही है जो मैंने इस प्रश्न के लिए अपेक्षित है, क्या कोई पुस्तकालय है?
23

यदि आपके पास सभी क्षेत्रों को समाप्‍त नहीं किया जाता है, तो क्या इसका समान परिणाम नहीं होगा, लेकिन हैश नहीं है?
ashleedawg

हां, लेकिन डेटा हैश से बड़ा हो सकता है।
जेआरजी

25

मुझे यकीन नहीं है कि मुझे आपका प्रश्न सही मिलेगा, लेकिन addEventListener के बारे में क्या? यदि आप IE8 समर्थन के बारे में बहुत ज्यादा परवाह नहीं करते हैं तो यह ठीक होना चाहिए। निम्नलिखित कोड मेरे लिए काम कर रहा है:

var form = document.getElementById("myForm");

form.addEventListener("input", function () {
    console.log("Form has changed!");
});

मेरी जरूरतों के लिए एकदम सही
आशीर्वाद

8

इसे प्राप्त करने का दूसरा तरीका यह है कि फॉर्म को क्रमबद्ध करें:

$(function() {
    var $form = $('form');
    var initialState = $form.serialize();
    
    $form.submit(function (e) {
      if (initialState === $form.serialize()) {
        console.log('Form is unchanged!');
      } else {
        console.log('Form has changed!');
      }
      e.preventDefault();
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
Field 1: <input type="text" name="field_1" value="My value 1"> <br>
Field 2: <input type="text" name="field_2" value="My value 2"> <br>
Check: <input type="checkbox" name="field_3" value="1"><br>
<input type="submit">
</form>


मुझे पसंद है कि आप कैसे सोच रहे हैं, खासकर यदि आप jQuery को चीर कर वैनिला जावास्क्रिप्ट के साथ करते हैं। मुझे लगता है कि सवाल यह था कि jQuery उपलब्ध था, लेकिन कोई और अधिक व्यापक रूप से लागू समाधान नहीं होने का कारण है, इस तरह की टिप्पणियों के साथ।
Ruffin

4

यहां बताया गया है कि मैंने यह कैसे किया (jQuery का उपयोग किए बिना)।

मेरे मामले में, मैं चाहता था कि एक विशेष रूप तत्व को गिना न जाए, क्योंकि यह वह तत्व था जिसने चेक को ट्रिगर किया और इसलिए हमेशा बदल जाएगा। असाधारण तत्व का नाम 'Report_period' रखा गया है और 'hasFormChanged ()' फ़ंक्शन में हार्ड-कोडित है।

परीक्षण करने के लिए, एक फ़ंक्शन को कॉल करें "changeReportingPeriod ()", जिसे आप शायद कुछ और नाम देना चाहते हैं।

महत्वपूर्ण: जब आप मानों को उनके मूल मूल्यों (आमतौर पर पृष्ठ लोड पर, लेकिन मेरे मामले में नहीं) पर सेट किया गया हो, तो आपको सेट करना होगा।

नोट: मैं यह दावा नहीं करता कि यह एक सुरुचिपूर्ण समाधान है, वास्तव में मैं सुरुचिपूर्ण जावास्क्रिप्ट समाधानों में विश्वास नहीं करता। जावास्क्रिप्ट में मेरा व्यक्तिगत जोर पठनीयता पर है, संरचनात्मक लालित्य पर नहीं (जैसे कि जावास्क्रिप्ट में संभव था)। मैं जावास्क्रिप्ट लिखने के दौरान फ़ाइल आकार के साथ अपने आप को चिंता नहीं करता हूं क्योंकि यही वह गज़िप है, और अधिक कॉम्पैक्ट जावास्क्रिप्ट कोड लिखने की कोशिश करने से रखरखाव के साथ असहनीय समस्याएं होती हैं। मैं कोई माफी नहीं देता, कोई पश्चाताप व्यक्त नहीं करता और इस पर बहस करने से इनकार करता हूं। यह जावास्क्रिप्ट है। क्षमा करें, मुझे खुद को समझाने के लिए यह स्पष्ट करना पड़ा कि मुझे पोस्टिंग को परेशान करना चाहिए। खुश रहो! :)


    var initial_values = new Array();

    // Gets all form elements from the entire document.
    function getAllFormElements() {
        // Return variable.
        var all_form_elements = Array();

        // The form.
        var form_activity_report = document.getElementById('form_activity_report');

        // Different types of form elements.
        var inputs = form_activity_report.getElementsByTagName('input');
        var textareas = form_activity_report.getElementsByTagName('textarea');
        var selects = form_activity_report.getElementsByTagName('select');

        // We do it this way because we want to return an Array, not a NodeList.
        var i;
        for (i = 0; i < inputs.length; i++) {
            all_form_elements.push(inputs[i]);
        }
        for (i = 0; i < textareas.length; i++) {
            all_form_elements.push(textareas[i]);
        }
        for (i = 0; i < selects.length; i++) {
            all_form_elements.push(selects[i]);
        }

        return all_form_elements;
    }

    // Sets the initial values of every form element.
    function setInitialFormValues() {
        var inputs = getAllFormElements();
        for (var i = 0; i < inputs.length; i++) {
            initial_values.push(inputs[i].value);
        }
    }

    function hasFormChanged() {
        var has_changed = false;
        var elements = getAllFormElements();

        for (var i = 0; i < elements.length; i++) {
            if (elements[i].id != 'reporting_period' && elements[i].value != initial_values[i]) {
                has_changed = true;
                break;
            }
        }

        return has_changed;
    }

    function changeReportingPeriod() {
        alert(hasFormChanged());
    }



3

बिना jQuery के देशी जावास्क्रिप्ट में आसानी से परिवर्तन का पता लगाया जा सकता है:

function initChangeDetection(form) {
  Array.from(form).forEach(el => el.dataset.origValue = el.value);
}
function formHasChanges(form) {
  return Array.from(form).some(el => 'origValue' in el.dataset && el.dataset.origValue !== el.value);
}


initChangeDetection()सुरक्षित रूप से आपके पृष्ठ के जीवनचक्र में कई बार कॉल किया जा सकता है: JSBin पर परीक्षण देखें


पुराने ब्राउज़रों के लिए जो नए तीर / सरणी फ़ंक्शन का समर्थन नहीं करते हैं:

function initChangeDetection(form) {
  for (var i=0; i<form.length; i++) {
    var el = form[i];
    el.dataset.origValue = el.value;
  }
}
function formHasChanges(form) {
  for (var i=0; i<form.length; i++) {
    var el = form[i];
    if ('origValue' in el.dataset && el.dataset.origValue !== el.value) {
      return true;
    }
  }
  return false;
}

हमेशा मेरे फॉर्म के लिए सच है
रिच स्टोन

क्या आप अपना फॉर्म JSBin या Gist पर पोस्ट कर सकते हैं ताकि हम आपके फॉर्म को देख सकें?
एंथुमक्रिस

मेरी गलती है, मैंने आपके उदाहरण के रूप में जेएससी के साथ फॉर्म का चयन किया और जेएस के साथ नहीं। यह क्रमिक अधिभार के बिना एक अच्छा और साफ js समाधान है। धन्यवाद!
रिच स्टोन

2

यहाँ देशी जावास्क्रिप्ट में एक पॉलीफ़िल पद्धति का डेमो है जो FormData()एपीआई को निर्मित, अद्यतन और हटाए गए प्रपत्र प्रविष्टियों का पता लगाने के लिए उपयोग करता है । आप जाँच कर सकते हैं कि क्या कुछ का उपयोग करके बदला गया था HTMLFormElement#isChangedऔर किसी ऑब्जेक्ट को रीसेट फॉर्म से अंतर वाले ऑब्जेक्ट का उपयोग करके प्राप्त करें HTMLFormElement#changes(यह मानते हुए कि वे इनपुट नाम से नकाबपोश नहीं हैं:

Object.defineProperties(HTMLFormElement.prototype, {
  isChanged: {
    configurable: true,
    get: function isChanged () {
      'use strict'

      var thisData = new FormData(this)
      var that = this.cloneNode(true)

      // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
      HTMLFormElement.prototype.reset.call(that)

      var thatData = new FormData(that)

      const theseKeys = Array.from(thisData.keys())
      const thoseKeys = Array.from(thatData.keys())

      if (theseKeys.length !== thoseKeys.length) {
        return true
      }

      const allKeys = new Set(theseKeys.concat(thoseKeys))

      function unequal (value, index) {
        return value !== this[index]
      }

      for (const key of theseKeys) {
        const theseValues = thisData.getAll(key)
        const thoseValues = thatData.getAll(key)

        if (theseValues.length !== thoseValues.length) {
          return true
        }

        if (theseValues.some(unequal, thoseValues)) {
          return true
        }
      }

      return false
    }
  },
  changes: {
    configurable: true,
    get: function changes () {
      'use strict'

      var thisData = new FormData(this)
      var that = this.cloneNode(true)

      // avoid masking: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reset
      HTMLFormElement.prototype.reset.call(that)

      var thatData = new FormData(that)

      const theseKeys = Array.from(thisData.keys())
      const thoseKeys = Array.from(thatData.keys())

      const created = new FormData()
      const deleted = new FormData()
      const updated = new FormData()

      const allKeys = new Set(theseKeys.concat(thoseKeys))

      function unequal (value, index) {
        return value !== this[index]
      }

      for (const key of allKeys) {
        const theseValues = thisData.getAll(key)
        const thoseValues = thatData.getAll(key)

        const createdValues = theseValues.slice(thoseValues.length)
        const deletedValues = thoseValues.slice(theseValues.length)

        const minLength = Math.min(theseValues.length, thoseValues.length)

        const updatedValues = theseValues.slice(0, minLength).filter(unequal, thoseValues)

        function append (value) {
          this.append(key, value)
        }

        createdValues.forEach(append, created)
        deletedValues.forEach(append, deleted)
        updatedValues.forEach(append, updated)
      }

      return {
        created: Array.from(created),
        deleted: Array.from(deleted),
        updated: Array.from(updated)
      }
    }
  }
})

document.querySelector('[value="Check"]').addEventListener('click', function () {
  if (this.form.isChanged) {
    console.log(this.form.changes)
  } else {
    console.log('unchanged')
  }
})
<form>
  <div>
    <label for="name">Text Input:</label>
    <input type="text" name="name" id="name" value="" tabindex="1" />
  </div>

  <div>
    <h4>Radio Button Choice</h4>

    <label for="radio-choice-1">Choice 1</label>
    <input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1" />

    <label for="radio-choice-2">Choice 2</label>
    <input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2" />
  </div>

  <div>
    <label for="select-choice">Select Dropdown Choice:</label>
    <select name="select-choice" id="select-choice">
      <option value="Choice 1">Choice 1</option>
      <option value="Choice 2">Choice 2</option>
      <option value="Choice 3">Choice 3</option>
    </select>
  </div>

  <div>
    <label for="textarea">Textarea:</label>
    <textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
  </div>

  <div>
    <label for="checkbox">Checkbox:</label>
    <input type="checkbox" name="checkbox" id="checkbox" />
  </div>

  <div>
    <input type="button" value="Check" />
  </div>
</form>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.