programing

html 양식 편집 여부를 탐지하는 일반적인 방법

javajsp 2023. 11. 5. 11:01

html 양식 편집 여부를 탐지하는 일반적인 방법

저는 HTML 양식을 탭으로 작성했습니다.한 탭에서 다른 탭으로 이동하면 데이터에 변경 사항이 없더라도 현재 탭의 데이터가 (DB에) 유지됩니다.

양식이 수정된 경우에만 지속 통화를 하고 싶습니다.양식에는 모든 종류의 컨트롤이 포함될 수 있습니다.일부 텍스트를 입력하여 양식을 더럽게 할 필요는 없지만 일정관리 컨트롤에서 날짜를 선택하는 것도 적합합니다.

이를 위한 한 가지 방법은 기본적으로 읽기 전용 모드로 양식을 표시하고 '편집' 버튼을 갖는 것이며, 사용자가 편집 버튼을 클릭하면 DB로 호출이 이루어집니다(데이터 수정 여부와 관계없이).이는 현재 존재하는 것을 더 잘 개선한 것입니다.

컨트롤 값이 수정되었는지 확인할 수 있는 일반 자바스크립트 함수 작성 방법을 알고 싶습니다.

순수 자바스크립트에서는 이 작업이 쉽지 않지만 jQuery는 다음 작업을 매우 쉽게 수행할 수 있습니다.

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

그런 다음 저장하기 전에 변경되었는지 확인할 수 있습니다.

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

위의 예에서 폼의 ID는 "my form"과 같습니다.

여러 형태로 필요한 경우 플러그인으로 쉽게 전환할 수 있습니다.

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

그렇다면 간단하게 다음과 같이 말할 수 있습니다.

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

양식이 변경되었는지 확인합니다.

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

질문을 제대로 이해했는지 모르겠지만, 이벤트 청취자를 추가하는 것은 어떨까요?IE8 지원에 크게 신경 쓰지 않는다면 이 정도면 괜찮을 것입니다.다음 코드가 저를 위해 작동합니다.

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

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

JQuery가 불가능한 경우.구글에서 빠르게 검색한 결과 MD5와 SHA1 해시 알고리즘의 자바스크립트 구현이 발견되었습니다.원하는 경우 모든 양식 입력을 연결하고 해시한 다음 해당 값을 메모리에 저장할 수 있습니다.사용자가 완료되면.모든 값을 연결하고 다시 해시합니다.해시 2개를 비교합니다.동일한 경우, 사용자는 양식 필드를 변경하지 않았습니다.서로 다를 경우 편집된 내용이 있으므로 지속성 코드를 호출해야 합니다.

이를 위한 또 다른 방법은 다음과 같은 형태를 직렬화하는 것입니다.

$(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 없이 네이티브 자바스크립트에서 쉽게 탐지할 수 있습니다.

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 테스트 참조


For older browsers that don't support newer arrow/array functions:

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

(jQuery를 사용하지 않고) 이렇게 했습니다.

저의 경우, 저는 특정 양식 요소가 계산되지 않기를 원했는데, 그것이 체크를 촉발시킨 요소였기 때문에 항상 바뀔 것이기 때문입니다.예외 요소의 이름은 'reporting_period'이며 'hasFormChanged()' 함수에서 하드 코딩됩니다.

테스트하려면 요소를 "changeReportingPeriod()" 함수라고 부르도록 합니다. 이 함수를 다른 이름으로 지정할 수도 있습니다.

중요: 값이 원래 값으로 설정되어 있으면 setInitialValues()를 호출해야 합니다(일반적으로 페이지 로드 시에는 그렇지 않습니다).

참고: 저는 이 솔루션이 우아한 솔루션이라고 주장하지 않습니다. 사실 저는 우아한 자바스크립트 솔루션을 믿지 않습니다.자바스크립트에서 저의 개인적인 강조점은 (마치 자바스크립트에서 가능했던 것처럼) 구조적 우아함이 아니라 가독성에 있습니다.저는 자바스크립트를 작성할 때 파일 크기에 전혀 관심이 없습니다. 왜냐하면 그것이 gzip의 목적이고, 더 콤팩트한 자바스크립트 코드를 작성하려고 하면 항상 유지보수와 관련된 참을 수 없는 문제들이 발생하기 때문입니다.저는 사과도 하지 않고, 반성도 하지 않으며 토론도 거부합니다.자바스크립트입니다.미안해요, 제가 굳이 글을 올려야겠다고 스스로를 설득하기 위해서 이 점을 분명히 해야 했어요.행복하세요! :)


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


