如何防止退出阻止脚本在使用后禁用提交按钮

问题描述 投票:1回答:1

我有一个脚本用于防止导航离开页面,因此不会意外地丢失更改。不幸的是,如果通过提交表单激活​​脚本,这也会“破坏”页面。因此,在我按下提交按钮后决定留在页面上时,我无法再提交表单。

当导航由提交按钮以外的其他内容完成时,这不会禁用提交按钮。

有没有办法防止这种情况发生,并允许我“意外”多次激活此脚本,同时仍然能够在弹出窗口后使用我的提交按钮?

<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" %>
javascript ruby-on-rails twitter-bootstrap simple-form
1个回答
1
投票

我花了一点时间,并建立了一个如何解决这类问题的例子。有几件事情不是;

  • 我创建了一个全局变量formSubmitting,用于查看表单是否正在提交,并在我设置为true的表单的onsubmit事件中
  • 我替换了运行在所有元素上的for循环以使用querySelectorAllfilter的组合如果你需要支持IE 11,那么你将需要用for循环替换调用filter来做同样的测试
  • 警告用户的过程如下: 如果表单未提交 如果表单没有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 Example

© www.soinside.com 2019 - 2024. All rights reserved.