在 Chrome/Safari 中提交表单两次

发布于 2024-09-08 11:56:15 字数 1207 浏览 4 评论 0原文

我正在寻求执行基本的表单发布,但以下内容在 Chrome 和 Safari 中提交到服务器两次(但在 Firefox 中的行为符合预期):

<form id="create-deck-form" action="/decks/create" method="post">
  <fieldset>
    <legend>Create new deck</legend>
    <label for="deck-name-field">Name</label>
    <input id="deck-name-field" name="deck-name-field" type="text" value="" maxlength="140" />

    <label for="tag-field">Tags</label>
    <input id="tag-field" name="tag-field" type="text" value="" maxlength="140" />

    <input class="add-button" type="submit" value="Create" />
  </fieldset>
</form>

我想使用 onsubmit 属性来执行验证提交之前的字段,但只要返回值为 true,表单就会提交两次。

我试图将 jQuery 处理程序绑定到表单,但在这里,默认行为不会被阻止,表单会提交两次,例如:

<script type="text/javascript">
 $(document).ready(function() {
     $("#create-deck-form").submit(function(event){
          if($("#deck-name-field").val() == "") {
            event.preventDefault();
            alert("deck name required");
          }
        });
 });
</script>

虽然我认为对于新人来说这里有一些明显的错误,但我我深感困惑,为什么提交(无论是否经过验证)都会在 Chrome 和 Safari 中向服务器发出重复的帖子。我将不胜感激任何见解。

I am seeking to perform a basic form post, but the following submits to the server twice in Chrome and Safari (but behaves as expected in Firefox):

<form id="create-deck-form" action="/decks/create" method="post">
  <fieldset>
    <legend>Create new deck</legend>
    <label for="deck-name-field">Name</label>
    <input id="deck-name-field" name="deck-name-field" type="text" value="" maxlength="140" />

    <label for="tag-field">Tags</label>
    <input id="tag-field" name="tag-field" type="text" value="" maxlength="140" />

    <input class="add-button" type="submit" value="Create" />
  </fieldset>
</form>

I would like to use the onsubmit attribute to perform validation on the fields before submission, but wherever the return value is true, the form is submitted twice.

I have sought to bind a jQuery handler to the form, but here too, where the default behaviour is not prevented, the form is submitted twice, e.g.:

<script type="text/javascript">
 $(document).ready(function() {
     $("#create-deck-form").submit(function(event){
          if($("#deck-name-field").val() == "") {
            event.preventDefault();
            alert("deck name required");
          }
        });
 });
</script>

While I suppose there is something blindingly obvious wrong here to a fresh pair of eyes, I am deeply confused why submission, with or without validation, makes a duplicate post to the server in Chrome and Safari. I'd be grateful for any insight.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明天过后 2024-09-15 11:56:15

