イントロダクション

4.10.1 イントロダクション

このセクションは非規定です。

フォームは、テキストフィールド、ボタン、チェックボックス、レンジコントロール、カラーピッカーといったフォームコントロールを持つウェブページの構成要素です。ユーザーは、フォームを使ってデータをサーバーへ送信して、さらに処理(検索や計算の結果を返すなど)を行わせることができます。多くの場合で、クライアント側にスクリプトが不要となります。もちろん、スクリプトから API を使うことで、ユーザー体験を向上させたり、サーバーへデータを送信せずに別の目的でフォームを使うこともできます。

いくつかの手順を踏めばフォームを書くことができます。順番は問いません:ユーザーインタフェースを書き、サーバー側の処理を実装し、サーバーと通信するユーザーインタフェースを定義します。

4.10.1.1 フォームのユーザーインタフェースを書く

このセクションは非規定です。

まずは手始めに、ピザの注文フォームを作ってみましょう。

どんなフォームも、form 要素から始まります。この中に、コントロールを置くことになります。ほとんどのコントロールは、input 要素で表されます。これはデフォルトでは 1 行テキストフィールドを提供します。コントロールにラベルを付けたいなら、label 要素を使います。ラベルのテキストとコントロールそのものは、label 要素の中に入れます。フォームのそれぞれの部分は段落と見なされ、通常は p 要素を使って、他の部分と分離されます。以上をまとめると、もし顧客の名前を求めるなら、このようになるでしょう:

<form>
 <p><label>お客様名: <input></label></p>
</form>

ユーザーにピザのサイズを選択させるために、ラジオボタンのセットを使うことができます。input 要素はラジオボタンにも使います。今回は、その type 属性の値を radio にします。ラジオボタンをグループとして機能するようにするために、それらの name 属性に共通の値を指定します。コントロールをひとつのグループにグループ化したい場合、この場合のラジオボタンですが、fieldset 要素を使うことができます。コントロールのグループのタイトルは、fieldset 要素の中で最初の要素に指定します。それは legend 要素でなければいけません。

<form>
 <p><label>お客様名: <input></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
</form>

前の手順からの変更点がハイライトされています。

トッピングの選択には、チェックボックスを使うことができます。これらには、type 属性の値を checkbox にした input 要素を使います:

<form>
 <p><label>お客様名: <input></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox> ベーコン </label></p>
  <p><label> <input type=checkbox> チーズ増量 </label></p>
  <p><label> <input type=checkbox> オニオン </label></p>
  <p><label> <input type=checkbox> マッシュルーム </label></p>
 </fieldset>
</form>

このフォームに書かれているピゼリアは、いつもミスばかりしています。そのため、顧客への連絡方法が必要です。これには、電話番号(type 属性の値を tel にセットした input 要素)、e-mail アドレス(type 属性の値を email にセットした input 要素)に特化したフォームコントロールを使うことができます:

<form>
 <p><label>お客様名: <input></label></p>
 <p><label>電話番号: <input type=tel></label></p>
 <p><label>E-mail アドレス: <input type=email></label></p>
 <fieldset>
  <legend>ピザのサイズ</legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox> ベーコン </label></p>
  <p><label> <input type=checkbox> チーズ増量 </label></p>
  <p><label> <input type=checkbox> オニオン </label></p>
  <p><label> <input type=checkbox> マッシュルーム </label></p>
 </fieldset>
</form>

配達時間を尋ねるのであれば、type 属性の値を time にセットした input 要素を使うことができます。これらのフォームコントロールの多くは、どんな値を指定できるのかを正確に制御するための属性を持っています。この場合、特に興味深い属性は、min, max, step の 3 つです。これらは、最小の時間、最大の時間、そして、指定可能な時間の間隔(秒)をセットします。このピゼリアは、午前 11 時から午後 9 時に限って配達しており、15 分単位でしか承っていません。これは次のようにマークアップすることができます:

<form>
 <p><label>お客様名: <input></label></p>
 <p><label>電話番号: <input type=tel></label></p>
 <p><label>E-mail アドレス: <input type=email></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox> ベーコン </label></p>
  <p><label> <input type=checkbox> チーズ増量 </label></p>
  <p><label> <input type=checkbox> オニオン </label></p>
  <p><label> <input type=checkbox> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900"></label></p>
</form>

フリー入力欄を用意したいなら、textarea 要素を使うことができます。この例では、これを使って、配達の指示を顧客が入力できる場所を用意することにします:

<form>
 <p><label>お客様名: <input></label></p>
 <p><label>電話番号: <input type=tel></label></p>
 <p><label>E-mail アドレス: <input type=email></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox> ベーコン </label></p>
  <p><label> <input type=checkbox> チーズ増量 </label></p>
  <p><label> <input type=checkbox> オニオン </label></p>
  <p><label> <input type=checkbox> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900"></label></p>
 <p><label>配達の指示: <textarea></textarea></label></p>
</form>

最後に、button 要素を使って、このフォームを送信できるようにします:

<form>
 <p><label>お客様名: <input></label></p>
 <p><label>電話番号: <input type=tel></label></p>
 <p><label>E-mail アドレス: <input type=email></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size> 小 </label></p>
  <p><label> <input type=radio name=size> 中 </label></p>
  <p><label> <input type=radio name=size> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox> ベーコン </label></p>
  <p><label> <input type=checkbox> チーズ増量 </label></p>
  <p><label> <input type=checkbox> オニオン </label></p>
  <p><label> <input type=checkbox> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900"></label></p>
 <p><label>配達の指示: <textarea></textarea></label></p>
 <p><button>注文確定</button></p>
</form>
4.10.1.2 フォームに対するサーバー側の処理を実装する

このセクションは非規定です。

サーバー側の処理の詳細な書き方については、この仕様の範囲外となります。このイントロダクションでは、https://pizza.example.com/order.cgi におけるスクリプトが、application/x-www-form-urlencoded の形式を使ったサブミットを受け付けるようになっているとしましょう。次のパラメータが HTTP POST ボディの中に入れられて送信されるはずです:

custname
顧客の名前
custtel
顧客の電話番号
custemail
顧客の e-mail アドレス
size
ピザのサイズ。small, medium, large のいずれか。
topping
トッピング。選択されたトッピングの取り得る値は、bacon, cheese, onion, mushroom です。
delivery
希望の配達時間
comments
配達の指示
4.10.1.3 サーバーと通信するためフォームを定義する

このセクションは非規定です。

フォームサブミットは、さまざまな方法でサーバーに送信されます。ごく一般的には、HTTP GET または HTTP POST リクエストが使われます。採用するメソッドを正確に指定するために、method 属性を form 要素に指定します。これは、フォームデータがどのようにエンコードされるのかを指定するものではありません。それを指定するには、enctype 属性を使います。さらに、サブミットするデータを処理するサービスの URL も指定しなければいけません。それには action 属性を使います。

サブミットさせたいフォームコントロールに対して、サブミットでデータを参照するために使う名前を指定しなければいけません。すでにラジオボタンのグループに名前を指定しました。この同じ属性(name)がサブミットの名前をも指定することになります。ラジオボタンは value 属性を使って異なる値を指定することによって、サブミットにおいて、それぞれを区別できるようになります。

マルチプルコントロールは、同じ名前を持つことができます。例えば、ここでは、すべてのチェックボックスに同じ名前を与えています。サーバーは、どんな値がその名前を伴ってサブミットされたのかを調べることで、どのチェックボックスがチェックされたのかを区別します。ラジオボタンと同じように、それらには、value 属性にユニークな値が与えられています。

前のセクションのこのセッティングを加えると、全体は次のようになります:

<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>お客様名: <input name="custname"></label></p>
 <p><label>電話番号: <input type=tel name="custtel"></label></p>
 <p><label>E-mail アドレス: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size value="small"> 小 </label></p>
  <p><label> <input type=radio name=size value="medium"> 中 </label></p>
  <p><label> <input type=radio name=size value="large"> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> ベーコン </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> チーズ増量 </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> オニオン </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p>
 <p><label>配達の指示: <textarea name="comments"></textarea></label></p>
 <p><button>注文確定</button></p>
</form>

これらの属性の値のうち、引用符が付いたものと、ものとそうでないものがある点については、特に意味はありません。構文のセクションに書かれているとおり、HTML 構文は、属性を指定するいくつかの妥当な方法を等しく許しています。

例えば、もし顧客が自分の名前に "Denise Lawrence" と入力し、電話番号に "555-321-8642" と入力し、e-mail アドレスを指定せず、中サイズのピザを希望し、トッピングにチーズ増量とマッシュルームを選択し、配達時間に午後 7 時を指定し、配達の指示には何も入力しなかったら、ユーザーエージェントは、このオンラインのウェブサービスに次の値をサブミットするでしょう:

custname=Denise+Lawrence&custtel=555-321-8624&custemail=&size=medium&topping=cheese&topping=mushroom&delivery=19%3A00&comments=
4.10.1.4 ライアント側のフォームバリデーション

このセクションは非規定です。

フォームがサブミットされる前にユーザーの入力をユーザーエージェントがチェックできるよう、フォームを記述することができます。とはいえ、サーバー側でもその入力が妥当かどうかを確認する必要はあります(悪意のあるユーザーはそのフォームのバリデーションを簡単にバイパスできるからです)。しかし、こうすることで、サーバーだけにユーザー入力をチェックさせていた分だけ、ユーザーは待たされずに済みます。

最もシンプルなのは required 属性ですが、これを input 要素に指定すると、値が指定されるまで、そのフォームはサブミットされないようにすることができます。この属性を顧客名と配達時間に加えれば、これらのフィールドを入力せずにフォームを送信しようと、ユーザーエージェントはユーザーに知らせることがでるようになります:

<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>お客様名: <input name="custname" required></label></p>
 <p><label>電話番号: <input type=tel name="custtel"></label></p>
 <p><label>E-mail アドレス: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size required value="small"> 小 </label></p>
  <p><label> <input type=radio name=size required value="medium"> 中 </label></p>
  <p><label> <input type=radio name=size required value="large"> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> ベーコン </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> チーズ増量 </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> オニオン </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p>
 <p><label>配達の指示: <textarea name="comments"></textarea></label></p>
 <p><button>注文確定</button></p>
</form>

maxlength 属性を使えば、入力の長さも制限することができます。これを textarea 要素に加えると、1000 文字までに制限でき、膨大なエッセイを書けないようにすることができます。これで、忙しい配達ドライバーがそれを読むのに夢中になることなく、目的地に行けるでしょう:

<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>お客様名: <input name="custname" required></label></p>
 <p><label>電話番号: <input type=tel name="custtel"></label></p>
 <p><label>E-mail アドレス: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> ピザのサイズ </legend>
  <p><label> <input type=radio name=size required value="small"> 小 </label></p>
  <p><label> <input type=radio name=size required value="medium"> 中 </label></p>
  <p><label> <input type=radio name=size required value="large"> 大 </label></p>
 </fieldset>
 <fieldset>
  <legend> ピザのトッピング </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> ベーコン </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> チーズ増量 </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> オニオン </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> マッシュルーム </label></p>
 </fieldset>
 <p><label>ご希望の配達時間: <input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p>
 <p><label>配達の指示: <textarea name="comments" maxlength=1000></textarea></label></p>
 <p><button>注文確定</button></p>
</form>

フォームがサブミットされるとき、不正なフォームコントロールそれぞれで、その後に、該当の form 要素自身で、invalid イベントが発出されます。これは、フォームの問題をまとめて表示するのに役立ちます。なぜなら、通常、ブラウザー自身は、その時点でひとつの問題を表示するだけだからです。

4.10.1.5 日付, 時刻, 数値のフォーマット

このセクションは非規定です。

このピザ配達の例では、時刻が "HH:MM" フォーマットで指定されています:時は 2 桁の数字で 24 時間表記です。分は 2 桁の数字です。(この例では必要ありませんでしたが、秒も指定することができます。)

しかし、ローケールによっては、ユーザーに表示する際に、時刻の表記が違うことがあります。たとえば、合衆国では今でも ”2pm” のように 12 時制に am/pm の識別を加えて使うのが一般的です。フランスでは、"14h00" のように、"h" という文字を使って時と分を分けるのが一般的です。

日付に関しても同じような問題があります。構成要素の順番ですらまったく一貫性がないという複雑さが加わります。たとえば、キプロスでは、the first of February 2003 は通常は "1/2/03" と書かれますが、日本では同じ日付でも一般的には "2003年02月01日" のように書かれます。数字ですらロケールによる違いがあります。たとえば、小数点の記号や 3 桁区切り文字もが違ってきます。

ゆえに、HTML やフォームサブミットで使われる時刻、日付、数字のフォーマットを見分けることが重要になってきます。これらは、すべてこの仕様で定義された形式となります(コンピューター可読な日時フォーマットとして、定評のある ISO 8601 をベースにしています)。これは、ブラウザーによってユーザーに表示される時刻、日付、数字のフォーマットにとどまらず、ブラウザーによってユーザーからの入力として受け付けられるフォーマットにも及びます。

"通信で"、つまり、HTML マークアップやフォームサブミットで使われるフォーマットは、コンピューター可読で、ユーザーのロケールにとらわれないよう一貫性を保つことが考慮されています。たとえば、日付は常に "YYYY-MM-DD" という形式で書かれます。たとえば "2003-02-01" です。ユーザーにこのフォーマットを見せるというわけではありません。

通信のフォーマットでページから得られる時刻、日付、数字は、ユーザーに表示される前に、ユーザーの好みの表現に変換されます(ユーザー設定やページのロケールに基づきます)。同様に、ユーザーが時刻、日付、数字を自分好みのフォーマットで入力したら、ユーザーエージェントは、それを DOM に挿入したりサブミットする前に、通信フォーマットに戻します。

これによって、ページやサーバーのスクリプトは、時刻、日付、数字を、ユーザーのニーズに応えながらも、数多くのフォーマットをサポートする必要はなく、一貫性のある方法で処理できるようになるのです。

フォームコントロールのローカライゼーションについては、実装上の注意もご覧ください。


※ 原文:http://www.w3.org/TR/2014/REC-html5-20141028/forms.html#introduction-1