Подтвердить что ты не робот

ASP.NET, jQuery, грязные формы и window.onbeforeunload

В моем веб-приложении ASP.NET я пытаюсь создать универсальный способ предупреждения пользователей перед тем, как перейти от формы, когда они внесут изменения, используя jQuery. Довольно стандартный материал, но после многих поисков мне еще предстоит найти технику, которая работает.

Вот что я имею в этой точке:

    addToPostBack = function(func) {
        var old__doPostBack = __doPostBack;
        if (typeof __doPostBack != 'function') {
            __doPostBack = func;
        } else {
            __doPostBack = function() {
                old__doPostBack();
                func();
            }
        }
    }

    var isDirty = false;

    $(document).ready(function() {
        addToPostBack(function() {
            alert("Postback detected.")
            clearDirty();
        });
        $(':input').bind("change select keydown", setDirty);
        window.onbeforeunload = function(e) {
            var msg = "You have unsaved changes. "
            if (isDirty == true) {
                var e = e || window.event;
                if (e) { e.returnValue = msg; }
                return msg;
            }
        };
    });

    setDirty = function() {isDirty = true;}

    clearDirty = function() {isDirty = false;}

Это работает, поскольку предупреждает пользователя от навигации. Проблема в том, что я получаю предупреждение при каждой обратной почте на одной странице. В моих формах есть несколько вещей, которые могут вызвать обратную передачу:

  • На странице есть кнопки сохранения, отмены и удаления.
  • На странице могут быть другие кнопки ссылок, которые выполняют функциональные возможности на стороне сервера, оставаясь на одной странице.
  • Могут быть другие элементы управления с autopostback = true, которые также имеют подключенные к серверу функции, но не приводят к тому, что пользователь покидает страницу.

Ни одна из этих вещей не должна вызывать предупреждение, поскольку пользователь не покидает страницу. Мой код пытается убрать addToPostBack (подробнее об этом в этом вопросе), чтобы очистить isDirty bit перед отправкой назад, но проблема в том, что в IE onbeforeunload срабатывает перед __doPostBack, по-видимому, потому, что IE запускается onbeforeunload сразу же при нажатии ссылки (как описано здесь).

Конечно, я могу подключить каждый из этих элементов управления, чтобы очистить isDirty bit, но я бы предпочел решение, которое работает на уровне формы, и это не требует, чтобы я касался каждого элемента управления, который может вызвать обратную передачу,

Есть ли у кого подход, который работает в ASP.NET, и это не связано с подключением каждого элемента управления, который может вызвать обратную передачу?

4b9b3361

Ответ 1

Я столкнулся с этим сообщением, в то время как Googling для решения для того, чтобы сделать то же самое в MVC. Это решение, адаптированное из Herb выше, похоже, хорошо работает. Поскольку в этом нет ничего MVC-специфичного, он должен работать так же хорошо для PHP, классического ASP или любого другого приложения, использующего HTML и JQuery.

var isDirty = false;

$(document).ready(function () {
    $(':input').bind("change select keydown", setDirty);
    $('form').submit(clearDirty);

    window.onbeforeunload = function (e) {
        var msg = "You have unsaved changes. "
        if (isDirty == true) {
            var e = e || window.event;
            if (e) { e.returnValue = msg; }
            return msg;
        }
    };
});

setDirty = function () { isDirty = true; }
clearDirty = function () { isDirty = false; }

Ответ 2

Вы всегда можете создать класс без заголовка, который имеет собственный метод OnLoad/OnUnload, который добавляет в javascript немедленное выполнение.

Тогда вам не нужно обрабатывать его на определенном уровне управления, а скорее на уровне формы/страницы.

Ответ 3

Интересно, но... почему бы вам не сделать все с помощью jQuery?

var  defaultSubmitControl = false;
var  dirty = false;
$(document).ready(function( ) {
    $('form').submit(function( ) { dirty = false });
    $(window).unload(function( ) {
        if ( dirty && confirm('Save?') ) {
            __doPastBack(defaultSubmitControl || $('form :submit[id]').get(0).id, '');
        }
    });
});
···
dirty = true;
···

Теперь, если это все еще вызывает ту же проблему (unload triggering before submit), вы можете попробовать другое дерево событий, поэтому вместо прямого вызова __doPostBack вы...

setTimeout(function( ) {
    __doPastBack(defaultSubmitControl || $('form :submit[id]').get(0).id, '');
}, 1);  // I think using 0 (zero) works too

Я не пробовал это, и это с самого начала, но я думаю, что это может быть способ его решить.

Ответ 4

Получил это, чтобы в основном отслеживать положение мыши. Имейте в виду, что вы все равно можете получить положительные значения для своего значения Y (следовательно, моя линия и 50 строк кода), но пока кнопки отправки более 100 пикселей вниз, вы должны быть в порядке.

Вот Javascript, который я добавил для отслеживания изменений мыши и захвата события onbeforeunload:

    <script language="JavaScript1.2">
    <!--

    // Detect if the browser is IE or not.
    // If it is not IE, we assume that the browser is NS.
    var IE = document.all?true:false

    // If NS -- that is, !IE -- then set up for mouse capture
    if (!IE) document.captureEvents(Event.MOUSEMOVE)

    // Set-up to use getMouseXY function onMouseMove
    document.onmousemove = getMouseXY;

    // Temporary variables to hold mouse x-y pos.s
    var tempX = 0
    var tempY = 0

    // Main function to retrieve mouse x-y pos.s

    function getMouseXY(e) {
      if (IE) { // grab the x-y pos.s if browser is IE
        tempX = event.clientX + document.body.scrollLeft
        tempY = event.clientY + document.body.scrollTop
      } else {  // grab the x-y pos.s if browser is NS
        tempX = e.pageX
        tempY = e.pageY
      }  
      // catch possible negative values in NS4
      if (tempX < 0){tempX = 0}
      if (tempY < 0){tempY = 0}  
      // show the position values in the form named Show
      // in the text fields named MouseX and MouseY
      document.Show.MouseX.value = tempX
      document.Show.MouseY.value = tempY
      return true
    }

    //-->
    </script>


    <script type="text/javascript">

        window.onbeforeunload = HandleOnClose;

        function HandleOnClose(e) {

            var posY = 0;
            var elem = document.getElementsByName('MouseY');
            if (elem[0]) {
                posY = elem[0].value;
            }

            if (posY < 50) {    // Your form "submit" buttons will hopefully be more than 100 pixels down due to movement
                return "You have not selected an option, are you sure you want to close?";
            }
        }

    </script>

Затем просто добавьте на свою страницу следующую форму:

    <form name="Show">
        <input type="hidden" name="MouseX" value="0" size="4">
        <input type="hidden" name="MouseY" value="0" style="display:block" size="0">
    </form>

И это! Он может использовать небольшую очистку (удалить MouseX и т.д.), Но это сработало в моем существующем приложении ASP.net 3.5 и подумало, что я опубликую, чтобы помочь кому-либо. Работает в IE 7 и Firefox 3.6, еще не пробовал Chrome.

Ответ 5

Я тоже занимаюсь этим, но то, что я нашел до сих пор, - это решение, которое использует все элементы html control вместо веб-элементов управления asp.net, подумайте об этом?

  <script type="text/javascript">
    $(document).ready(function () {
      $("form").dirty_form();
      $("#btnCancel").dirty_stopper();
    });             
  </script>