防止用户通过按Enter键提交表单

982

我有一个调查网站,在用户填写问卷时,似乎存在按下回车键(原因未知)并且在没有点击提交按钮的情况下,意外提交了问卷表单的问题。是否有方法可以防止这种情况发生?

我在调查中使用HTML、PHP 5.2.9和jQuery。


3
不要使用表单标签,自定义ajax请求。但是当然,你可以继续使用按键监听和预防措施,那就是我会做的事情。 - jancha
我不使用表单标签,因为我更喜欢通过非传统的方式(例如:在字段失去焦点时提交某些字段等)通过ajax请求处理表单。您还可以创建一个特殊的监听器来捕获Enter键并仅在需要时处理它。 - Juan
36个回答

1037

你可以使用类似于的方法

$(document).ready(function() {
  $(window).keydown(function(event){
    if(event.keyCode == 13) {
      event.preventDefault();
      return false;
    }
  });
});

在阅读原帖的评论时,为了使其更易用并允许用户在填写完所有字段后按下Enter键:
function validationFunction() {
  $('input').each(function() {
    ...

  }
  if(good) {
    return true;
  }
  return false;
}

$(document).ready(function() {
  $(window).keydown(function(event){
    if( (event.keyCode == 13) && (validationFunction() == false) ) {
      event.preventDefault();
      return false;
    }
  });
});

9
我目前只是寻求一个快速解决方案,没有时间实施验证项目。我感谢大家的回答,但在此期间,这是我要采用的答案。谢谢。 - DForck42
11
该方法存在缺陷,因为当用户焦点在提交按钮上时,会阻止其通过按回车键提交表单。最佳解决方案是BalusC提出的方法,在仅当用户焦点在表单输入上时才中断回车键。 - Anson Kao
3
我曾经遇到过这种情况(仅适用于Internet Explorer),需要将keydown事件绑定到document上,而非window,才能使其正常工作。 - MartinHN
18
你可能需要在条件语句中添加&& !$(document.activeElement).is('textarea'),否则文本框内的换行符会被阻止(至少在IE浏览器中是这样)。 - Flash
4
这对我有用。但这也防止在文本区域中添加换行符。 - César León
显示剩余12条评论

812

禁止在任何地方按下回车键

如果你的表单中没有 <textarea> ,那么只需在<form>中添加以下内容:

<form ... onkeydown="return event.key != 'Enter';">

或者使用jQuery:

$(document).on("keydown", "form", function(event) { 
    return event.key != "Enter";
});

这将导致在表单中的每个按键都会被检查 key。如果不是Enter,则返回true,继续进行任何操作。如果是Enter,则返回false,任何操作都会立即停止,因此表单不会被提交。

keydown 事件比 keyup 更好,因为keyup 太晚了以至于无法阻止表单提交。历史上还有一个 keypress,但它已经被弃用,同样地 KeyboardEvent.keyCode 也已被弃用。您应该使用KeyboardEvent.key 来代替,它将返回正在按下的键的名称。当检查Enter时,这将同时检查13(普通输入)和108(数字键盘输入)。

请注意,有些答案建议使用 $(window) 而不是 $(document) 来处理 keydown/keyup,但在 IE<=8 中这样做无效,因此如果您也想覆盖这些用户,则不是一个好选择。

仅允许


18
这个应该是最好的答案,因为它还涉及到包括文本区域在内的表单,并更好地解释了事件传播。 - foobar
3
这应该是正确答案,因为它不会干扰其他回车键监听器,就像 Bootstrap tags input(https://bootstrap-tagsinput.github.io/bootstrap-tagsinput/examples/)一样。 - Maroun Melhem
1
我选择了这个解决方案,因为我只需要添加不到一行的代码。其他条件相同的情况下,较短的答案更好。 - Jonathon Philip Chambers
做得好!已经修复了错误。 - Antimatterr
我不喜欢这个答案,因为它没有击中问题的核心。它甚至没有理解问题。这是一个盲目的修复,意味着如果你不了解根本原因,它会反弹回来。我更喜欢下面Daniel Trebien的答案,因为它进行了根本原因分析并提供了更轻量级的解决方案。 - Philippe F
显示剩余4条评论

294

W3C HTML5规范的第4.10.22.2节隐式提交指出:

form元素的默认按钮是该form元素拥有者为该form元素的提交按钮中,在树顺序中的第一个。

如果用户代理支持让用户隐式提交表单(例如,在某些平台上,当文本字段聚焦时按“Enter”键会隐式提交表单),那么对于具有已定义激活行为默认按钮的表单进行隐式提交必须导致用户代理在运行合成点击激活步骤上对该默认按钮进行操作。

注意:因此,如果默认按钮被禁用,则当使用此类隐式提交机制时不会提交表单。(当禁用时,按钮没有激活行为。)

因此,一种符合标准的方法是在表单中放置一个已禁用的提交按钮作为第一个提交按钮,以禁用任何隐式提交表单的功能:

<form action="...">
  <!-- Prevent implicit submission of the form -->
  <button type="submit" disabled style="display: none" aria-hidden="true"></button>

  <!-- ... -->

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

这种方法的一个好处是它可以在没有 JavaScript 的情况下运行; 无论 JavaScript 是否启用,都需要符合标准的网络浏览器来防止隐式表单提交。


4
一方面,这种方法简单且可以避免已接受答案所建议的所有问题。另一方面,它似乎有点利用了标准。赞扬使用了aria-* 属性。我希望能听到更多反馈意见。 - png
4
也可以作为 <input type="submit" disabled style="display: none" aria-hidden="true" />,这样可以减少页面大小几个字符。 :-P - new name
9
IE 11 无论如何都会提交。 - CamaroSS
5
这在Safari上不起作用,其他浏览器似乎没问题。 - Martin Belcher - AtWrk
16
Safari是新的IE。 - twistedpixel
显示剩余13条评论

76
如果你使用一个脚本来实际提交表单,那么你可以在 onsubmit 处理程序中添加 "return false" 语句,像这样:

<form onsubmit="return false;">

JavaScript 中调用表单的 submit() 方法不会触发事件。

只针对Chrome浏览器有效,这将禁用提交按钮,如果您想在提交按钮本身上触发onlick事件,则可以使用这种方法。 Ajax提示:在返回之前添加函数调用,用户仍然可以使用回车键而不将表单提交到页面。 - Dennis Heiden
在Chrome、IE-11和Firefox上对我有效,并且是最简单的解决方案。禁用整个页面部分的回车键,就像一些答案所做的那样,似乎过于极端且容易出现错误。 - Yogi

70

为了防止表单被提交,我必须捕获与按键相关的三个事件:

    var preventSubmit = function(event) {
        if(event.keyCode == 13) {
            console.log("caught ya!");
            event.preventDefault();
            //event.stopPropagation();
            return false;
        }
    }
    $("#search").keypress(preventSubmit);
    $("#search").keydown(preventSubmit);
    $("#search").keyup(preventSubmit);

你可以将上述所有内容组合成一个简洁的版本:

    $('#search').bind('keypress keydown keyup', function(e){
       if(e.keyCode == 13) { e.preventDefault(); }
    });

7
你可以将最后三个选择器连接起来,或者使用一个方法同时绑定多个事件,例如 $("#search").bind('keypress keyup keydown',preventSubmit) - Moak
因为在ASP.NET Web表单中,所有内容都必须嵌套在<form>标签中,所以回车键提交表单...这个解决方案禁用了回车键并解决了问题,感谢@Dave!然后我通过id启用了某些字段的回车键。 - Ian Campbell
@Upgradingdave,你是如何写出"log()"而不是"console.log()"的? - radbyx
1
@radbyx ... 很好的发现,应该是 console.log,我已经更新了我的答案。 - Upgradingdave
请注意,使用 keypress keyup keydown 会触发 if 条件中的任何代码 两次 - Avatar

24

使用:

$(document).on('keyup keypress', 'form input[type="text"]', function(e) {
  if(e.keyCode == 13) {
    e.preventDefault();
    return false;
  }
});

这个解决方案适用于网站上的所有表单(包括通过Ajax插入的表单),只是防止在输入文本框中按下 Enter 键。将它放在一个文档就绪函数中,然后忘掉这个问题一辈子。


我认为原始答案 e.which 很好,不需要更改为 e.keyCode。两者都返回回车键的值 13。请参见 https://dev59.com/o2855IYBdhLWcg3wNhd1#4471635 和 https://dev59.com/OXXYa4cB1Zd3GeqP7o96#18184976。 - goodeye
2
此解决方案解决了两个问题:1)不要在按下回车键时提交表单;2)允许在文本区域中按下回车键。 - PlanetUnknown

