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


210

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

  • 押して Enter
  • HTMLFormElement.submit()JSでの使用

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

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

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

これまでの私の実験では、次のことが示されています。

  • 押すとEnter、Firefoxの、オペラと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>

回答:


115

あなたはJavascriptを(すなわち経由でフォームを送信した場合formElement.submit()、または何かに相当)、その後、どれも送信ボタンのは、成功したと見なされず、それらの値のいずれも提出されたデータには含まれていません。(を使用してフォームをsubmitElement.click()送信した場合、参照した送信はアクティブと見なされます。ここでは送信ボタンが明確であるため、これは実際には質問の送信に該当しませんが、含めたいと思いました。最初の部分を読み、JSフォームの送信を介して送信ボタンを成功させる方法を知りたい人のform.submit()ために。もちろん、フォームのonsubmitハンドラーはこの方法で起動しますが、経由しない場合は別の魚のやかんです...)

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

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

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


1
第2パラグラフについて:私の基本的な質問は、「ブラウザが送信コントロールを指定せずにフォームを送信する手段を提供する場合」の影響について、仕様に何かあるかどうかでした。しかし、私はダビデの返答から、そうではないと収集しました。IEについての私のポイントは、Enterキーを押すとフォームが送信され、送信ボタンが設定されないことでした。結果として、同じスクリプトに複数のフォームを送信する場合、それらを区別するために送信ボタンに依存することはできません。これは私が取り組んでいるプロジェクトで思い付きました。
スチュワート

1
非常に便利な最初のパラグラフブラケットセクション-ありがとうございます。
rbassett

63

HTML 4はそれを明示的にしません。現在のHTML5草案では、最初の送信ボタンをデフォルトにする必要があると規定しています

form要素のデフォルトボタンは、最初にボタンを提出して 、ツリーの順序を持つフォーム所有者のものである form要素。

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


わかりました、それはそれがすることになっているものです。使ってもいいですか?
Pacerier 2014年

HTML5で「暗黙の提出」を見てうれしいです。
Clint Pachl、2015年

61

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仕様では、非表示の要素をユーザーの操作から除外する必要があることが示されているため、機能しません。だから、代わりにそれを明白な視界に隠してください!

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

注:フォームをタブで移動しても、ビジュアル要素のフォーカスは表示されませんが、非表示のボタンが選択されます。この問題を回避するには、それに応じてtabindex属性を設定し、非表示の送信ボタンのtabindex属性を省略します。それが!重要なこれらのスタイルを促進するために場違いに見えるかもしれませんが、彼らは必要がありますこの修正プログラムに干渉から任意のフレームワークや既存のボタンのスタイルを防ぎます。また、これらのインラインスタイルは間違いなく不適切な形式ですが、ここでは概念を証明しています...量産コードを記述していません。


5
ありがとう。ディスプレイにつまずいた問題なし。ボタンを最小化する代わりに、ボタンをで囲むことでページの外に移動することもできます<div style="position: fixed; left: -1000px; top: -1000px />。もう1つ注意する必要があります。CSSを使用してボタンをページフローから最小化または移動すると、スクリーンリーダーにデフォルトのボタンが表示されるため、WAIの問題が発生する可能性があります。
Stefan Haberl 2012年

2
この詳細な回答をありがとう@James。
ネイサン

1
これでうまくいきました、ありがとう。これをボタンのborder:noneに追加する必要がありました。それを誠実に消えさせる
マクンバ

4
非表示ボタンのtabindex属性を-1に設定するだけです
tvanc

2
何の<input/>ためにあるの?
Sz。

16

この投稿は、誰かが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;
}
});
}); 

jQuery.Eventには常にその.wich属性があります。また、DOMにフォールバックする必要もありません.keyCode(または.charCodeその点については)。
Arjan

ここでのjQueryに関するもう1つの問題は、不要な二重クエリです。trueを返す必要がないため、さらにjQueryのバージョンは、Arjanが以前にアドバイスした削減を統合することについては本当に明確で不足しています。
soletan 2012

私はkeypressの代わりにkeydownを使用し(キーアップの待機を回避)、e.preventDefault();この関数の最初に追加して、「実際の」デフォルトボタンの実行を回避しました。本当にうまくいきます。
マット・ロイ

6

私は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。


19
悪いアイデア。JSが無効になっていると、フォームは機能しません。JSは控えめに使用する必要があります。
BalusC 2010年

7
JSがデフォルトでオフになっているブラウザーはほとんどなく、iPodのブラウザーもオフになっています。私が引用していたフォームでは、JS offはそれを役に立たなくします!JSの実行に大きく依存しています。
グラフィック

7
デフォルトでオフにされているかどうかにかかわらず、JSが無効になっている人は、このようなばかげた小さな障害を回避するためだけにスイッチをオンにする必要はありません。
Stewart

