代码之家  ›  专栏  ›  技术社区  ›  Stewart

如何确定HTML表单上的默认提交按钮?

  •  195
  • Stewart  · 技术社区  · 15 年前

    如果表单是通过任何特定按钮提交的,例如

    • 按压 进入
    • 使用 HTMLFormElement.submit() 在JS中

    浏览器应该如何确定多个提交按钮中的哪个按钮(如果有)用作按下的按钮?

    这在两个层面上很重要:

    • 调用一个 onclick 附加到提交按钮的事件处理程序
    • 发送回Web服务器的数据

    到目前为止,我的实验表明:

    • 按压时 进入 ,firefox、opera和safari使用表单中的第一个提交按钮
    • 按压时 进入 ,IE使用第一个提交按钮,或者根本不使用,这取决于我还没弄清楚的条件。
    • 所有这些浏览器都完全不使用JS提交

    标准怎么说?

    如果有帮助的话,这里是我的测试代码(PHP只与我的测试方法相关,而与我的问题本身无关)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Test</title>
    </head>
    
    <body>
    
    <h1>Get</h1>
    <dl>
    <?php foreach ($_GET as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
    </dl>
    
    <h1>Post</h1>
    <dl>
    <?php foreach ($_POST as $k => $v) echo "<dt>$k</dt><dd>$v</dd>"; ?>
    </dl>
    
    <form name="theForm" method="<?php echo isset($_GET['method']) ? $_GET['method'] : 'get'; ?>" action="<?php echo $_SERVER['SCRIPT_NAME']; ?>">
        <input type="text" name="method" />
        <input type="submit" name="action" value="Button 1" onclick="alert('Button 1'); return true" />
        <input type="text" name="stuff" />
        <input type="submit" name="action" value="Button 2" onclick="alert('Button 2'); return true" />
        <input type="button" value="submit" onclick="document.theForm.submit();" />
    </form>
    
    </body></html>
    
    14 回复  |  直到 6 年前
        1
  •  104
  •   Andrzej Doyle    15 年前

    如果您通过javascript提交表单(即 formElement.submit() 或者其他类似的东西)。 没有人 其中个提交按钮被认为是成功的,它们的任何值都不包含在提交的数据中。(请注意,如果您使用 submitElement.click() 然后,您引用的提交被认为是活动的;这并不属于您问题的范围,因为这里的提交按钮是明确的,但我想我会将它包括在阅读第一部分的人中,并想知道如何通过JS表单提交使提交按钮成功。当然,表单的onsubmit处理程序仍将以这种方式激发,而不会通过 form.submit() 那又是一壶鱼……)

    如果表单是通过在非文本区域字段中按Enter提交的,那么它实际上是由用户代理来决定它在这里想要什么。这个 specs 在文本输入字段中,不要说任何关于使用Enter键提交表单的内容(如果您切换到某个按钮并使用空格或其他方式激活它,则不会有任何问题,因为特定的提交按钮是明确使用的)。它所说的是,当一个提交按钮被激活时,一个表单必须被提交,这甚至不是一个要求,即按回车键,例如文本输入将提交表单。

    我相信Internet Explorer会选择源代码中第一个出现的提交按钮;我觉得Firefox和Opera会选择TabIndex最低的按钮,如果没有其他定义,则会返回到第一个定义的按钮。提交是否具有非默认值属性IIRC也有一些复杂的问题。

    关键是这里没有明确的标准,完全是由浏览器的一时冲动决定的-尽可能在你做的任何事情中,尽量避免依赖任何特定的行为。如果你真的必须知道,你可能会发现各种浏览器版本的行为,但当我调查这一段时间前,有一些相当复杂的条件(当然,这会随着新的浏览器版本而改变),我建议你尽可能避免它!

        2
  •  59
  •   James    11 年前

    安德烈兹基本上把它钉牢了…但这里有一个简单的跨浏览器解决方案。

    采取如下形式:

    <form>
        <input/>
        <button type="submit" value="some non-default action"/>
        <button type="submit" value="another non-default action"/>
        <button type="submit" value="yet another non-default action"/>
    
        <button type="submit" value="default action"/>
    </form>
    

    重构为:

    <form>
        <input/>
    
        <button style="overflow: visible !important; height: 0 !important; width: 0 !important; margin: 0 !important; border: 0 !important; padding: 0 !important; display: block !important;" type="submit" value="default action"/>
    
        <button type="submit" value="some non-default action"/>
        <button type="submit" value="another non-default action"/>
        <button type="submit" value="yet another non-default action"/>
        <button type="submit" value="still another non-default action"/>
    
        <button type="submit" value="default action"/>
    </form>
    

    由于W3C规范指示多个提交按钮是有效的,但忽略了用户代理应该如何处理这些按钮的指导,因此浏览器制造商可以根据自己的需要来实现这些按钮。我发现他们要么提交表单中的第一个提交按钮,要么在当前具有焦点的表单字段之后提交下一个提交按钮。

    不幸的是,只需添加 显示:无; 无法工作,因为W3C规范指示应从用户交互中排除任何隐藏元素。所以把它藏在显眼的地方!

    上面是我最终投入生产的解决方案的一个例子。按Enter键将触发默认表单提交,这是预期的行为,即使存在其他非默认值并且位于DOM中的默认提交按钮之前。在避免使用javascript处理程序的同时,与显式用户输入进行鼠标/键盘交互的好处。

    注意:在窗体中切换将不会显示任何可视元素的焦点,但仍将导致选择不可见按钮。为了避免这个问题,只需相应地设置tabindex属性,并在不可见的提交按钮上省略tabindex属性。虽然推广这些风格似乎不合适!重要的是,他们 应该 防止任何框架或现有按钮样式干扰此修复。而且,这些内联样式的形式确实很差,但我们在这里证明了概念…不写生产代码。

        3
  •  57
  •   Rudie    7 年前

    HTML 4不显式。当前HTML5工作草案 specifies that the first submit button must be the default :

    form 元素的默认按钮是 第一 submit button 在里面 tree order 谁的 form owner 那是 形式 元素。

    如果用户代理支持让用户提交表单 隐式(例如,在某些平台上,点击“回车”键 当文本字段集中时,隐式提交表单),然后 这样做是为了 default button 有定义 activation behavior 必须使用户代理 run synthetic click activation steps 在那 默认按钮 .

        4
  •  16
  •   Jeremy Meo    12 年前

    我认为如果有人想用jquery来做这篇文章会有所帮助:

    http://greatwebguy.com/programming/dom/default-html-button-submit-on-enter-with-jquery/

    基本解决方案是:

    $(function() {
        $("form input").keypress(function (e) {
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
            $('input[type=submit].default').click();
            return false;
        } else {
            return true;
        }
        });
    });
    

    另一个我喜欢的是:

    jQuery(document).ready(function() {
    $("form input, form select").live('keypress', function (e) {
    if ($(this).parents('form').find('button[type=submit].default, input[type=submit].default').length <= 0)
    return true;
    
    if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
    $(this).parents('form').find('button[type=submit].default, input[type=submit].default').click();
    return false;
    } else {
    return true;
    }
    });
    }); 
    
        5
  •  6
  •   graphic    14 年前

    我有一个表单,上面有11个提交按钮,当用户按下Enter时,它总是使用第一个提交按钮。我在别处读到,在一个表单上有多个提交按钮不是一个好主意(坏做法),最好的方法是将您想要的按钮作为默认按钮,作为表单上唯一的提交按钮。其他按钮应该做成“type=button”,并添加一个onclick事件,调用您自己的javascript提交例程。类似这样的事情:

    <SCRIPT Language="JavaScript">
    function validform()
    {
      // do whatever you need to validate the form, and return true or false accordingly
    }
    
    function mjsubmit()
    {
      if (validform()) { document.form1.submit(); return true;}
      return false;
    }
    </SCRIPT>
    <INPUT TYPE=BUTTON NAME="button1" VALUE="button1" onClick="document.form1.submitvalue='button1'; return mjsubmit();">
    <INPUT TYPE=BUTTON NAME="button2" VALUE="button2" onClick="document.form1.submitvalue='button2'; return mjsubmit();">
    <INPUT TYPE=SUBMIT NAME="button3" VALUE="button3" onClick="document.form1.submitvalue='button3'; return validform();">
    <INPUT TYPE=BUTTON NAME="button4" VALUE="button4" onClick="document.form1.submitvalue='button4'; return mjsubmit();">
    

    这里,button3是默认的,尽管您以编程方式使用其他按钮提交表单,但mjsubmit例程会验证它们。Hth.

        6
  •  4
  •   Godwin    8 年前

    现在可以使用 flexbox :

    HTML

    <form>
        <h1>My Form</h1>
        <label for="text">Input:</label>
        <input type="text" name="text" id="text"/>
    
        <!-- Put the elements in reverse order -->
        <div class="form-actions">
            <button>Ok</button> <!-- our default action is first -->
            <button>Cancel</button>
        </div>
    </form>
    

    CSS

    .form-actions {
        display: flex;
        flex-direction: row-reverse; /* reverse the elements inside */
    }
    

    解释
    使用flex box,我们可以颠倒使用 display: flex 通过使用CSS规则: flex-direction: row-reverse . 这不需要CSS或隐藏元素。对于不支持flexbox的旧浏览器,它们仍然可以得到一个可行的解决方案,但元素不会反转。

    演示
    http://codepen.io/Godwin/pen/rLVKjm

        7
  •  2
  •   Kristian    9 年前

    由于在将提交重定向到另一个页面的中间有提交按钮,所以我也遇到了同样的问题,如:

    <button type="submit" onclick="this.form.action = '#another_page'">More</button>
    

    当用户按Enter键时,单击此按钮而不是另一个提交按钮。

    所以我做了一些基本的测试,通过创建一个包含多个提交按钮和不同可见性选项的From,然后onclick事件警报单击了哪个按钮: https://jsfiddle.net/aqfy51om/1/

    用于测试的浏览器和操作系统:

    窗户

    • 谷歌Chrome43(C'mon google:D)
    • Mozilla火狐38
    • Internet Explorer 11
    • 歌剧30

    OSX

    • 谷歌Chrome 43
    • Safari 7.1.6

    尽管应用了可见性选项,但大多数浏览器还是单击了第一个按钮。 执行IE和Safari 点击了第三个按钮,“隐藏”容器内的“可见”按钮:

    <div style="width: 0; height: 0; overflow: hidden;">
        <button type="submit" class="btn btn-default" onclick="alert('Hidden submit button #3 was clicked');">Hidden submit button #3</button>
    </div>
    

    所以我的建议是:

    如果表单有多个具有不同含义的提交按钮,则在表单开头包含具有默认操作的提交按钮,该操作可以是:

    1. 完全可见
    2. 用容器包装 style="width: 0; height: 0; overflow: hidden;"

    编辑 另一个选项可能是偏移按钮(仍在起始处) style="position: absolute; left: -9999px; top: -9999px;" ,刚在IE-Worked中尝试过,但我不知道它还能搞砸什么,例如打印。

        8
  •  1
  •   Ryan Florence    15 年前

    根据您的评论:

    结果是,如果你有 多个表单提交到同一个表单 脚本,不能依赖提交 按钮来区分它们。

    我放弃了 <input type="hidden" value="form_name" /> 进入每一种形式。

    如果使用javascript提交:将提交事件添加到表单,而不是单击事件按钮。Saavy用户不经常触摸鼠标。

        9
  •  1
  •   axiom82 Joeytje50    10 年前

    当您在一个表单中有多个提交按钮,并且用户按Enter键从文本字段提交表单时,此代码将通过从按键事件调用表单上的提交事件来覆盖默认功能。这是代码:

    $('form input').keypress(function(e){
    
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){ $(e.target).closest('form').submit(); return false; }
        else return true;
    
    });
    
        10
  •  1
  •   TMa    9 年前

    奇怪的是第一个按钮 进入 始终转到第一个按钮,无论是否可见,例如使用jquery show/hide() . 添加属性 .attr('disabled', 'disabled') 完全禁止接收输入提交按钮。这是一个问题,例如调整时 插入/编辑+删除 记录对话框中的按钮可见性。我发现少了一些粗俗和简单的地方 编辑 在前面 插入

    <button type="submit" name="action" value="update">Update</button>
    <button type="submit" name="action" value="insert">Insert</button>
    <button type="submit" name="action" value="delete">Delete</button>
    

    并使用javascript代码:

    $("#formId button[type='submit'][name='action'][value!='insert']").hide().attr('disabled', 'disabled');
    $("#formId button[type='submit'][name='action'][value='insert']").show().removeAttr('disabled');
    
        11
  •  0
  •   gcb    13 年前

    我的食谱:

    <form>
    <input type=hidden name=action value=login><!-- the magic! -->
    
    <input type=text name=email>
    <input type=text name=password>
    
    <input type=submit name=action value=login>
    <input type=submit name=action value="forgot password">
    </form>
    

    如果未单击任何按钮,则将发送默认隐藏字段。

    如果单击它们,则它们具有首选项,并且传递它的值。

        12
  •  0
  •   Johan Fredrik Varen    12 年前

    我使用的另一个解决方案是在表单中只使用一个按钮,并伪造其他按钮。

    下面是一个例子:

    <form>
      <label for="amount">Amount of items</label>
      <input id="amount" type="text" name="amount" />
      <span id="checkStock" class="buttonish">Check stock</span>
      <button type="submit" name="action" value="order">Place order</button>
    </form>
    

    然后我将跨距元素的样式设置为按钮。JS监听器观察跨度并在单击后执行所需的操作。

    不一定适合所有情况,但至少很容易做到。

        13
  •  0
  •   Christopher K. cweiske    12 年前

    HTML 4 spec :

    如果表单包含多个提交按钮,则只有激活的 提交按钮成功。

    这意味着,如果提交按钮超过1个且未激活(单击),则无一个按钮应成功。

    我认为这是有道理的: 想象一个有多个提交按钮的巨大表单。在顶部有一个“删除此记录”按钮,随后会有很多输入,在底部有一个“更新此记录”按钮。当用户在表单底部的字段中点击Enter时,他永远不会怀疑自己从顶部隐式地点击了“删除此记录”。

    因此,我认为使用用户没有定义(单击)的第一个或任何其他按钮不是一个好主意。 当然,浏览器也在这样做。

        14
  •  -2
  •   Jesús Carrera    10 年前

    编辑: 抱歉,在写这个答案的时候,我在考虑一般意义上的提交按钮。下面的答案不是关于多重的 type="submit" 按钮,因为它只留下一个 类型=“提交” 把另一个换成 type="button" . 我把答案留在这里作为参考,以防有人能改变 type 以它们的形式:

    要确定按Enter键时按下的按钮,可以用 类型=“提交” ,其他按钮用 类型=“按钮” . 例如:

    <input type="button" value="Cancel" />
    <input type="submit" value="Submit" />