22

我还不能评论,所以我会发表一个新回答。

被接受的答案还可以,但它无法在数字键盘输入中停止提交。至少在当前版本的Chrome中是如此。我不得不改变按键代码条件,然后它就能正常工作。

if(event.keyCode == 13 || event.keyCode == 169) {...}

6
Enter和Return之间的区别 - 许多销售点操作员仅使用数字键盘。+1 - helloserve
9
现在(2015年5月21日),在Chrome 42、IE 11和FireFox 36中,无论是普通回车还是小键盘回车,keyCode都是13。 - Cliff Burton

22

与其阻止用户按下 Enter,这可能看起来很不自然,你可以保持表单不变并添加一些额外的客户端验证:当调查未完成时,结果不会发送到服务器,用户会收到一个好消息,告诉他们需要完成什么才能完成表单。如果您正在使用jQuery,请尝试使用Validation插件:

http://docs.jquery.com/Plugins/Validation

这将需要比捕获 Enter 按钮更多的工作,但肯定会提供更丰富的用户体验。


16
听起来不错,但可选字段会带来问题,用户可能会因为错误而按下回车键,导致表单被提交。我不知道你如何确定“调查未完成”的情况,除非将每个字段都设置为必填项(不能有默认选择,也不能留空……)。 - Christophe Roussy