2
どのようなフォームに11個の送信ボタンがありますか?(好奇心
ベン

2
控えめなJavascriptを検証する最大の理由は、邪魔なJavascriptが面倒な傾向があるためです。私が考えていることをどのように修飾するかはわかりませんが、JSに完全に依存しているページを見ると、DOMを使用してトリッキーなことをしたり、サーバーで意図しない何かを実行したりできると思います。
サマンサブランハム、2012年

6

これは、次を使用して解決できます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 */
}

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

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


2

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

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

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

そのため、複数の送信ボタンとさまざまな可視性オプションを備えたfromを作成し、どのボタンがクリックされたかを通知するonclickイベントを作成することで、いくつかの基本的なテストを行いました:https : //jsfiddle.net/aqfy51om/1/

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

ウィンドウズ

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

OSX

  • Google Chrome 43
  • Safari 7.1.6

これらのブラウザのほとんどは、IEとSafariが適用された可視性オプションを除いて最初のボタンをクリックし、3番目のボタンをクリックしました。

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

編集 別のオプションは、ボタンをオフセットすることです(それでもfromの先頭にあります)style="position: absolute; left: -9999px; top: -9999px;"、IEで試してみました-機能しましたが、印刷など、他に何が失敗するのかわかりません。


1

あなたのコメントから:

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

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

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


確かに、それはこの質問を頼む:stackoverflow.com/questions/541869/...
スチュワート

1

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;

});

シンプルで問題を修正
toddmo

1

最初のボタンEnterが表示されているかどうかに関係なく常に最初のボタンに移動するのは奇妙ですshow/hide()。たとえば、jqueryを使用します。属性を追加.attr('disabled', 'disabled')すると、Enter送信ボタンを完全に受信できなくなります。たとえば、レコードダイアログで[挿入] / [編集] + [削除]ボタンの表示を調整するときに問題が発生します。ハックが少なく、挿入の前に編集を配置するだけで済みました

<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');

0

私のレシピ:

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

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

それらがクリックされた場合、それらは優先され、その値が渡されます。


2
しかし、この動作は標準で指定されているのでしょうか?また、ブラウザはそれを正しく実装すると信頼できますか?
スチュワート

良い質問。私はすべてのAブラウザー(yuiブラウザーマトリックスから)で動作するようにテストしました。これは、(標準の指定に関係なく)実際に使用できる最も一貫したものです
gcb

@yellowandredどうなる?後で見る
gcb 2013

1
私の間違い、私は{type = "hidden"}を変更しましたが、同じ 'name'の値に気づきませんでした。
黄色と赤

これはIE11またはFx30では機能しません。値は常に非表示の値に設定されます。
ジェイミーキットソン2014年

0

私が使用した別の解決策は、フォームにボタンを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>

次に、span要素をボタンのようにスタイルします。JSリスナーはスパンを監視し、クリックすると目的の操作を実行します。

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


1
JSを無効にしているユーザーのフォールバックは何ですか?
スチュワート

JSを無効にしたユーザーは、インターネットを使用できなくなります。これは、今日と同じくらい簡単です。
Christoffer Bubach 2016

0

HTML 4仕様

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

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

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

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


-2

編集:申し訳ありませんが、この回答を書いているとき、私は一般的な意味で送信ボタンについて考えていました。以下の答えは複数のtype="submit"ボタンに関するものではありません。1つだけを残しtype="submit"、もう1つをに変更するためtype="button"です。typeフォームを変更できる人を助けるために、参考のためにここに答えを残します:

Enterキーを押したときにどのボタンが押されたかを判断するには、それをでマークアップしtype="submit"、他のボタンはでマークしますtype="button"。例えば:

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

「ボタン」と入力しても、フォームは送信されません。クライアント側のスクリプトをトリガーするためにのみ使用されます。
スチュワート

正確に言うと、Enterキーを押すとブラウザがスキップし、タイプが「送信」のブラウザが実行されます。たとえば、タイプが「ボタン」のボタンを使用して、クリックで他のことを実行できます。反対票を削除してください。
ヘススカレラ2013

問題は、複数の送信ボタンに関するものでした。
スチュワート

私の例は、複数の送信ボタンに対して完全に有効です。タイプが「送信」のものは、押されたものとして動作するようにブラウザによって決定されたものです(これが問題でした)。次に、他のボタンを使用して、ボタンを送信ボタンとして使用することも、例にあるonClickイベントなどのJavaScriptイベントを使用することもできます。だから私の答えは関連性があり、反対票を投じる価値はありません。削除してください。
ヘススカレラ2013

1
そのうちの1つだけを「送信」と入力し、JavaScriptを使用して他のボタンを実装することにより、あいまいさを取り除くことを提案することがポイントである場合、これはグラフィックの返信の複製であるため、悪い考えとしてすでに却下されています。
スチュワート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.