문제

ASP .NET 응용 프로그램에서 "구원받지 않은 변경"프롬프트를 구현해야합니다. 사용자가 웹 양식에서 컨트롤을 수정하고 저장하기 전에 탐색하려고 시도하는 경우, 프롬프트가 변경되지 않은 것으로 경고하고 현재 페이지를 취소하고 유지할 수있는 옵션을 제공해야합니다. 사용자가 컨트롤을 건드리지 않은 경우 프롬프트가 표시되지 않아야합니다.

이상적으로는 이것을 JavaScript로 구현하고 싶지만, 내 코드를 굴리는 경로를 내려 가기 전에이를 달성하기위한 기존의 프레임 워크 또는 권장 설계 패턴이 있습니까? 이상적으로는 최소한의 변경으로 여러 페이지에서 쉽게 재사용 할 수있는 것을 원합니다.

도움이 되었습니까?

해결책

jQuery 사용 :

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

결합 onunload/onbeforeunload 필요한 방법.

주석에서 다음은 코드를 복제하지 않고 모든 입력 필드를 참조합니다.

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

사용 $(":input") 모든 입력, TextArea, Select 및 버튼 요소를 나타냅니다.

다른 팁

퍼즐의 한 조각 :

/**
 * 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이벤트 등록.

.aspx 페이지에는 양식 정보가 "더러운"인지 여부를 알리기 위해 JavaScript 함수가 필요합니다.

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

다음은 브라우저의 OnbeforeUnload 기능과 jQuery를 사용하여 OnChange 이벤트를 캡처합니다. 또한 제출 또는 재설정 버튼을 찾으려면 변경 사항이 발생했음을 나타내는 플래그를 재설정합니다.

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;

모두에게 답장을 보내 주셔서 감사합니다. jQuery와 보호 데이터 플러그인. 이를 통해 페이지의 모든 컨트롤에 모니터링을 자동으로 적용 할 수 있습니다.

그러나 특히 ASP .NET 응용 프로그램을 다룰 때 몇 가지 경고가 있습니다.

  • 사용자가 취소 옵션을 선택하면 dopostback 함수에 JavaScript 오류가 발생합니다. 나는 그것을 억제하기 위해 dopostback 내에서 .submit 호출 주위에 시도를 수동으로 놓아야했다.

  • 일부 페이지에서는 사용자가 같은 페이지에 대한 포스트 백을 수행하지만 저장되지 않는 작업을 수행 할 수 있습니다. 이로 인해 JavaScript 논리가 재설정되므로 포스트 백 이후에는 아무것도 변경되지 않았다고 생각합니다. 페이지와 함께 다시 게시되는 숨겨진 텍스트 상자를 구현해야했으며 데이터가 더럽든지 여부를 나타내는 간단한 부울 값을 보유하는 데 사용됩니다. 이것은 포스트 백에서 지속됩니다.

  • 페이지의 일부 포스트백이 저장 버튼과 같은 대화 상자를 트리거하지 않기를 원할 수 있습니다. 이 경우 jQuery를 사용하여 wind

바라건대 이것은 비슷한 것을 구현 해야하는 다른 사람에게 도움이되기를 바랍니다.

다음 솔루션은 프로토 타입 (FF, IE 6 및 Safari로 테스트)에 대해 작동합니다. 일반적인 형태의 관찰자 (양식을 발사 : 양식의 모든 필드가 수정 된 경우 변경)를 사용하여 다른 물건에도 사용할 수 있습니다.

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

다음은 간단한 JavaScript / JQuery 솔루션입니다. 사용자가 "UNDOS"를 설명하고 응용 프로그램의 용이성을 위해 함수 내에 캡슐화되며 제출시 잘못 파종하지 않습니다. 함수를 호출하고 양식의 ID를 전달하십시오.

이 함수는 페이지가로드 될 때 양식을 한 번, 사용자가 페이지를 떠나기 전에 다시 한 번 양식을 직렬화합니다. 두 형태의 상태가 다르면 프롬프트가 표시됩니다.

시도해보십시오 : 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');
});

주어진 페이지에서 여러 형식을 지원하는 일반 솔루션 (프로젝트에 복사하여 붙여 넣기 만하면됩니다)

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

참고 :이 솔루션은 일반적인 통합 솔루션을 만들기 위해 다른 솔루션에서 결합되어 있습니다.

특징:

  • 앱에 복사하여 붙여 넣기 만하면됩니다.
  • 여러 형식을 지원합니다.
  • 클래스가 "형태 더 높은"수업을 받았기 때문에 스타일링하거나 더러운 형태를 만들 수 있습니다.
  • '무시-초기'클래스를 추가하여 일부 양식을 제외 할 수 있습니다.

최근에 오픈 소스 jQuery 플러그인에 기여했습니다. 더티 폼.

플러그인은 동적으로 추가 된 HTML과 함께 작동하도록 설계되었으며 여러 형식을 지원하며 거의 모든 대화 프레임 워크를 지원할 수 있으며, 브라우저로 돌아가서로드하기 전에 브라우저로 돌아가고, 맞춤형 편집기에서 더러운 상태를 얻을 수 있도록 플러그가 가능한 헬퍼 프레임 워크가 있습니다 (Tinymce 플러그인이 포함되어 있음). , iframes 내에서 작동하며 더러운 상태는 마음대로 설정되거나 재설정 될 수 있습니다.

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

jQuery를 사용하여 양식 변경을 감지하는 것은 매우 간단합니다.

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

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

나는 위의 Slace의 제안에 따라 대부분의 편집 가능한 요소를 포함시키고 특정 요소 (여기에 "srsearch"라고 불리는 CSS 스타일)를 제외하여 더러운 깃발을 설정하지 못하게합니다.

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

      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 = 언로드 페이지;

이것이 바로 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 언로드에. 파이처럼 쉽습니다.

하나의 방법, 배열을 사용하여 변수를 보유하여 변경을 추적 할 수 있습니다.

여기에 매우 간단한 방법이 있습니다 변경 사항을 감지하십시오, 그러나 나머지는 우아하지 않습니다.

상당히 단순하고 작은 또 다른 방법 Farfetched 블로그:

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

IE Document.ready에서 제대로 작동하지 않으면 입력 값이 업데이트됩니다.

따라서 IE 브라우저에 대해서도 처리 할 수있는 문서 내부의로드 이벤트를 바인딩해야합니다.

아래는 문서에 넣어야 할 코드입니다.

 $(document).ready(function () {
   $(window).bind("load", function () { 
    $("input, select").change(function () {});
   });
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top