web-dev-qa-db-ja.com

HTMLフォームのデフォルトの送信ボタンはどのように決定されますか?

フォームが送信されたが、特定のボタンではなく、

  • 押すことにより Enter
  • jSでHTMLFormElement.submit()を使用する

ブラウザは、押されたボタンとして使用する複数の送信ボタンがある場合、どのボタンを決定することになっていますか?

これは2つのレベルで重要です。

  • 送信ボタンに接続されたonclickイベントハンドラーの呼び出し
  • webサーバーに送り返されたデータ

これまでの私の実験は次のことを示しています。

  • 押すとき Enter、Firefox、OperaおよびSafariは、フォームの最初の送信ボタンを使用します
  • 押すとき Enter、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>
197
Stewart

JavaScript(formElement.submit()または同等のもの)を介してフォームを送信すると、noneの送信ボタンは成功したと見なされ、その値はどれにも含まれません送信されたデータ。 (submitElement.click()を使用してフォームを送信する場合、参照先の送信はアクティブと見なされます。ここでは、送信ボタンは明確であるため、これは実際にはあなたの質問の範囲には含まれませんが、これは、最初の部分を読んで、JSフォーム送信を介して送信ボタンを成功させる方法を知りたい人向けです。もちろん、フォームのonsubmitハンドラーは、この方法で起動しますが、form.submit()経由ではないので、 )

Textarea以外のフィールドでEnterキーを押してフォームが送信された場合、実際にユーザーエージェントがフォームの内容を決定します。 specs テキスト入力フィールドでEnterキーを使用してフォームを送信することについては何も言わない(ボタンにタブで移動し、スペースなどを使用してアクティブにすると、その特定の問題はありません)送信ボタンは明確に使用されます)。それが言っているのは、送信ボタンがアクティブになったときにフォームを送信する必要があるということだけです。たとえば、Enterキーを押す必要はありません。テキスト入力によりフォームが送信されます。

Internet Explorerは、ソースの最初に表示される送信ボタンを選択すると信じています。 FirefoxとOperaは、最も低いtabindexを持つボタンを選択し、他に何も定義されていない場合は最初に定義されたボタンに戻ると感じています。また、サブミットにデフォルト値以外の属性IIRCがあるかどうかに関して、いくつかの問題があります。

取り去るポイントは、ここで何が起こるかについての定義された標準がなく、それは完全にブラウザの気まぐれにあるということです-あなたがしていることは可能な限り、特定の行動に依存しないようにしてください。本当に知っておく必要がある場合は、さまざまなブラウザーバージョンの動作を見つけることができますが、しばらく前にこれを調査したときに、かなり複雑な条件がありました(もちろん、新しいブラウザーバージョンで変更される可能性があります)できればそれを避けるべきです!

107
Andrzej Doyle

Andrezjはほとんどそれを打ち付けました...しかし、これは簡単なクロスブラウザソリューションです。

次のような形式を取ります。

<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仕様では、非表示の要素はユーザーインタラクションから除外する必要があると示されているため、単にdisplay:none;のスタイルを追加するだけでは機能しません。そのため、代わりに目立たないように隠してください!

上記は、私が最終的に本番環境に導入したソリューションの例です。 Enterキートリガーを押すと、デフォルト以外の値が存在し、DOMのデフォルトの送信ボタンの前にある場合でも、デフォルトのフォーム送信が期待どおりに動作します。 JavaScriptハンドラーを回避しながら、明示的なユーザー入力とマウス/キーボードの相互作用のボーナス。

注:フォームをタブで移動しても、視覚要素のフォーカスは表示されませんが、非表示ボタンが選択されたままになります。この問題を回避するには、適宜tabindex属性を設定し、非表示の送信ボタンのtabindex属性を省略します。これらのスタイルを!importantにプロモートすることは場違いに思えるかもしれませんが、shouldは、フレームワークまたは既存のボタンスタイルがこの修正を妨げるのを防ぎます。また、これらのインラインスタイルは間違いなく貧弱な形式ですが、ここでは概念を実証しています...量産コードを記述していません。

60
James

HTML 4はそれを明示的にしません。現在のHTML5ワーキングドラフト は、最初の送信ボタンをデフォルトにする必要があることを指定しています

form要素のデフォルトボタンは、 tree order の最初の submit button です。 フォーム所有者 は、form要素です。