这个问题实际上与 Facebox (http://defunkt.github.com/facebox/) 有关。 Facebox 初始化会在页面加载后引发第二组请求。因此,如果您发布到 /myaction/create,Facebox 将启动第二组请求,并将基本 URL 设置为 /myaction/create。解决方法是在发布后重定向到处理 get 请求的 URL,这样您就不会执行两次发布。非常感谢您的帮助。

This issue is actually associated with Facebox (http://defunkt.github.com/facebox/). Facebox initialization causes a second set of requests after your page loads. So, if you post to /myaction/create, Facebox will start a second set of requests with the base URL set to /myaction/create. A fix is to redirect to a URL which handles get requests after doing a post, so you don't end up performing the post twice. Thanks very much for your help.

七秒鱼° 2024-09-15 11:56:15

我不是 100% 确定,但请尝试这个:

<script type="text/javascript">
   $(document).ready(function() {
      $("#create-deck-form").submit(function(event){
         if(!$("#deck-name-field").val().length) {
           return false;
         }
       });
   });
</script>

如果这不起作用,请查看

for(e in $("#create-deck-form").data('events'))
    alert(e);

这将提醒您绑定到您的表单的所有事件。也许还有更多的事件处理程序?否则也发出警报/记录

$("#create-deck-form").attr('onclick')

$("#create-deck-form").attr('onsubmit')

以防万一。

I'm not 100% sure, but please try this one:

<script type="text/javascript">
   $(document).ready(function() {
      $("#create-deck-form").submit(function(event){
         if(!$("#deck-name-field").val().length) {
           return false;
         }
       });
   });
</script>

if that does not work, please have a look at

for(e in $("#create-deck-form").data('events'))
    alert(e);

This will alert you all events which are bound to your form. Maybe there are more event handlers? Otherwise also alert/log

$("#create-deck-form").attr('onclick')

and

$("#create-deck-form").attr('onsubmit')

just in case.

琉璃繁缕 2024-09-15 11:56:15

浏览器(例如 Safari 桌面版)将表单提交事件屏蔽为单击事件。因此,即使您在表单的提交事件上设置了 evt.preventDefault()evt.stopPropagation(),您也可能会遇到提交表单的问题。

一个很好的例子和场景是通过按 ENTER 键提交表单。在这种情况下,Safari 会发出一个点击事件,这可能会导致其他事件侦听器触发,等等。

解决方案:

您可以像这样监听那些被屏蔽的提交事件:

$('[type="submit"]', $('form')).on('click', function(evt) {
    ...
}

现在您只想捕获那些实际被屏蔽的事件;您不想捕获提交按钮上的鼠标单击。

因此,您必须区分真实点击和恶意点击。您可以通过检查 evt.originalEvent 对象来执行此操作。

如果您能找到一个 pointerId (Chrome) 键,那么恶意点击就会带有 pointerId = -1 (某些负值);如果您没有 pointerId(例如 Safari),您可以查找 evt.originalEvent.detail 键(Safari),如果出现恶意点击,该键会带有值为 0(零)。

完整示例

$('[type="submit"]', $('form')).on('click', function(evt) {
    let do_not_submit = false
    // chrome
    if (typeof evt.originalEvent.pointerId !== 'undefined' && evt.originalEvent.pointerId < 0) {
        do_not_submit = true
    }
    // safari
    if (!do_not_submit && typeof evt.originalEvent.detail !== 'undefined' && evt.originalEvent.detail === 0) {
        do_not_submit = true
    }
    if (do_not_submit) {
        evt.preventDefault()
        evt.stopPropagation()
        return
    }
    // no worries ... 
    // submitting ...
}

Browsers (Safari Desktop for instance) mask form submit events as click events. So you might run into an issue of forms being submitted even if you have an evt.preventDefault() or evt.stopPropagation() set on your form's submit event.

Good example and scenario for this is submitting a form by hitting the ENTER key. In that case Safari emits a click event that might cause other event listeners to fire, etc.

Solution:

You can listen to those masked submit events like this:

$('[type="submit"]', $('form')).on('click', function(evt) {
    ...
}

Now you only want to catch those events that are actually masked; you don't want to catch a mouseclick on a submit button.

Therefore you have to distinguish real clicks from those rogue ones. You can do so by checking the evt.originalEvent object.

If you can find a pointerId (Chrome) key than rogue clicks come with a pointerId = -1 (some negative value); if you don't have a pointerId (eg. Safari) you can look for the evt.originalEvent.detail key (Safari) which in case of rogue clicks comes with the value of 0 (zero).

Full Example

$('[type="submit"]', $('form')).on('click', function(evt) {
    let do_not_submit = false
    // chrome
    if (typeof evt.originalEvent.pointerId !== 'undefined' && evt.originalEvent.pointerId < 0) {
        do_not_submit = true
    }
    // safari
    if (!do_not_submit && typeof evt.originalEvent.detail !== 'undefined' && evt.originalEvent.detail === 0) {
        do_not_submit = true
    }
    if (do_not_submit) {
        evt.preventDefault()
        evt.stopPropagation()
        return
    }
    // no worries ... 
    // submitting ...
}
顾北清歌寒 2024-09-15 11:56:15

您可以在发出警报后尝试 return false; 并删除 event.preventDefault();。也许您还需要在 else 子句中 return true; 。我相信我在某个地方有这样的工作。

Can you try return false; after your alert and remove event.preventDefault();. Maybe you also need return true; in your else-clause. I believe I have that working somewhere.

霞映澄塘 2024-09-15 11:56:15

好吧,不确定这会有多大帮助,但尝试删除提交输入并通过 JavaScript 提交表单。因此,例如

<input id="submit-button" class="add-button" type="button" value="Create" />

,然后,您可以尝试现在,您的方式也应该可以工作,而不是监听 onsubmit

$('#submit-button').click(function(evt) {
    if(validationSuccess(...)) {
        $("#create-deck-form").submit();
    } else {
        //display whatever
    }
});

...但是这样您可以调试问题所在...这应该只提交一次...很好运气!

Ok, not sure how much this will help, but try removing the submit input and submitting the form via javascript. So for instance

<input id="submit-button" class="add-button" type="button" value="Create" />

Then instead of listening to the onsubmit, you can try

$('#submit-button').click(function(evt) {
    if(validationSuccess(...)) {
        $("#create-deck-form").submit();
    } else {
        //display whatever
    }
});

Now you're way should work too... but this way you can debug where you're problem is.... This should only submit once... good luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文