質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.10%

submitイベントハンドラ関数の中で <input type="submit"> を得るには?

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 6,807

score 16919

submit イベントハンドラ関数の中で <input type="submit"> を得る方法はないでしょうか。

<form>
  <p><input type="text" name="id"></p>
  <p>
    <input type="submit" value="submit1">
    <input type="submit" value="submit2">
  </p>
</form>
<script>
'use strict';
document.querySelector('form').addEventListener('submit', function (event) {
  // ここで submit ボタンを取得したい
  console.log(event.type, event.target);
  event.preventDefault();
}, false);
</script>

 - submitイベントハンドラ関数内で input[type=submit] を参照したい - JSFiddle

click イベントで得られるのは分かりますが、submit イベントハンドラ関数のスコープに引き渡す為に面倒な手順が必要になるので積極的に使いたくはありません。

'use strict';
(function () {
    function handleSubmit (event) {
      console.log(event.type, this.submit);
      console.log(event.type, 'activeElement', event.target.ownerDocument.activeElement);
      event.preventDefault();
      this.submit = null;
    }

    function handleClick (event) {
      var input = event.target;

      if (input.tagName === 'INPUT' && input.type === 'submit') {
        this.submit = input;
        console.log(event.type, input);
      }
    }

    function handleClickSubmit (event) {
      switch (event.type) {
        case 'click':
          handleClick.call(this, event);
          break;
        case 'submit':
          handleSubmit.call(this, event);
          break;
      }
    }

    function main () {
      var form = document.querySelector('form'),
          listener = {
            handleEvent: handleClickSubmit,
            submit: null
          };

      form.addEventListener('submit', listener, false);
      form.addEventListener('click', listener, false);
    }

    main();
}());
click イベントと併用して submit イベントハンドラ関数内で input[type=submit] を得る - JSFiddle

何かスマートな解決法がないものでしょうか。

(2015/11/24 21:36追記)
click イベントを併用するコードを追記しました。
現状ではこのコードが最善だと思っていますが、更にスマートな方法を求めています。

(2015/11/26 21:20追記)
listener オブジェクトを共有する事で handleSubmit 上位スコープに listner オブジェクトを置かなくて済むようにコードを修正しました。

(2015/12/02 21:38追記)
eripong さんに Firefox 独自拡張の event.explicitOriginalTarget を紹介して頂きました。
Event.explicitOriginalTarget - Web API インターフェイス | MDN
click イベントと併用して submit イベントハンドラ関数内で input[type=submit] を得る - JSFiddle
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

汚い方法ですが、clickイベントでformにinputを入れておくと、できました。

click イベントでformに保存して submit イベントハンドラ関数内で input[type=submit] を得る - JSFiddle

'use strict';
(function () {
  function handleSubmit (event) {
    var form = event.target;
    if (form.submitElement) {
      console.log(event.type, form.submitElement);
      form.submitElement = null;
    }
    event.preventDefault();
  }

  function handleClick (event) {
    var input = event.target;

     if (input.tagName === 'INPUT' && input.type === 'submit') {
       input.form.submitElement = input;
     }
  }

  function main () {
    var form = document.querySelector('form');

    form.addEventListener('submit', handleSubmit, false);
    form.addEventListener('click', handleClick, false);
  }

  main();
}());

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/26 10:56 編集

    http://discourse.wicg.io/t/extend-submit-events-add-the-button-element-that-triggered-the-submit/406/3
    http://stackoverflow.com/questions/2066162/how-can-i-get-the-button-that-caused-the-submit-from-the-form-submit-event
    でも議論されていますね。
    Firefoxにはevent.originalEvent.explicitOriginalTargetというプロパティがあるらしいです。
    他は、clickと連携するか、document.activeElementを使うかなど、
    この場で議論されているものと大差ないように見えます。

    キャンセル

  • 2015/11/26 22:25

    Event#explicitOriginalTarget は素晴らしいですね。
    非標準なので標準化される未来を望みます。
    とりあえず、Event#explicitOriginalTarget の互換コードを書けば良いと思いましたが、Polyfill 的な実装にすると前方互換性が失われてしまうのでどうしたものか…。

    キャンセル

  • 2015/12/02 21:39

    - submit ハンドラ関数の event オブジェクトに event#explicitOriginalTarget の拡張を加える
    - submit イベント発火後に "-custom-submit" イベントを発火させて event#explicitOriginalTarget の拡張を加える
    いろいろ方法を考えましたが、上手い落としどころが見つかりませんでした。
    他に代案もなさそうなので、一度締め切りたいと思います(将来的に希望に適うメソッド、プロパティが出てきましたら紹介頂ければ幸いです)。
    今回は Firefox 独自拡張であるものの Event#explicitOriginalTarget という私の期待通りの動作になるプロパティを紹介してくれた eripong さんをベストアンサーとさせて頂きます。
    http://jsfiddle.net/wz8e2enL/6/

    キャンセル

0

ちょっときたない方法ですが、こういう方法がありました。

<form>
  <input type="submit" value="submit1">
  <input type="submit" value="submit2">
</form>
<script>
'use strict';
document.querySelector('form').addEventListener('submit', function (event) {
    // 現在フォーカスがある要素を取得(submit直後ならクリックされたボタンになっているはず)
    var clickedButton = document.activeElement;
    console.log(clickedButton);
    console.log(event.type, event.target);
    event.preventDefault();
}, false);
</script>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/24 20:29

    input[type="text"]のEnter入力でsubmitが走った時は意図した通りに動かないです。

    キャンセル

  • 2015/11/24 21:13 編集

    回答ありがとうございます。
    やはり、一筋縄ではいかないようですね。
    input[type=text] の Enter にも対応させるとなると keydown と組み合わせる必要があってかなり大変そうです。
    …と思いましたが、click なら検知してくれました。
    http://jsfiddle.net/wz8e2enL/3/

    キャンセル

0

form の input ですよね、

input text の エンターは、submit ボタンのクリックイベントが動作します。

イベントハンドラ内で、jquery の場合は、e.target.form.ボタンの名前 とかで普通に取れます。
submit ボタンの並びがきまってるならば、e.target.form.querySelector("input[type=submit]:first") とか並びを指定すれば目的のボタンが取れます。キーダウンをエミュレートするなら、エンターじゃなくて、スペースキーですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/11/25 20:26 編集

    > 2個並んでるどっちのボタンが対象なのか知りたい?ってことですか。
    違います。clickを使うならkeydownを使う必要がないのではと指摘はしました。
    http://jsfiddle.net/wz8e2enL/3/ を実行いただけば分かるかと思います(質問文の後半にコードとリンクがあります)。
    質問の主題は submit イベントハンドラ関数内で input[type=submit] を得る事です。

    キャンセル

  • 2015/11/25 22:58

    http://jsdo.it/ipadcaron/IIfM
    こんなのはどうですか。

    キャンセル

  • 2015/11/26 07:58

    Raggさんの回答の document.activeElement を応用したコードですね。
    確かに期待通りの動作ですが、keydown or click から submit までのタイミングで focus がなくなると機能しなくなるのがネックだと感じています。
    少ない可能性ですが、やろうと思えば focus を外す事は可能ですので…。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る