Клиент / JS Framework для защиты "несохраненных данных"? - PullRequest
20 голосов
/ 26 сентября 2008

У нас есть типичное веб-приложение, которое по сути представляет собой приложение для ввода данных с множеством экранов, некоторые из которых имеют некоторую сложность. Мы должны предоставить эту стандартную возможность, чтобы убедиться, что если пользователь забудет нажать кнопку «Сохранить», прежде чем покинуть или закрыть свой браузер, он получит предупреждение и может отменить (но только при наличии несохраненных или грязных данных).

Я знаю основы того, что я должен сделать - на самом деле я уверен, что делал все это раньше, за несколько лет (связать с onbeforeunload, отследить «грязное» состояние страницы и т. Д.) ...) но прежде чем я приступлю к кодированию этого YET AGAIN, есть ли у кого-нибудь какие-нибудь предложения для библиотек (бесплатных или иных), которые помогут?

Ответы [ 6 ]

19 голосов
/ 26 сентября 2008

Один кусочек пазла:

/**
 * 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["someFormOfInterest"]))
    {
        // 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.

13 голосов
/ 10 апреля 2009

Если вы используете jQuery, вот простой трюк:

$('input:text,input:checkbox,input:radio,textarea,select').one('change',function() {
  $('BODY').attr('onbeforeunload',"return 'Leaving this page will cause any unsaved data to be lost.';");
});

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

$('BODY').removeAttr('onbeforeunload');

... или вы попадете в цикл, в котором вас будут спрашивать подсказки.

В моем случае у меня было большое приложение, и я делал location.href, перенаправлял в Javascript, а также отправлял формы, а затем некоторые AJAX отправляли, которые затем возвращались с успешным ответом, встроенным в страницу. В любом из этих условий мне приходилось перехватывать это событие и использовать вызов removeAttr ().

7 голосов
/ 08 февраля 2010

В дополнение к ответу Ланса, я только что провел день, пытаясь запустить этот фрагмент. Во-первых, в jquery 1.4, похоже, есть ошибки с привязкой события change (по состоянию на февраль '10). JQuery 1.3 в порядке. Во-вторых, я не могу заставить jquery связывать onbeforeunload / beforeunload (я подозреваю, что IE7, который я использую). Я пробовал разные селекторы, ("тело"), (окно). Я пробовал «.bind», «.attr». Возврат к чистому js сработал (я также видел несколько похожих постов на SO об этой проблеме):

$(document).ready(function() {
    $(":input").one("change", function() {
        window.onbeforeunload = function() { return 'You will lose data changes.'; }
    });
    $('.noWarn').click(function() { window.onbeforeunload = null; });
});

Примечание. Я также использовал селектор ': input' вместо того, чтобы перечислять все типы ввода. Строго перебор, но я подумал, что это круто: -)

7 голосов
/ 19 июня 2009

Хотел немного расширить на Volomike отличный код jQuery.

Таким образом, у нас есть очень крутой и элегантный механизм для достижения цели предотвращения непреднамеренной потери данных путем перехода от обновленных данных до их сохранения, т.е. обновленное поле на странице, затем нажмите кнопку, ссылку или даже кнопку возврата в браузере, прежде чем нажимать кнопку Сохранить.

Единственное, что вам нужно сделать, это добавить тег класса «noWarn» ко всем элементам управления (особенно к кнопкам «Сохранить»), которые отправляют сообщения обратно на сайт, которые либо сохраняют, либо не удаляют обновленные данные.

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

Отлично! Молодец, Воломике!

Просто используйте код jQuery следующим образом:

$(document).ready(function() {

    //----------------------------------------------------------------------
    // Don't allow us to navigate away from a page on which we're changed
    //  values on any control without a warning message.  Need to class our 
    //  save buttons, links, etc so they can do a save without the message - 
    //  ie. CssClass="noWarn"
    //----------------------------------------------------------------------
    $('input:text,input:checkbox,input:radio,textarea,select').one('change', function() {
        $('BODY').attr('onbeforeunload',
        "return 'Leaving this page will cause any unsaved data to be lost.';");
    });

    $('.noWarn').click(function() { $('BODY').removeAttr('onbeforeunload'); });

});
2 голосов
/ 01 апреля 2010

Я создал плагин jQuery , который можно использовать для реализации функции предупреждения о несохраненных изменениях для веб-приложений. Поддерживает постбэки. Он также содержит ссылку на информацию о том, как нормализовать поведение события onbeforeunload в Internet Explorer.

1 голос
/ 08 марта 2010

Я внес еще одно небольшое улучшение в реализации jQuery, перечисленные на этой странице. Моя реализация справится, если у вас проверка страницы ASP.NET на стороне клиента включена и используется на странице.

Это позволяет избежать «ошибки» очистки функции onBeforeLeave, когда страница фактически не публикуется при клике из-за ошибки проверки. Просто используйте класс no-warn-validate для кнопок / ссылок, которые вызывают проверку. Он по-прежнему имеет класс no-warn для использования на элементах управления, которые имеют CausesValidation=false (например, кнопка «Сохранить как черновик»). Этот шаблон, вероятно, может быть использован для других сред проверки, кроме ASP.NET, поэтому я публикую здесь для справки.

 function removeCheck() { window.onbeforeunload = null; }

$(document).ready(function() {
    //-----------------------------------------------------------------------------------------
    // Don't allow navigating away from page if changes to form are made. Save buttons, links,
    // etc, can be given "no-warn" or "no-warn-validate" css class to prevent warning on submit.
    // "no-warn-validate" inputs/links will only remove warning after successful validation
    //-----------------------------------------------------------------------------------------
    $(':input').one('change', function() {
        window.onbeforeunload = function() {
            return 'Leaving this page will cause edits to be lost.';
        }
    });

    $('.no-warn-validate').click(function() {
        if (Page_ClientValidate == null || Page_ClientValidate()) { removeCheck(); }
    });

    $('.no-warn').click(function() { removeCheck() });
});
...