Как запретить сценарию блокировки выхода отключать кнопку отправки после его использования - PullRequest
0 голосов
/ 12 февраля 2019

У меня есть скрипт, используемый для предотвращения перехода от страницы, чтобы изменения не были потеряны случайно.К сожалению, это также «ломает» страницу, если скрипт активируется путем отправки формы.Таким образом, я больше не могу отправить форму после того, как я нажму кнопку отправки и решу остаться на странице.

Это не не отключает кнопку отправки, когда навигация выполняется чем-то иное , чем кнопка отправки.

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

<script>
  window.onbeforeunload = function() {
    var inputs = document.getElementsByTagName('input');
    var unfinished = 'false';
    for (var i = 0; i < inputs.length; ++i) {
      if (inputs[i].value != '') {
        unfinished = 'true';
      }
    }
    if (unfinished == 'true') {
      return 'Are you sure you want to leave?';
    }
  }
</script>

Перед активацией выходного блокиратора (с помощью кнопки отправки):

<input type="submit" name="commit" value="Edit product" class="btn btn-warning btn-block" data-disable-with="Edit product">

После активации блокировщика выхода (с помощью кнопки отправки):

<input type="submit" name="commit" value="Edit product" class="btn btn-warning btn-block" data-disable-with="Edit product" disabled="">

Как видите, он добавляет disabled="", когда по какой-то причине находится на моем сайте.

Форма:

<%= simple_form_for @pack, url: pack_path(@pack), method: :patch do |f| %>
<%= render 'shared/error_messages', object: f.object %>
  <%= f.input :title, class: "form-control center" %>
  <%= f.input :pack_type, class: "form-control center" %>
  <%= f.input :category_id, prompt: "Select Category", collection: [ "sample-pack", "vocal-pack", "preset-pack", "track-pixel", "track-indie", "track-orchestral"], input_html: { class: "form-control center" } %>
  <%= f.input :price, class: "form-control center" %>
  <%= f.input :audio_embed, class: "form-control center" %>
  <%= f.input :video_embed, class: "form-control center" %>
  <%= f.input :art_link, prompt: "ENTER N/A IF STRACK", class: "form-control center" %>
  <%= f.input :download_url, class: "form-control center" %>
  <%= f.submit "Edit product", class: "btn btn-warning btn-block" %>
<% end %>
  <%= link_to "Cancel", packs_path, class: "btn btn-danger top-drop" %>

1 Ответ

0 голосов
/ 13 февраля 2019

Я потратил немного времени и построил пример того, как я подхожу к этому типу проблемы.Пара вещей, чтобы не были;

  • Я создал глобальную переменную formSubmitting, которая используется, чтобы увидеть, отправляется ли форма, и в событии onsubmit формы я установил для него значение true
  • Я заменил цикл for, который работал над всеми элементами, чтобы использовать комбинацию querySelectorAll и filter Если вам требуется поддержка IE 11, вам нужно заменить вызов filter нацикл for выполняет тот же тест
  • Процесс предупреждения пользователя выглядит следующим образом:
    • Если форма не отправляется
    • Если форма не имеетатрибут disabled
    • Если в форме есть текстовые поля, которые не являются пустыми
      • , предупреждают пользователя об уходе со страницы

// Global variable used to determin if the form is being submitted
// This is used to determine if the user is navigating away from the page
// or trying to submit the form
var formSubmitting = false;

function findNonEmptyInputsInForm(formName) {
  // the css selector we are using here breaks down like this
  // -  form[id="' + formName + '"]
  //    Find the specific formwe want to check the textboxes in
  // -  > fieldset 
  //    We are only interested in the fieldsets in that form
  // -  > input[type="text"]
  //    we only want the inputs in that fieldset that are textboxes

  var cssSelector = 'form[id="' + formName + '"] > fieldset > input[type="text"]';

  // Call filter on the Array to only find elements that
  return Array.prototype.filter.call(document.querySelectorAll(cssSelector), (e) => e.value != '')
}

window.onbeforeunload = function(e) {
  // check if the form is being submitted
  // we don't want to block the user from 
  // submittng the form
  if (!formSubmitting) {
    // reset the formSubmitting flag
    formSubmitting = false;
    // pull the disabled attribute from the form
    var formDisabled = document.forms["test"].getAttribute('disabled') === "";

    // check if the disabled attribute has been added
    // to the form, we don't want to prevent navigation
    // if the disabled attribute is on the form
    if (!formDisabled) {
      // find all the textboxes that have a value
      var noneEmptyElements = findNonEmptyInputsInForm('test');
      // check if the user has entered any values in the textbox
      // we don't want to prevent navigation if the user 
      // hasn't modified the form
      if (noneEmptyElements.length > 0) {
        // display the confirmation
        return 'Are you sure you want to leave?';
      }
    }
  }

  // reset the formSubmitting flag
  formSubmitting = false;
}
<form id="test" name="test" action="/" onsubmit="formSubmitting = true;">
  <fieldset form="test">
    <label for="test_input">Test Element 1</label>
    <input id="test_input" type="text" /><br/>


    <label for="test_input2">Test Element 2</label>
    <input id="test_input2" type="text" /><br/>


    <label for="test_input3">Test Element 3</label>
    <input id="test_input3" type="text" /><br/><br />

    <button type="submit">Submit</button>
  </fieldset>
</form>

Вот ссылка на скрипку, с которой вы можете поиграть и добавить / удалить атрибут disabled. Пример JsFiddle

...