Клиент/JS Framework для защиты от несанкционированных данных?

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

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

Ответ 1

Один кусочек головоломки:

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

Ответ 2

Если вы используете 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().

Ответ 3

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

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

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

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

Awesome! Молодцы Воломики!

Просто введите код 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'); });

});

Ответ 4

Дополнение к Лэнсу, я просто провел день, пытаясь запустить этот фрагмент. Во-первых, jquery 1.4, похоже, имеет ошибки с привязкой события изменения (по состоянию на февраль '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", а не перечислял все типы ввода. Строго перехитрить, но я подумал, что это круто: -)

Ответ 5

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

Ответ 6

Я сделал еще одно небольшое улучшение для реализаций 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() });
});