다음은 API를 사용하여 작성, 업데이트 및 삭제된 양식 항목을 탐지하는 네이티브 자바스크립트의 폴리필 메소드 데모입니다.변경된 사항이 있는지 확인할 수 있습니다.HTMLFormElement#isChanged를 사용하여 리셋 폼과 차이점을 포함하는 객체를 얻습니다.HTMLFormElement#changes(입력된 이름으로 가려지지 않음을 assuming합니다.

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>

저는 위의 Teekin의 기여를 매우 좋아하고, 그것을 실행해왔습니다.

그러나 다음과 같은 코드를 사용하여 체크박스도 허용하도록 확장했습니다.

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

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

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

    // 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]);
    }
    for (i = 0; i < checkboxes.length; i++) {
        all_form_elements.push(checkboxes[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++) {
        if(inputs[i].type != "checkbox"){
            initial_values.push(inputs[i].value);
        }
        else
        {
            initial_values.push(inputs[i].checked);
        }
    }
    
}

function hasFormChanged() {
    var has_changed = false;
    var elements = getAllFormElements();
    var diffstring = ""
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].type != "checkbox"){
            if (elements[i].value != initial_values[i]) {
                has_changed = true;
                //diffstring = diffstring + elements[i].value+" Was "+initial_values[i]+"\n";
                break;
            }
         }
         else
         {
            if (elements[i].checked != initial_values[i]) {
                has_changed = true;
                //diffstring = diffstring + elements[i].value+" Was "+initial_values[i]+"\n";
                break;
            }
         }
    }
    //alert(diffstring);
    return has_changed;
}

diffstring은 디버깅 도구일 뿐입니다.

다음을 포함한 모든 분야에 대한 Philippe Leybaert의 답변이 있습니다.select,textarea그리고.input그리고.serialize @nikoskip의 솔루션을 순수 자바스크립트로 제공합니다.

이것은 값이 정말로 원래 상태로 반전되지 않고 변경되었는지 확인합니다.

var $ = function( query ) { return document.querySelector( query ) }

HTMLFormElement.prototype.trackChanges = function(){
    let data = new URLSearchParams(new FormData(this)).toString();
    this.dataset.origData = data;
}

HTMLFormElement.prototype.isChanged = function(){
    let data = new URLSearchParams(new FormData(this)).toString();
    return ( data != this.dataset.origData )
}

그렇다면 간단하게 다음과 같이 말할 수 있습니다.

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

양식이 변경되었는지 확인합니다.

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

예:

var $ = function( query ) { return document.querySelector( query ) }

HTMLFormElement.prototype.trackChanges = function(){
  let data = new URLSearchParams(new FormData(this)).toString();
  this.dataset.origData = data;
}

HTMLFormElement.prototype.isChanged = function(){
  let data = new URLSearchParams(new FormData(this)).toString();
  return ( data != this.dataset.origData )
}

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

function TestForm(){
  if( $("#myform").isChanged())
    alert("Form has changed");
  else
    alert("Form has not changed");
  return false;
}
* { font: 16pt Arial }

div { margin: 20px 0 }
<form action="" method="get" id="myform" onsubmit="return TestForm()">
  <div>
    <label>Date:
      <input type="date" name="date">
    </label>
  </div>
  <div>
    <label>Email: 
      <input type="email" name="email">
    </label>
  </div>
  <div>
    <button>Is form changed?</button>
  </div>
 </form>

언급URL : https://stackoverflow.com/questions/959670/generic-way-to-detect-if-html-form-is-edited