Предупреждаю пользователя перед тем, как покинуть web-страницу с несохраненными изменениями

У меня есть несколько страниц с формами в моем заявлении.

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

314
задан CodeCaster 8 January 2015 в 10:56
поделиться

2 ответа

Опробовано универсальное решение Эли Грея, работавшее только после того, как я упростил код до

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

  })();

. При модификации его удаляется использование target[defaultValue] и используется только target.dataset[defaultValue] для хранения реального значения по умолчанию. .

И я добавил «сохраненный» прослушиватель событий, где «сохраненное» событие будет вызвано вами самостоятельно при успешном сохранении.

Но это «универсальное» решение работает только в браузерах, но не работает в веб-обозрении приложения, например, wechat браузерах.

Чтобы заставить его работать в браузерах wechat (частично), еще одно улучшение:

  'use strict';
  (() => {
    const modified_inputs = new Set();
    const defaultValue = 'defaultValue';
    // store default values
    addEventListener('beforeinput', evt => {
      const target = evt.target;
      if (!(defaultValue in target.dataset)) {
        target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
      }
    });

    // detect input modifications
    addEventListener('input', evt => {
      const target = evt.target;
      let original = target.dataset[defaultValue];

      let current = ('' + (target.value || target.textContent)).trim();

      if (original !== current) {
        if (!modified_inputs.has(target)) {
          modified_inputs.add(target);
        }
      } else if (modified_inputs.has(target)) {
        modified_inputs.delete(target);
      }

      if(modified_inputs.size){
        const event = new Event('needSave')
        window.dispatchEvent(event);
      }
    });

    addEventListener(
      'saved',
      function(e) {
        modified_inputs.clear()
      },
      false
    );

    addEventListener('beforeunload', evt => {
      if (modified_inputs.size) {
        const unsaved_changes_warning = 'Changes you made may not be saved.';
        evt.returnValue = unsaved_changes_warning;
        return unsaved_changes_warning;
      }
    });

    const ua = navigator.userAgent.toLowerCase();

    if(/MicroMessenger/i.test(ua)) {
      let pushed = false

      addEventListener('needSave', evt => {
        if(!pushed) {
          pushHistory();

          window.addEventListener("popstate", function(e) {
            if(modified_inputs.size) {
              var cfi = confirm('确定要离开当前页面嘛?' + JSON.stringify(e));
              if (cfi) {
                modified_inputs.clear()
                history.go(-1)
              }else{
                e.preventDefault();
                e.stopPropagation();
              }
            }
          }, false);
        }

        pushed = true
      });
    }

    function pushHistory() {
      var state = {
        title: document.title,
        url: "#flag"
      };
      window.history.pushState(state, document.title, "#flag");
    }
  })();
0
ответ дан 23 November 2019 в 01:08
поделиться

Можно использовать, сериализируют (), чтобы создать закодированную текстовую строку URL путем сериализации значений формы и проверить, изменилась ли форма, beforeunload

$(document).ready(function(){
    var form = $('#some-form'),
        original = form.serialize()

    form.submit(function(){
        window.onbeforeunload = null
    })

    window.onbeforeunload = function(){
        if (form.serialize() != original)
            return 'Are you sure you want to leave?'
    }
})

Отсылают эту ссылку https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form, Записанный Vladimir Sidorenko

0
ответ дан 23 November 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: