submit ボタン disable 技の罠

昨日のonsubmit で submit ボタンを disable にしてユーザビリティを良くするにはちょっとした罠があって、それに気付かずに使うとはまってしまうかもしれないので、それもちょっと書いておく、というか今日僕自身がはまったわけだが。

罠というのは、type="submit" な input 要素、つまりは submit ボタンを onsubmit ハンドラで disable するまでは良いのですが、このとき

<input type="submit" name="foo" value="bar">

としていて、foo=bar という値が渡ってくることを期待し、それを内部の処理に使っていると嫌な目に逢う、という話です。先のやり方では input 要素が disable になって GET なり POST なりされるので、押したボタンに対応するパラメータが渡ってこない、というわけです。一つの form の中に submit ボタンが複数あって、どのボタンが押されたかによってロジックを分岐させているような場合に痛い目に逢います。

これを回避するには幾つかやり方があると思うのですが、僕が思いついたのは、ボタンが押された時点でその input 要素に割り当てられているパラメータを hidden パラメータに置き換えて form に追加して、それから disable にする、という方法です。

つまり、ボタンの onclick ハンドラで以下のような関数を呼び出します。

function setHiddenValue(button) {
  if (button.name) {
    var q = document.createElement('input');
    q.type = 'hidden';
    q.name = button.name;
    q.value = button.value;
    button.form.appendChild(q);
  }
}

button.createElement と form.appendChild で、hidden なフォームパラメータに置き換えてしまうという方法です。

先のエントリーの関数を onsubmit に、今回のコードを onlick にといちいちするために HTML のテンプレートを書き換えたりするのがめんどくさい、という場合はハンドラへの登録も JavaScript で自動化してしまえばよくて、

  1. body の onload ハンドラで document.forms によりページ内の form をすべて取得
  2. それぞれの form の中に含まれるボタンな要素の onclick プロパティに上記のにメソッドを代入
  3. form の onsubmit プロパティにボタンを disable にするメソッドを代入

と順番に下っていく形でやっていくとうまくいくと思います。