21

一个简单好用的jQuery解决方案:

$("form").bind("keypress", function (e) {
    if (e.keyCode == 13) {
        return false;
    }
});

1
+1 我正在寻找一个 jQuery 的替代方案,而不是使用普通的 JS,例如 var key = event.keyCode || event.which; if (key == 13) return false; - RaphaelDDL
1
从技术上讲,这仍然是POJ,只是用了一个更简单的jQuery包装器。你提供的代码几乎是一样的东西。 - Eonasdan

21

完全不同的方法:

  1. 在表单中第一个 <button type="submit"> 将会在按下 Enter 键时被激活。
  2. 即使该按钮带有 style="display:none; 属性,也是如此。
  3. 该按钮的脚本可以返回 false,以中止提交过程。
  4. 您仍然可以使用另一个 <button type=submit> 提交表单。只需返回 true 即可级联提交。
  5. 在真正的提交按钮聚焦时按下 Enter 将激活真正的提交按钮。
  6. <textarea> 或其他表单控件内按下 Enter 将会按照正常方式执行。
  7. <input> 表单控件内按下 Enter 将触发第一个 <button type=submit>,其返回值为 false,因此不会发生任何事情。

因此:

<form action="...">
  <!-- insert this next line immediately after the <form> opening tag -->
  <button type=submit onclick="return false;" style="display:none;"></button>

  <!-- everything else follows as normal -->
  <!-- ... -->
  <button type=submit>Submit</button>
</form>

1
在Chrome和Firefox中,甚至更短的版本是<button disabled style="display:none;"><button>,这也有不需要JS即可工作的优点。Safari只是忽略了按钮,所以其他的东西会像平常一样发生。 - Erics
1
我真的不喜欢“忽略13个按键码”的方式,所以我开始思考一些简单而又巧妙的方法,这个想法突然浮现在我的脑海中,当我滚动这个页面时,我看到了这个帖子:)。对于共同的想法和当然是最好的解决方案,我点赞。 - Jalali Shakib
哦,太棒了,最后一个按钮可以像这样设置,以防止在快速点击时出现重复提交:<button onclick="this.disabled=true;this.form.submit();" type="submit"">提交</button> - Arash
@ArashMoosapour 请不要在提交按钮获得焦点时禁用它们 - 这样做会丢失焦点,并且会带来无障碍问题。 - Erics
1
我在我的Firefox中没有看到这个隐藏按钮产生任何效果。 - Роман Коптев
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接