ユーザーエージェントがフォームを暗黙的に送信することをサポートしている場合(たとえば、一部のプラットフォームでは、テキストフィールドが暗黙的にフォームをフォーカスしている間に「Enter」キーを押すと) デフォルトボタン には、定義された アクティベーション動作 があり、ユーザーエージェントは その上で合成クリックアクティベーションステップ を実行します デフォルトボタン .

57
Quentin

誰かが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;
}
});
}); 
16

11個の送信ボタンを持つフォームがあり、ユーザーがEnterキーを押したときに常に最初の送信ボタンを使用します。フォームに複数の送信ボタンを配置するのは良い考えではないことをお勧めしますが、これを行う最善の方法は、フォームの唯一の送信ボタンとしてデフォルトのボタンを使用することです。他のボタンは「TYPE = BUTTON」にして、JavaScriptで独自の送信ルーチンを呼び出すonClickイベントを追加する必要があります。このようなもの :-

<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
graphic

これは 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 */
}

説明
フレックスボックスを使用すると、CSSルールdisplay: flexを使用して、flex-direction: row-reverseを使用するコンテナー内の要素の順序を逆にすることができます。これには、CSSまたは非表示要素は必要ありません。フレックスボックスをサポートしていない古いブラウザーの場合、実行可能なソリューションは得られますが、要素は元に戻りません。

デモ
http://codepen.io/Godwin/pen/rLVKjm

5
Godwin

次のように送信を別のページにリダイレクトする送信ボタンが中央にあったため、同じ質問に苦労しました:

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

ユーザーがEnterキーを押すと、別の送信ボタンの代わりにこのボタンがクリックされました。

そこで、複数の送信ボタンと異なる可視性オプションを使用してfromを作成し、どのボタンがクリックされたかを警告するonclickイベントによって、いくつかのプリミティブテストを行いました。 https://jsfiddle.net/aqfy51om/1/

テストに使用したブラウザとOS:

WINDOWS

  • Google Chrome 43(c'mon google:D)
  • Mozilla Firefox 38
  • Internet Explorer 11
  • Opera 30.0

OSX

  • Google Chrome 43
  • Safari 7.1.6

これらのブラウザのほとんどは、3番目のボタンをクリックした可視性オプションexept 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;"でコンテナにラップ

EDITもう1つのオプションは、ボタンをオフセットすることです(fromの先頭で)style="position: absolute; left: -9999px; top: -9999px;"、IEで試してみました_-うまくいきましたが、印刷など、他に何が台無しになるかわかりません。

2
Kristian

1つのフォームに複数の送信ボタンがあり、ユーザーが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;

});
1
axiom82

あなたのコメントから:

その結果、同じスクリプトに複数のフォームを送信する場合、送信ボタンに頼ってそれらを区別することはできません。

<input type="hidden" value="form_name" />を各フォームにドロップします。

Javascriptで送信する場合:送信イベントをフォームに追加し、ボタンのイベントをクリックしないでください。 Saavyユーザーはマウスにあまり触れません。

1
Ryan Florence

最初のボタンEnterが表示されているかどうかに関係なく、常に最初のボタンに移動するのは奇妙です。 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');
1
TMa

HTML 4仕様 から:

フォームに複数の送信ボタンが含まれる場合、アクティブ化された送信ボタンのみが成功します。

これは、複数の送信ボタンがあり、アクティブ化(クリック)されていない場合、成功するものはないことを意味しています。

そして、私はこれが理にかなっていると主張します:複数の送信ボタンを持つ巨大なフォームを想像してください。上部に「このレコードを削除」ボタンがあり、続いて多くの入力が続き、下部に「このレコードを更新」ボタンがあります。ユーザーがフォームの下部のフィールドでEnterキーを押すと、暗黙的に上部から「このレコードを削除」がヒットしたことを疑うことはありません。

したがって、ユーザーが定義(クリック)しない最初のボタンまたは他のボタンを使用することはお勧めできません。それにもかかわらず、ブラウザはもちろんそれを行っています。

0
Christopher K.

私のレシピ:

<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>

どのボタンも「クリック」されない場合、デフォルトの非表示フィールドを送信します。

クリックされた場合、設定があり、その値が渡されます。

0
gcb

私が使用した別の解決策は、フォームにボタンを1つだけ配置し、他のボタンを偽造することです。

以下に例を示します。

<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リスナーはスパンを監視し、クリックすると目的の操作を実行します。

必ずしもすべての状況に適しているわけではありませんが、少なくとも簡単に実行できます。

0