WCAG 2.0 達成方法集

Skip to Content (Press Enter)

クライアントサイドスクリプトの達成方法

このウェブページは、「WCAG 2.0 達成方法集 : WCAG 2.0 の達成方法と失敗例」におけるクライアントサイドスクリプトの達成方法を掲載している。ウェブコンテンツ技術特有の達成方法は、「一般 (General)」の達成方法に取って代わるものではない。コンテンツ制作者は適合に向けて作業する際には、「一般 (General)」の達成方法とウェブコンテンツ技術特有の達成方法の双方を考慮に入れる必要がある。

ウェブコンテンツ技術特有の達成方法は、あらゆる状況で WCAG 2.0 の達成基準と適合要件を満たすコンテンツを作るために使うことができる技術を指しているわけではない。 コンテンツ制作者はその技術の限界に注意を払い、障害のある人にアクセシブルな方法でコンテンツを提供す必要がある。

達成方法についての情報は、WCAG 2.0 達成方法集のイントロダクションを参照のこと。他のウェブコンテンツ技術の達成方法一覧については、目次を参照のこと。




SCR1: 利用者が初期設定の制限時間を延長できるようにする

適用 (対象)

クライアントサイドスクリプトによりコントロールされた制限時間。

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、スクリプトがデフォルトの制限時間のある機能を提供する際、その時間を延長するメカニズムを提供することによって、利用者がデフォルトの制限時間を延長できるようにすることである。利用者がより長い制限時間を要求できるようにするために、利用者がより長い制限時間を入力できる、又は より多くの時間を必要としていることを示す (例えば) フォームをスクリプトが提供することができる。制限時間が切れそうであることを利用者に警告する場合 (SCR16: 制限時間が切れようとしていることを利用者に警告するスクリプトを提供するを参照)、このフォームを警告のダイアログから利用可能にする。どれぐらいの追加時間が必要かを示すことができるようにするか、繰り返し制限時間を延長できるようにすることによって、利用者はデフォルトの制限時間を少なくとも 10 倍延長することができる。

事例

  • ウェブページに最新の株式市場のデータがあり、定期的に更新されている。利用者が最初の更新の前に警告を受けたとき、利用者には更新の間隔を延長するための選択肢が提供されている。

  • オンラインチェスゲームにおいて、各プレーヤーはそれぞれの動きが終わるまでの制限時間が与えられている。動かせる時間がほとんど終わりであるという警告をプレーヤーが受けたとき、利用者には時間を増やすための選択肢が提供されている。

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

  1. PHPBuilder Time-out Info

検証

手順

  1. 制限時間を強制するためにスクリプトを使用しているウェブページで、制限時間が切れるまで待つ。

  2. 制限時間を延長する選択肢が提供されているかどうかを判断する。

期待される結果

  • 2.の結果が真であり、かつインタラクションを完了するために更なる時間が提供されている。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR2: キーボード及びマウスのイベントハンドラを両方とも使用する

適用 (対象)

スクリプトをサポートしている HTML 及び XHTML

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、マウスやフォーカスのイベントによって装飾画像が変化する、機器に依存しないイベントの使い方を説明することである。onmouseover や onmouseout イベントを使って、マウスがページ中のある要素に重なるか、又は離れたときに装飾画像が変化するようにする。また、onfocusonblur イベントを使って、要素がフォーカスされたか、フォーカスを失ったかによって画像を変更する。

下記の例では、アンカー要素の前に装飾画像がある。利用者がアンカータグにマウスオーバーすると、アンカータグの前の装飾画像が変化する。また、マウスがアンカーを離れると、画像は元に戻る。同じ画像の変化は、利用者がキーボードを使ってアンカー要素にフォーカスしたときにも起こる。フォーカスされたときに画像が変化し、フォーカスを失ったときには元の画像に戻る。これは、アンカー要素に onmouseoveronmouseoutonfocus 及び onblur イベントハンドラを付加することで実現できる。このイベントハンドラは JavaScript の関数で updateImage() と呼ばれており、画像の src 属性を変更する。updateImage() は onmouseover、onmouseout、onfocus、及び onblur イベントの応答として呼ばれる。

それぞれの画像には固有の ID が与えられている。この ID はどちらの画像が使われるかを表す論理値とともに、updateImage() に渡される: updateImage(imgId, isOver);。論理値 true は、マウスがアンカー要素に乗った場合、又はそれがフォーカスされた場合に渡される。false は、マウスがアンカー要素から離れた場合、又はそれがフォーカスを失った場合に渡される。 updateImage() 関数は、画像の ID を使用して画像を読み込み、その後に論理値の状態に応じて src 属性を変更する。画像は装飾目的で使用されているので、alt 属性値は空であることに注意する。

注記: サイズの近い画像を使用し、画像要素では幅と高さの属性値を指定することが望ましい。これは、画像が更新されることによりページのレイアウトが変化してしまうことを防ぐ。例では、同一サイズの画像が使用されている。

事例

事例 1

コード例:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
 <html lang="en">
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Changing Image Source in a Device Independent Manner</title>
 <script type="text/javascript">
 /* このfunctionは、img要素のsrc属性値を変更する。
  * param imgId - 変更する画像オブジェクトのID
  * param isOver - true: マウスオーバーしたとき、又はオブジェクトがフォーカスを受け取ったとき
  *                false: マウスオーバーを外したとき、又はフォーカスを外したとき
 */
 function updateImage(imgId, isOver) {
   var theImage = document.getElementById(imgId);
   if (theImage != null) { //could use a try/catch block for user agents supporting at least JavaScript 1.4
                           // These browsers support try/catch - NetScape 6, IE 5, Mozilla, Firefox
      if (isOver) {
        theImage.setAttribute("src","yellowplus.gif");
      }
      else {
        theImage.setAttribute("src","greyplus.gif");
      }
   }
 }
 </script>
 </head>
 <body>
 <p>Mouse over or tab to the links below and see the image change.</p>
 <a href="http://www.w3.org/wai" onmouseover="updateImage('wai', true);" onfocus="updateImage('wai', true);"
   onmouseout="updateImage('wai',false);" onblur="updateImage('wai',false);">
 <img src="greyplus.gif" border="0" alt="" id="wai">
   W3C Web Accessibility Initiative</a> &
 <a href="http://www.w3.org/International/" onmouseover="updateImage('i18n', true);" 
   onfocus="updateImage('i18n',true);" onmouseout="updateImage('i18n',false);"
   onblur="updateImage('i18n',false);">
   <img src="greyplus.gif" border="0" alt="" id="i18n">
   W3C Internationalization</a>
 </body>
 </html>

検証

手順

ウェブページを読み込み、マウス及びキーボードを用いてイベントを検証する。

  1. ウェブページが読み込まれたとき、「通常の」画像が期待通りに表示されていることを確認する。

  2. マウスを使用

    1. イベントハンドラを含む要素の上にマウスを移動する (この事例ではアンカー要素)。画像が期待されている画像に変化することを確認する。

    2. マウスを要素から外す。画像が「通常の」画像に戻ることを確認する。

  3. キーボードを使用

    1. キーボードを使ってイベントハンドラを含む要素にフォーカスを設定する。画像が期待されている画像に変化することを確認する。

    2. キーボードを使って要素からフォーカスを外す (一般的には別の要素にフォーカスを移す)。画像が「通常の」画像に戻ることを確認する。

  4. 画像が変更されたときに、ページ上の他の要素のレイアウトに影響がないことを確認する。

期待される結果

  • 上記の全ての結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR14: 不可欠ではないアラートの表示を任意にするために、スクリプトを使用する

適用 (対象)

緊急ではない情報提供のアラートにスクリプトを使用するウェブコンテンツ技術

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、メッセージ (アラート) を含むダイアログを利用者に表示することである。アラートが表示されたとき、それがフォーカスされると、利用者はそれを閉じるためにダイアログの OK ボタンを押さなければならない。これらのアラートにフォーカスが移ってしまうと、特に、緊急ではない情報に使用されたとき、利用者の気が散ってしまうかもしれない。今日の名言、役に立つ小技、又は特定のイベントまでのカウントダウンなど、緊急ではない目的のアラートは、利用者がウェブページに提供された選択肢でそれらを有効にすることなしには現れないようにする。

この達成方法では、アラートを表示するかどうかの利用者の選択を保存する JavaScript のグローバル変数に割り当てる。初期値は false にする。 ラッパー関数は、アラートを表示する前にこの変数の値をチェックするために作成される。alert() 関数を直接呼び出すよりもむしろ、アラートを表示するすべての呼び出しをこのラッパー関数にかけるようにする。ページの上部には、ページでのアラートの表示を利用者が有効にするためのボタンを提供する。この達成方法は訪問ベースで 1 回の訪問ごとに作動する。ページが読みこまれるたび、アラートは無効にされ、利用者は手動でそれらを有効にしなければならない。あるいは、コンテンツ制作者は、利用者の選択をセッションを越えて保存するためにクッキーを使用することができる。

事例

事例 1

以下のスクリプトは、利用者が「アラートを利用する」というボタンを選択するなら、10 秒ごとにアラートボックスに名言を表示する。利用者は再び「アラートを利用しない」を選択することで、名言のアラートボックスを非表示にすることができる。

コード例:


<script type="text/javascript">
var bDoAlerts = false;  // アラートを表示するかどうか指定するグローバル変数
/* アラートを有効/無効にする関数。
 * param ブーリアン型 bOn - trueでアラートを有効、falseで無効。
*/
function modifyAlerts(isEnabled) {
   bDoAlerts = isEnabled;
}
/* アラート表示のラッパー関数。bDoAlertsの値をチェックし
* bDoAlertsがtrueのときに alert() 関数を呼び出すだけ。
*/
function doAlert(aMessage) {
    if (bDoAlerts) {
       alert(aMessage);
    }
}
// 例 - 名言を表示するループ。
var gCounter = -1;  // カウンタを保存するグローバル変数
// quotes変数は名言のリストで初期化される
var quotes = new Array("quote 1", "quote 2", "quote 3", "quote 4", "quote 5");
function showQuotes() {
   if (++gCounter &amp;gt;= quotes.length) { //★「&amp;gt;」は「>」ではないでしょうか?★
     gCounter = 0;
   }
   doAlert(quotes[gCounter]);
   setTimeout("showQuotes();", 10000);
}
showQuotes();
</script>

ページの本文内には、アラートを有効にしたり無効する方法を含める。以下はひとつの例である:

コード例:


<body>
<p>Press the button below to enable the display of famous quotes 
using an alert box<br />
<button id="enableBtn" type="button" onclick="modifyAlerts(true);">
Turn Alerts On</button><br />
<button id="disableBtn" type="button" onclick="modifyAlerts(false);">
Turn Alerts Off</button></p>

このコードを実装したサンプル: アラートの実装例

検証

手順

JavaScript の alert を使用した緊急ではない中断をサポートするウェブページにおいて:

  1. ウェブページを読み込んだとき、緊急ではないアラートが表示されないことを確認する。

  2. 緊急ではないアラートを有効にするメカニズムがあることを確認する。

  3. 緊急ではないアラートを有効にすると、アラートが表示されることを確認する。

期待される結果

  • JavaScript の alert を使用して緊急ではない中断をサポートするウェブページでは、上記の 1.、2 及び 3 の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR16: 制限時間が切れようとしていることを利用者に警告するスクリプトを提供する

適用 (対象)

スクリプトによって制御された制限時間

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、インタラクションを完了させるための時間がほとんど無いことを利用者に通知することである。スクリプトによって、時間制限のある機能が提供される場合には、そのスクリプトは利用者に制限時間が迫っていることを警告する機能を含み、より多くの時間を要求するためのメカニズムを提供することができる。制限時間の 20 秒以上前に、そのスクリプトは制限時間が迫っている事を伝え、利用者がさらに時間を必要とするかどうかを尋ねる確認ダイアログを提供する。もし利用者の答えが「はい」の場合、制限時間をリセットする。もし利用者の答えが「いいえ」又は返答がない場合、制限時間の終了を許可する。

この達成方法は、window.setTimeout() メソッドで設定された制限時間に関係する。例えば、60 秒で制限時間が切れる設定の場合、制限時間を 40 秒に設定して、確認ダイアログを表示させることができる。確認ダイアログが表示された時、新しく時間制限が残り 20 秒に設定される。「制限時間の猶予期間」の満了時に、当初の設計では 60 秒の制限時間の満了の時にとられていたであろう処置がとられる。

事例

事例 1

ある株式市場相場ページは最新の統計を利用可能な状態を確保するため 5 分毎にページを更新するスクリプトを使用している。その 5 分間が終了する 20 秒前に、確認ダイアログが表示され、利用者がページを更新する前にもっと時間が必要かどうかを尋ねる。これにより、利用者に更新が差し迫っていることを認識させるとともに、もし希望するならそれを回避できるようにする。

コード例:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"<url>http://www.w3.org/TR/html4/loose.dtd">http://www.w3.org/TR/html4/loose.dtd</title>">
<html lang="en">
<head>

<title>Stock Market Quotes</title>
<script type="text/javascript">
<!--
function timeControl() {
	// タイマーを4分40秒に設定し、利用者に確認を求める
	setTimeout('userCheck()', 280000);
}
function userCheck() {
	// ページの再読み込みを20秒に設定する
	var id=setTimeout('pageReload()', 20000);
	// 利用者が「OK」を選択した場合、タイマーがリセットされる
	// それ以外の場合、サーバーによりページが再読み込みされる
	if (confirm("This page is set to refresh in 20 seconds. 
	Would you like more time?"))
	{
	clearTimeout(id);
	timeControl();
	}
}
function pageReload() {
	window.location.reload(true);
}
timeControl();
-->
</script>
</head>
<body>
<h1>Stock Market Quotes</h1>
...etc...
</body>
</html>

検証

手順

スクリプトによって時間制限を制御されているウェブページにおいて:

  1. ページを読み込み、制限時間より 20 秒少ないタイマーを開始する。

  2. タイマーが切れるとき、間近に迫った時間制限を警告する確認ダイアログが表示されることを確認する。

期待される結果

  • 2. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR18: クライアントサイドのバリデーション及びアラートを提供する

適用 (対象)

利用者の入力を検証するコンテンツ

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、クライアントサイドのスクリプトによって、各フィールドで利用者が入力する値を確認することである。エラーが見つかった場合、警告ダイアログを表示し、エラーの内容をテキストで示す。警告ダイアログを閉じるとともに、スクリプトによってキーボードフォーカスをエラーが起こったフィールドに移動させれば、それは利用者にとって役立つ。

事例

事例 1: イベントハンドラで単一のコントロールをチェックする

以下のスクリプトは、有効な日付がフォームのコントロールに入力されたかをチェックする。

コード例:


<label for="date">Date:</label>
<input type="text" name="date" id="date" 
onchange="if(isNaN(Date.parse(this.value))) 
alert('This control is not a valid date. 
Please re-enter the value.');" />

事例 2: 利用者がフォームを送信したときに複数のコントロールをチェックする

次の例はフォーム内の複数のコントロールを表している。form 要素は、利用者がフォームを送信しようとした際、検証スクリプトを実行するために、イベントハンドラを作成する onsubmit 属性を用いている。検証で問題がない場合、イベントは true を返し、フォームの送信を続行する。検証でエラーが検出された場合は、利用者が問題を修正できるようエラーメッセージを表示し、送信を取り消すために false を返す。

注記 1: この事例は簡潔さのためにアラートを用いて説明している。利用者により役立つ通知は、問題のあるコントロールをハイライトし、エラーの内容とデータの修正が必要なコントロールに移動する方法をページ上に示すことである。

注記 2: この事例では簡潔さのために form 要素に onsubmit 属性を用いているが、通常であればページがロードした際にフォーム送信用のイベントリスナーを作成する。

スクリプトコード:


function validate() {
	// initialize error message
	var msg = "";
	
	//validate name
	var pattern = /^[a-zA-Z\s]+$/;
	var el = document.getElementById("name");
	if (!pattern.test(el.value))  msg += "Name can only have letters and spaces. ";
	
	// validate number
	var pattern = /^[\d\-+\.\s]+$/;
	var el = document.getElementById("tel");
	if (!pattern.test(el.value))  msg += "Telephone number can only have digits and separators. ";
	
	if (msg != "") {
		alert(msg);
		return false;
	} else return true;
}

フォームコード:


<form action="multiple-controls.html" onsubmit="return validate()">
	<p>
		<label for="name">Name: </label>
		<input type="text" name="name" id="name" />
	</p>
	<p>
		<label for="tel">Telephone number: </label>
		<input type="text" name="tel" id="tel" />				
	</p>
	<p>
		<input type="submit" />
	</p>
</form>

利用者がフォームを送信したときに複数のコントロールをチェックする実装例にこの実装方法のデモがある。

検証

手順

特定の入力を必要とするフォームのフィールドに対して:

  1. 無効なデータを入力する。

  2. エラーを説明している警告が提供されているかどうかを判断する。

期待される結果

  • 2. の結果が真である

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR19: select 要素の onchange イベントは、コンテキストの変化を引き起こすことのないように使用する

適用 (対象)

スクリプトをサポートする HTML 及び XHTML。この達成方法では、JavaScript 1.4 の try/catch 構文を用いる。

これは、次の達成基準に関連する達成方法である:

ユーザエージェント及び支援技術によるサポート

SCR19 に関するユーザエージェントサポートノートを参照のこと。

解説

この達成方法の目的は、ウェブページの他の要素を更新する select 要素において onchange イベントを正しく使用する方法を示すことである。この達成方法は、コンテキストの変化を引き起こさない。ウェブページに一つかそれ以上の select 要素があるとき、一方の onchange イベントは、そのウェブページの別の select 要素における選択肢を更新できる。そして、select 要素によって必要とされるデータのすべてが、ウェブページの中に含まれている。

ウェブページでの音声読み上げ順序において、選択によって変更されるアイテムが、トリガーとなる select 要素の後にあることに注意することが重要である。これは、支援技術が変化を察知するのを確実にし、変更されたアイテムがフォーカスされたとき、利用者は新しいデータを認識する。なお、この達成方法は、ユーザエージェントによる JavaScript のサポート状況に依存する。

事例

事例 1

この事例には、二つの select 要素がある。最初の select 要素でアイテムが選択されたとき、二つめの select 要素の選択肢が適切に更新される。最初の select 要素には、大陸のリストがある。そして、二つめの select 要素には、選択された大陸に位置する国々の一部のリストがある。onchange イベントは、大陸の選択に連動している。大陸の選択が変わると、国の選択肢は、ドキュメントオブジェクトモデル (DOM) を通して JavaScript を用いて変更される。必要であるすべてのデータ、国と大陸のリスト、はウェブページの中に含まれている。

以下のコードの概要:

  • トリガーとなる select 要素の大陸ごとの国々のリストを含む countryLists 配列

  • 大陸の select 要素の onchange イベントによって呼ばれる countryChange() 関数

  • ウェブページの本文の select 要素を作成する XHTML コード

コード例:


<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
  <head> 
    <meta http-equiv="content-type" content="text/xhtml; charset=utf-8" /> 
    <title>Dynamic Select Statements</title> 

<script type="text/javascript">
 //<![CDATA[ 
 // 国の選択項目のリストに現れるのと同じ順の選択可能な国の配列 
 var countryLists = new Array(4) 
 countryLists["empty"] = ["Select a Country"]; 
 countryLists["North America"] = ["Canada", "United States", "Mexico"]; 
 countryLists["South America"] = ["Brazil", "Argentina", "Chile", "Ecuador"]; 
 countryLists["Asia"] = ["Russia", "China", "Japan"]; 
 countryLists["Europe"]= ["Britain", "France", "Spain", "Germany"]; 
 /* CountryChange() はselect要素のonchangeイベントから呼び出される。 
 * param selectObj - onchangeイベントで生成されるselectオブジェクト。
 */ 
 function countryChange(selectObj) { 
 // 選択された選択肢のインデックスを得る 
 var idx = selectObj.selectedIndex; 
 // 選択された選択肢の値を得る 
 var which = selectObj.options[idx].value; 
 // countryLists 配列から項目のリストを検索するために選択された選択肢の値を使う 
 cList = countryLists[which]; 
 // そのIDを通して国のselect要素を得る
 var cSelect = document.getElementById("country"); 
 // 国のリストから現在の選択肢を削除する 
 var len=cSelect.options.length; 
 while (cSelect.options.length > 0) { 
 cSelect.remove(0); 
 } 
 var newOption; 
 // 新しい選択肢を生成する 
 for (var i=0; i<cList.length; i++) { 
 newOption = document.createElement("option"); 
 newOption.value = cList[i];  // 選択肢の文字列と値は同じとする 
 newOption.text=cList[i]; 
 // 新しい選択肢を追加する 
 try { 
 cSelect.add(newOption);  // これはDOMをサポートするブラウザでは失敗するが、IEには必要 
 } 
 catch (e) { 
 cSelect.appendChild(newOption); 
 } 
 } 
 } 
//]]>
</script>
</head>
<body>
  <noscript>This page requires JavaScript be available and enabled to function properly</noscript>
  <h1>Dynamic Select Statements</h1>
  <label for="continent">Select Continent</label>
  <select id="continent" onchange="countryChange(this);">
    <option value="empty">Select a Continent</option>
    <option value="North America">North America</option>
    <option value="South America">South America</option>
    <option value="Asia">Asia</option>
    <option value="Europe">Europe</option>
  </select>
  <br/>
  <label for="country">Select a country</label>
  <select id="country">
    <option value="0">Select a country</option>
  </select>
</body>
 </html>

このコードの実装サンプル: 動的なセレクトメニュー

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

(今のところ、なし。)

検証

手順

  1. トリガーとなる select 要素 (この事例では、大陸を選択するセレクトメニュー) に移動し、選択肢の値を変える。

  2. トリガーによって更新された select 要素 (この事例では、国を選択するセレクトメニュー) へ移動する。

  3. 一致する選択肢の値が、他の select 要素に表示されていることを確認する。

  4. トリガーとなる select 要素へ移動し、選択肢へ移動するが、値を変えない。

  5. 一致する選択肢の値が、関連付けられた要素にまだ表示されていることを確認する。

関連付けられた要素の変化が認識されることを確かめるために、select 要素を支援技術を用いて検証することが望ましい。

期待される結果

  • 3. 及び 5. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR20: キーボードとその他のデバイス固有の機能を両方とも使用する

適用 (対象)

機能を実装するためにスクリプトを用いる全てのコンテンツ

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、イベントと関連付けられたスクリプト機能を含むコードを伴った、キーボード固有及びマウス固有のイベント双方の使用を明示することである。キーボード固有及びマウス固有のイベントを一緒に用いることにより、さまざまな種類の機器でコンテンツを操作できることを保証することができる。例えば、スクリプトが keypress を認識したときに、マウスボタンをクリックしたときと同じ動作を行うことができるようにする。このテクニックにより、キーボードによるアクセスだけでなく他の機器によるアクセスの達成基準を満たすことができる。

JavaScript でよく使用されるイベントハンドラには、onblur、onchange、onclick、ondblclick、onfocus、onkeydown、onkeypress、onkeyup、onload、onmousedown、onmousemove、onmouseout、onmouseover、onmouseup、onreset、onselect、onsubmit、onunload が含まれる。いくつかのマウス固有の機能には、論理的に対応するキーボード固有の機能がある (例えば 'onmouseover' と 'onfocus' のように)。キーボード向けのイベントハンドラは、対応するマウス向けの機能とともに提供すべきである。

次の表は、マウスイベントハンドラに対応するキーボードイベントハンドラの候補である。

対応表
マウス向けキーボード向け
mousedownkeydown
mouseupkeyup
click [1] keypress [2]
mouseoverfocus
mouseoutblur

1 click は基本的にはマウスのイベントハンドラであるが、ほとんどの HTML 及び XHTML 向けのユーザエージェントは、HTML のネイティブコントロール (例: ボタン又はリンク) が有効化された場合、マウス又はキーボードのどちらで有効化されたかにかかわらず、イベントを処理することができる。そのため、もともとフォーカスできる HTML 要素にハンドラを追加するときは、実際にはキーボード用のイベントを補完する必要はない。しかし、下記の事例 2 のように他のイベントにハンドラを追加するときは、必要である。

2 keypress イベントハンドラは、どのキーに対しても有効であることから、そのイベントハンドラ関数では、イベントを処理する前に、Enter キーが押されたかどうかをチェックすべきである。そうでなければ、イベントハンドラは利用者が任意のキーを押すたびに実行され、コントロールから抜けるために Tab キーを押すような場合にも実行されるので、通常は望ましくない。

(dblclick 及び mousemove のような) いくつかのマウス固有の機能には、対応するキーボード固有の機能がない。つまり、いくつかの機能は機器別に違った実装をしなければならないということである (例えば、実装されているマウス固有の機能と同等の機能を、キーボードから実行するための一連のボタン操作を含むようにする)。

事例

事例 1

この画像リンクの例では、利用者がポインタを画像に重ねると画像が変化する。キーボード利用者に同様の体験を提供するには、利用者が画像リンクに Tab キーで移動した場合に、画像を変化させればよい。

コード例:


<a href="menu.php" onmouseover="swapImageOn('menu')" onfocus="swapImageOn('menu')" 
onmouseout="swapImageOff('menu')" onblur="swapImageOff('menu')"> 
<img id="menu" src="menu_off.gif" alt="Menu" /> 
</a>

事例 2

この事例では、マウスとキーボードの両方を用いて機能を実行できる画像のカスタムコントロールを紹介している。マウスイベントの onclick は、対応するキーボードイベントの onkeypress によって補完されている。tabindex 属性は、キーボードを用いて Tab キーで移動した際に、画像の上で停止させるためのものである。この事例では nextPage() 関数が、押されたキーボードのキーがEnterであることを確認すべきであり、そうでない場合は、画像がフォーカスを持つ間にすべてのキーボード動作に応答するが、これは期待される動作ではないことに注意する。

コード例:


<img onclick="nextPage();" onkeypress="nextPage();" tabindex="0" src="arrow.gif" 
alt="Go to next page"> 

注記: この例では img 要素に tabindex を用いている。現時点では (文法的に) 妥当ではないが、この機能を実装するための古典的なテクニックとして用いられている。このようなカスタムコントロールでは、コントロールの役割 (role) と状態 (state) を支援技術に引き渡すために WAI-ARIA も用いるべきである。

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. 全てのインタラクティブな機能を探す。

  2. それらのインタラクティブな機能全てに、キーボードだけを使ってアクセスできることを確認する。

期待される結果

  • 2. の結果が真である

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR21: ページにコンテンツを追加するために、Document Object Model (DOM) の機能を使用する

適用 (対象)

HTML 及び XHTML の中で利用される ECMAScript

これは、次の達成基準に関連する達成方法である:

ユーザエージェント及び支援技術によるサポート

SCR21 に関するユーザエージェントサポートノートを参照のこと。

解説

この達成方法の目的は、document.write 又は object.innerHTML の代わりに Document Object Model (DOM) の機能を用いて、ページ中にコンテンツを追加することである。document.write() メソッドは XHTML で正しい MIME タイプ (application/xhtml+xml) が指定されているときに動作せず、innerHTML プロパティは DOM の仕様ではないため利用すべきでない。もし DOM の機能を利用してコンテンツを追加すれば、ユーザエージェントは DOM にアクセスしてコンテンツを取り込むことができる。createElement() 関数を使って DOM の中に要素を作成することもできる。createTextNode() は要素に関連付けられたテキストを作成するのに用いられる。appendChild()removeChild()insertBefore() 及び replaceChild() 関数は、要素やノードを追加したり削除したりするのに用いられる。その他の DOM 関数は、作成された要素に属性を与えるときに使用される。

注記: フォーカス可能な要素を文書に追加するとき、tabindex 属性を用いて明示的なタブ順序を指定してはならない。なぜなら、文書の中央にフォーカス可能な要素を追加するときに問題が発生するからである。tabindex 属性を明示的に設定しないことで、デフォルトのタブ順序が新しい要素に割り当てられるようにする。

訳注 1: HTML 5.2§7.4.3. document.write() の Warning でも述べられているように、たとえ HTML (MIME タイプ text/html) であっても document.write() の使用は勧められていない。

訳注 2: innerHTML は 2018 年現在、DOM Parsing and Serialization 仕様で定義されている。

訳注: WAIC では SCR21 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR21 では、「達成可能」と評価されている。WAIC はこの達成方法が検証した環境で広く動作すると判断している。

事例

事例 1

この例では、クライアントサイドスクリプトの使用法として、フォームの検証方法を紹介している。もしエラーがみつかれば、適切なエラーメッセージが表示される。この例では DOM 関数を使用し、タイトル、エラーに関する短い説明、及びエラー一覧の順序付リストを含むエラー通知を追加している。タイトルの内容はリンクとして書かれているので、focus メソッドを使って利用者の注意をエラーに向けることができる。個別のリスト項目もまた、リンクとして書かれているので、そのリンク先に移動したときにエラーのあるフォームのフィールドにフォーカスできるように書かれている。

この例では、簡単にするために二つのテキストフィールドだけを検証しているが、一般的なフォームハンドラにするために容易に拡張することができる。クライアントサイドの検証は、それを唯一の検証とすべきではなく、サーバーサイドの検証でも確認するべきである。クライアントサイドでの検証の利点は、利用者にすぐにフィードバックを提供することで、サーバーからエラーが帰ってくるまでの間、彼らを待たせることがないこと、及びサーバーへの余計なトラフィックを軽減できることである。

次の例はフォームにイベントハンドラを追加するスクリプトである。もしスクリプトが有効であれば、サーバーにフォームが送信される前に validateNumbers() 関数がクライアントサイドの検証のために呼び出される。もしスクリプトが有効でなければ、フォームはすぐにサーバー側に送信されるので、検証機能はサーバーにも実装されるべきである。

コード例:


window.onload = initialise;
function initialise()
{
  // 標準に準拠したユーザエージェントが対象
  if (!document.getElementById || !document.createElement || !document.createTextNode)
    return;

  // フォームにイベントハンドラを付加
  var objForm = document.getElementById('numberform');
  objForm.onsubmit= function(){return validateNumbers(this);};
} 

次の例は validation の機能である。エラーメッセージの要素を作成するために createElement()、createTextNode()、及び appendChild() DOM 関数を使用しているところに注目して欲しい。

コード例:


function validateNumbers(objForm)
{
  // フィールドを検証
  var bFirst = isNumber(document.getElementById('num1').value);
  var bSecond = isNumber(document.getElementById('num2').value);
  // 問題がある場合、エラーを表示
  if (!bFirst || !bSecond)
  {
    var objExisting = document.getElementById('validationerrors');
    var objNew = document.createElement('div');
    var objTitle = document.createElement('h2');
    var objParagraph = document.createElement('p');
    var objList = document.createElement('ol');
    var objAnchor = document.createElement('a');
    var strID = 'firsterror';
    var strError;
    // 見出し要素にリンクを含めることによって、スクリーンリーダーは
    // フォーカスを置くことができる - そのリンク先はエラー一覧の中で 
    // 一番最初のエラー項目とする
    objAnchor.appendChild(document.createTextNode('Errors in Submission'));
    objAnchor.setAttribute('href', '#firsterror');
    objTitle.appendChild(objAnchor);
    objParagraph.appendChild(document.createTextNode('Please review the following'));
    objNew.setAttribute('id', 'validationerrors');
    objNew.appendChild(objTitle);
    objNew.appendChild(objParagraph);
    // 発見したエラーすべてをエラー一覧に追加
    if (!bFirst)
    {
      strError = 'Please provide a numeric value for the first number';
      objList.appendChild(addError(strError, '#num1', objForm, strID));
      strID = '';
    }
    if (!bSecond)
    {
      strError = 'Please provide a numeric value for the second number';
      objList.appendChild(addError(strError, '#num2', objForm, strID));
      strID = '';
    }
    // エラー情報に一覧を追加
    objNew.appendChild(objList);
    // 既存のエラーがあった場合、新規のエラーと置き換える
    // あるいは、新規のエラーをフォームの先頭に追加する
    if (objExisting)
      objExisting.parentNode.replaceChild(objNew, objExisting);
    else
    {
      var objPosition = objForm.firstChild;
      objForm.insertBefore(objNew, objPosition);
    }
    // フォーカスを見出しにあるアンカーに置いて、スクリーンリーダーに
    // 対してエラーがあることを警告する
    objAnchor.focus();
    // フォームを送信しない
    objForm.submitAllowed = false;
    return false;
  }
  return true;
}

// 数字を検証する関数
function isNumber(strValue)
{
  return (!isNaN(strValue) &amp;&amp; strValue.replace(/^\s+|\s+$/, '') !== '');
} 

以下は、エラーメッセージを作成して、関連するフォームのフィールドにフォーカスさせるための補助関数である。

コード例:


// エラー内容を説明する、エラーのフォームフィールドへのリンクの
// リスト項目を作成する関数
function addError(strError, strFragment, objForm, strID)
{
  var objAnchor = document.createElement('a');
  var objListItem = document.createElement('li');
  objAnchor.appendChild(document.createTextNode(strError));
  objAnchor.setAttribute('href', strFragment);
  objAnchor.onclick = function(event){return focusFormField(this, event, objForm);};
  objAnchor.onkeypress = function(event){return focusFormField(this, event, objForm);};
  // strIDに値がある場合、これがリストで一番目のエラーとなる
  if (strID.length > 0)
    objAnchor.setAttribute('id', strID);
  objListItem.appendChild(objAnchor);
  return objListItem;
}

// エラーのフォームフィールドにフォーカスを置く関数
function focusFormField(objAnchor, objEvent, objForm)
{
  // キーボードナビゲーションを可能にするAllow keyboard navigation over links
  if (objEvent &amp;&amp; objEvent.type == 'keypress')
    if (objEvent.keyCode != 13 &amp;&amp; objEvent.keyCode != 32)
      return true;
  // フォーカスをフォームコントロールに設定する
  var strFormField = objAnchor.href.match(/[^#]\w*$/);
  objForm[strFormField].focus();
  return false;
} 

以下は事例のフォーム用 HTML である。

コード例:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
	<title>ECMAScript Form Validation</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<script type="text/javascript" src="validate.js"></script>
</head>
<body>
<h1>Form Validation</h1>
<form id="numberform" method="post" action="form.php">
<fieldset>
<legend>Numeric Fields</legend>
<p>
<label for="num1">Enter first number</label>
<input type="text" size="20" name="num1" id="num1">
</p>
<p>
<label for="num2">Enter second number</label>
<input type="text" size="20" name="num2" id="num2">
</p>
</fieldset>
<p>
<input type="submit" name="submit" value="Submit Form">
</p>
</form>
</body>
</html>

この例はクライアントサイドスクリプトに限定しているため、サーバーサイドの検証によって補完されるべきである。例では、クライアントサイドスクリプトが利用できるときのエラーメッセージの作成に限定される。

このコードの実装サンプル: フォームの検証

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

(今のところ、なし。)

検証

手順

動的に新しいコンテンツを作成するページに対して:

  1. ソースコードを検証して、新しいコンテンツが document.write()、innerHTML、outerHTML、innerText 又は outerText を用いて作成されていないことを確認する。

訳注: 解説の訳注で示した document.write()innerHTML に加えて、outerHTML は 2018 年現在、DOM Parsing and Serialization 仕様で定義されており、innerTextHTML 5.2§3.2.6. The innerText IDL attribute で定義されている。したがって、手順 1 に示されるものに関しては、outerText のみが非標準である。HTMLElement.outerText - Web APIs | MDN も参照のこと。

期待される結果

  • 1. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR22: 点滅を制御し、5 秒以内に停止させるために、スクリプトを使用する

適用 (対象)

スクリプトで制御されたコンテンツの点滅をサポートするウェブコンテンツ技術

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、スクリプトによる点滅を、5 秒未満で停止する設定にできるよう制御することである。 スクリプトを用いて、コンテンツの点滅効果を開始し、表示と非表示の状態切り替えを制御し、そして 5 秒以下で停止させる。setTimeout() 関数を用いて、点滅するコンテンツの表示と非表示の状態を切り替え、点滅の回数と所要時間の積が 5 秒近くになった時に停止させる。

事例

事例 1

この例では、JavaScript を用いて HTML 及び XHTML コンテンツの点滅を制御する。JavaScript は、コンテンツの表示状態を制御して点滅効果を生みだす。効果の開始を制御し、5 秒以内に停止させる。

コード例:

...
<div id="blink1" class="highlight">New item!</div>
<script type="text/javascript">
<!--
// 点滅「on」状態
function show()
{
	if (document.getElementById)
	document.getElementById("blink1").style.visibility = "visible";
}
// 点滅「off」状態
function hide()
{
	if (document.getElementById)
	document.getElementById("blink1").style.visibility = "hidden";
}
// 点滅効果を出すために「on」と「off」の状態を450ミリ秒ごとに切り替え
// 4500ミリ秒後に終了 (5秒未満)
for(var i=900; i < 4500; i=i+900)
{
	setTimeout("hide()",i);
	setTimeout("show()",i+450);
}
-->
</script>
...

検証

手順

点滅しているコンテンツのそれぞれの箇所に対して:

  1. 点滅効果が開始される時、5 秒間のタイマーを開始させる。

  2. タイマーが切れるとき、点滅が停止している。

期待される結果

  • 点滅しているコンテンツのそれぞれの箇所に対して、2. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR24: 利用者の要求に応じて新しいウィンドウを開くために、プログレッシブエンハンスメントを使用する

適用 (対象)

HTML 4.01 及び XHTML 1.0

訳注: HTML4 及び XHTML 1.0 は Superseded Recommendation としてマークされ、廃止された仕様である。

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、利用者が要求していない新しいウィンドウの出現によって引き起こされうる混乱を回避することである。突然新しいウィンドウが開くと、利用者は混乱したり、そのことに気づかなかったりする。文書型が target 属性を認めていない場合 (HTML 4.01 Strict や XHTML 1.0 Strict には存在しない)、又はコンテンツ制作者が target 属性の使用を好まない場合には、ECMAScript を用いて新しいウィンドウを開くことができる。以下にある事例は、スクリプトを用いて新しいウィンドウを開く方法を示している。その事例では、リンク (a 要素) にイベントハンドラを追加して、利用者にリンク先のコンテンツが新しいウィンドウで開くことを事前に知らせている。

事例

事例 1

マークアップ:

スクリプトはドキュメントの head 要素内に組み込まれており、リンクにはスクリプトのフックとなる id 属性がある。

コード例:


<script type="text/javascript" src="popup.js"></script>
…
<a href="help.html" id="newwin">Show Help</a>

スクリプト:

コード例:


// ブラウザによるイベント登録のサポートは不十分だが
// 従来のイベントモデルを用いる
window.onload = addHandlers;

function addHandlers()
{
  var objAnchor = document.getElementById('newwin');

  if (objAnchor)
  {
    objAnchor.firstChild.data = objAnchor.firstChild.data + ' (opens in a new window)';
    objAnchor.onclick = function(event){return launchWindow(this, event);}
    // UAAG ではユーザエージェントにデバイス非依存な方法でイベントを処理することを
    // 要求しているが、そうしないブラウザが多いのでキーボードイベントを追加する
    objAnchor.onkeypress = function(event){return launchWindow(this, event);}
  }
}

function launchWindow(objAnchor, objEvent)
{
  var iKeyCode, bSuccess=false;

  // キーボードからのイベントである場合、利用者がリンクをリクエストしたときだけ
  // 新しいウィンドウを開くようにする (リターン又はスペース)
  if (objEvent &amp;&amp; objEvent.type == 'keypress')
  {
    if (objEvent.keyCode)
      iKeyCode = objEvent.keyCode;
    else if (objEvent.which)
      iKeyCode = objEvent.which;

    // キャリッジリターン又はスペースではない場合、ユーザエージェントが
    // アクションの処理を継続するようにtrueを返す
    if (iKeyCode != 13 &amp;&amp; iKeyCode != 32)
      return true;
  }

  bSuccess = window.open(objAnchor.href);

  // ウィンドウが開かなかった場合、ブラウザには同じウィンドウで開くという
  // デフォルトのアクションを継続させる
  if (!bSuccess)
    return true;

  // ウィンドウが開いたら、ブラウザによる処理をそこで止める
  return false;
} 

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. ドキュメントにあるリンクを起動して、新しいウィンドウが開くかどうかを確認する。

  2. 新しいウィンドウを開くリンクごとに、次のいずれかを達成するためにスクリプトを用いることを確認する:

    1. リンクが新しいウィンドウを開くことを明示している

    2. デバイス非依存のイベントハンドラを用いている

    3. 新しいウィンドウを開けない場合、ブラウザが同じウィンドウにリンク先のコンテンツを開くことができる。

期待される結果

  • 2.の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR26: 動的なコンテンツを、Document Object Model の、そのトリガーとなる要素の直後に挿入する

適用 (対象)

HTML 及び XHTML、スクリプト

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、Document Object Model (DOM) に挿入されたユーザインタフェースの要素をタブ順序及びスクリーンリーダーの読み上げ順序がユーザエージェント標準のふるまいによって正しく設定されるような方法で配置することである。この達成方法は、メニューやダイアログのように隠れているものと表示されているもの、全てのユーザインタフェース要素に利用することができる。

スクリーンリーダーの読み上げ順序は、Document Object Model 内の HTML 又は XHTML の要素の順序に基づいており、それはタブ順序についても同様である。この達成方法では、新しいコンテンツを DOM のそのトリガーとなる要素の直後に挿入する。トリガーとなる要素は、リンク又はボタンでなければならず、スクリプトはその onclick イベントにより呼び出されなければならない。これらの要素はもともとフォーカス可能であり、その onclick イベントはデバイスに依存しない。フォーカスは選択された要素に残り、その後に挿入された新しいコンテンツは、タブ順序及びスクリーンリーダーの読み上げ順序の両方において、次の順番となる。

この達成方法は同期された更新にも利用できることに注目して欲しい。(AJAX と呼ばれることのある) 非同期の更新では、支援技術に非同期のコンテンツが挿入されたことを通知するために追加の達成方法が必要となる。

訳注: WAIC では SCR26 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR26 では、「達成可能」と評価されている。WAIC はこの達成方法が検証した環境で広く動作すると判断している。

事例

事例 1

この例では、リンクがクリックされた際にメニューを生成し、そのリンクの後に挿入する。リンクの onclick イベントは新しいメニューのための ID をパラメータとして渡す ShowHide スクリプトを呼び出すために使用される。

コード例:

<a href="#" onclick="ShowHide('foo',this)">Toggle</a>

ShowHide スクリプトは新しいメニューを含む div を生成し、リンクを挿入する。最終行がスクリプトの核心となる。スクリプトのトリガーとなる要素の親を探し、新しい子として生成された div をそれに追加する。これにより、新しい div は DOM 内でリンクの次になる。利用者がタブを押したときには、フォーカスがメニュー内で最初のフォーカス可能な項目となる生成されたリンクに移動する。

コード例:


function ShowHide(id,src)
{
	var el = document.getElementById(id);
	if (!el)
	{
		el = document.createElement("div");
		el.id = id;
		var link = document.createElement("a");
		link.href = "javascript:void(0)";
		link.appendChild(document.createTextNode("Content"));
		el.appendChild(link);
		src.parentElement.appendChild(el);
	}
	else
	{
		el.style.display = ('none' == el.style.display ? 'block' : 'none');
	}
} 

CSS は div およびリンクをメニューのように見せるために利用される。

検証

手順

  1. ポップアップではないダイアログのトリガーとなる全てのエリアを探す。

  2. そのダイアログがボタン又はリンクのクリックイベントによりトリガーされる。

  3. スクリプトによって生成された DOM を調査できるツールを使って、ダイアログが DOM 内で次の位置にきている。

期待される結果

  • 2. 及び 3. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR27: Document Object Model を用いて、ページ上にある複数のセクションを並び替える

適用 (対象)

HTML および XHTML、スクリプト

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、コンポーネントを再配置するための極めてユーザブルかつアクセシブルなメカニズムを提供することである。再配置するためのメカニズムのうち、もっとも一般的なものは、コンポーネントに番号をつけることができる設定ページに利用者を送ること、又は、コンポーネントをドラッグ&ドロップして希望する位置へ移動できるようにすることのふたつである。ドラッグ&ドロップの方が、ひとつずつ項目を適当な位置に並べることができ、結果を感覚的に得られるため、はるかにユーザブルな方法である。残念なことに、ドラッグ&ドロップはマウスの利用に頼った方法である。この達成方法は、利用者がコンポーネントのメニューを使って、それらを機器に依存することなく適当な位置に再配置することを可能にする。ドラッグ&ドロップによる再配置機能の代替として、もしくはそれと併用して利用することができる。

メニューはリンクリストで、コンテンツを再配置するスクリプトのトリガーとなる、機器に依存しない onclick イベントを使用している。コンテンツは単に視覚的にだけでなく、Document Object Model (DOM) でも再配置されているので、すべての機器向けに正しい順序となっている。

事例

事例 1

この例は上下間の再配置を行う。このアプローチはまた、右と左のオプションを追加することで、2 次元での再配置にも利用できる。

この例のコンポーネントは順序無しリストのリスト項目である。順序無しリストは、こうしたコンポーネントのような類似項目のためのとてもよいセマンティックモデルである。メニューを使う方法も、他のタイプのグループ化に使用できる。

モジュールはリスト項目であり、それぞれのモジュールは、div 要素内のコンテンツに加えて、入れ子になったリストとして表されたメニューを含んでいる。

コード例:

<ul id="swapper">
    <li id="black">
        <div class="module">
            <div class="module_header">
                <!-- menu link -->
                <a href="#" onclick="ToggleMenu(event);">menu</a>
                <!-- menu -->
                <ul class="menu">
                    <li><a href="#" onclick="OnMenuClick(event)" 
                        onkeypress="OnMenuKeypress(event);">up</a></li>
                    <li><a href="#" onclick="OnMenuClick(event)" 
                        onkeypress="OnMenuKeypress(event);">down</a></li>
                </ul>
            </div>
            <div class="module_body">
                Text in the black module
            </div>
        </div>
    </li>
    ...
</ul>

ここまでは、簡単なツリーの例でメニューを出したり隠したりする方法をとりあげてきたので、モジュールを入れ替えるコードについても着目する。イベントを同期させてデフォルトのリンクアクションをキャンセルしてから、作業に移動する。最初に、これから作業する要素、メニュー、再配置されるモジュール、メニューリンクのための一連のローカル変数をセットする。それから、再配置の方向を確認した後に、入れ替えるノードの取得を試みる。ノードを見つけた場合、swapNode() を呼び出して二つのモジュールを入れ替え、 PositionElement() でモジュールと共に絶対配置されたメニューを移動し、すべてが完了したメニュー項目にフォーカスを設定する。

コード例:

function MoveNode(evt,dir)
{
    HarmonizeEvent(evt);
    evt.preventDefault();

    var src = evt.target;
    var menu = src.parentNode.parentNode;
    var module = menu.parentNode.parentNode.parentNode;
    var menuLink = module.getElementsByTagName("a")[0];
    var swap = null;
    
    switch(dir)
    {
        case 'up':
        {
            swap = module.previousSibling;
            while (swap &amp;&amp; swap.nodeType != 1)
            {
                swap = swap.previousSibling;
            }
            break;
        }
        case 'down':
        {
            swap = module.nextSibling;
            while (swap &amp;&amp; swap.nodeType != 1)
            {
                swap = swap.nextSibling;
            }
            break;
        }
    }
    if (swap &amp;&amp; swap.tagName == node.tagName)
    {
        module.swapNode(swap);
        PositionElement(menu,menuLink,false,true);
    }
    src.focus();
} 

ノード入れ替えの CSS は、モジュール及び小さなメニューのサイズや色の調整だけで、前のツリーの例と大きな違いはない。

コード例:


ul#swapper { margin:0px; padding:0px; list-item-style:none; }
ul#swapper li { padding:0; margin:1em; list-style:none; height:5em; width:15em; 
    border:1px solid black; }
ul#swapper li a { color:white; text-decoration:none; font-size:90%; }

ul#swapper li div.module_header { text-align:right; padding:0 0.2em; }
ul#swapper li div.module_body { padding:0.2em; }

ul#swapper ul.menu { padding:0; margin:0; list-style:none; background-color:#eeeeee; 
    height:auto; position:absolute; text-align:left; border:1px solid gray; display:none; }
ul#swapper ul.menu li { height:auto; border:none; margin:0; text-align:left; 
    font-weight:normal; width:5em; }
ul#swapper ul.menu li a { text-decoration:none; color:black; padding:0 0.1em; 
    display:block; width:100%; } 

検証

手順

  1. ドラッグ&ドロップで再配置可能なウェブユニット内のすべてのコンポーネントを探す。

  2. リンクのリストで構成されたメニューを用いて、それらが再配置可能なメカニズムがあることを確認する。

  3. メニューが DOM 内の再配置可能な項目の中に含まれていることを確認する。

  4. 再配置のスクリプトはリンクの onclick イベントだけをトリガーにしていることを確認する。

  5. 視覚的にだけではなく、項目が DOM の中でも再配置されていることを確認する。

期待される結果

  • 2.~5. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR28: コンテンツのブロックをバイパスするために、展開可能及び折り畳み可能なメニューを使用する

適用 (対象)

クライアントサイドスクリプティングを提供するウェブコンテンツ技術

これは、次の達成基準に関連する達成方法である:

解説

この達成方法は、繰り返される構成要素を利用者のコントロールの下でメニューを展開したり折りたたんだりできるメニューの中に置くことで、その構成要素をスキップできるようにする。利用者は、メニューを折りたたむことで繰り返される構成要素をスキップできる。利用者は、メニューの要素を隠したり削除したりするユーザインタフェースを呼び出すことができる。関連情報には、ナビゲーションをスキップするメカニズムを提供するために利用できるメニュー、ツールバー及びツリーの達成方法をいくつか挙げている。

注記: 類似の方法は、サーバーサイドスクリプティングを用いて修正後のウェブページを読み込むことでも実装できる。

事例

事例 1

ウェブページの先頭にあるナビゲーションリンクは、すべて HTML、CSS 及び JavaScript を用いて実装されているメニュー項目である。ナビゲーションバーが展開しているとき、ナビゲーションのリンクは利用可能になっている。ナビゲーションバーがたたまれているとき、リンクは利用不可能である。

コード例:


...

  <script type="text/javascript">
  function toggle(id){
    var n = document.getElementById(id);
    n.style.display =  (n.style.display != 'none' ? 'none' : '' );
  }
  </script>

...

  <a href="#" onclick="toggle('navbar')">Toggle Navigation Bar</a>
  
  <ul id="navbar">
  <li><a href="http://target1.html">Link 1</a></li>
  <li><a href="http://target2.html">Link 2</a></li>
  <li><a href="http://target3.html">Link 3</a></li>
  <li><a href="http://target4.html">Link 4</a></li>
  </ul>

... 

このコードの実装サンプル: ナビゲーションバーをリンクで切り替える

訳注: WAIC では SCR28-1 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR28-1 では、「要注意」と評価されている。WAIC はウェブ制作者にこの達成方法が一部の環境では動作しないことに注意を促すものである。

事例 2

一連のウェブページのための目次はそれぞれのページの先頭近くで繰り返される。目次の先頭にあるボタンで、利用者はそれを消したり復元したりできる。

コード例:


...

   <script type="text/javascript">
  function toggle(id){
    var n = document.getElementById(id);
    n.style.display =  (n.style.display != 'none' ? 'none' : '' );
  }
  </script>

  ...

  <button onclick="return toggle('toc');">Toggle Table of Contents</button>
  <div id="toc">
    ...
  </div>

...

このコードの実装サンプル: 目次をボタンで切り替える

訳注: WAIC では SCR28-2 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR28-2 では、「要注意」と評価されている。WAIC はウェブ制作者にこの達成方法が一部の環境では動作しないことに注意を促すものである。

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. ユーザインタフェースコントロールで、繰り返されるコンテンツを展開したり折りたたんだりできることを確認する。

  2. コンテンツが展開されたとき、それが読み上げ順序の論理的な場所でプログラムによる解釈が可能なコンテンツに含まれていることを確認する。

  3. コンテンツが折りたたまれているとき、それがプログラムによる解釈が可能でない部分にあることを確認する。

期待される結果

  • 上記の全ての項目の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR29: 静的な HTML 要素にキーボードアクセシブルなアクションを追加する

適用 (対象)

HTML 及び XHTML、スクリプト

これは、次の達成基準に関連する達成方法である:

ユーザエージェント及び支援技術によるサポート

SCR29 に関するユーザエージェントサポートノートを参照のこと。

解説

この達成方法の目的は、 divspan などの静的な HTML 要素により実行されるユーザインターフェース コントロールにキーボードアクセスを提供する方法を示すことである。この達成方法は tabindex 属性を設定することで要素をフォーカス可能にし、onclick ハンドラに加えて onkeyup 又は onkeypress ハンドラを提供することでキーボードから動作を実行することができるようにするものである。

tabindex 属性の値が 0 の際、要素はキーボードでフォーカス可能であり、文書のタブ順序に含まれる。tabindex 属性の値が -1 の際、要素はタブ移動できないが、element.focus() を使用することによりフォーカスをプログラムで制御できる。

静的な HTML 要素にはそれらに関連した動作がないため、スクリプトが利用できない環境に対する、代替としての実装又は説明を提供することはできない。この達成方法はクライアントサイド スクリプティングが利用できる環境でのみ使用されるべきである。

注記: そのようなユーザインターフェース コントロールは SC 4.1.2 を達成しなければならない。ユーザインターフェース コントロールの役割、名前及び状態についての情報がないままこの達成基準を適用する場合、失敗例 F59 に該当し、スクリプトを用いて、HTML の div 要素又は span 要素をユーザインタフェースのコントロールにしたことによる達成基準 4.1.2 の失敗例となる。

事例

事例 1: div 要素に JavaScript によるアクションを追加する

ページにある div 要素には一意の id 属性及び値が 0 の tabindex 属性が付与されている。スクリプトはドキュメントオブジェクトモデル (DOM) を利用し、id によって div 要素を見つけ onclick ハンドラ及び onkeyup ハンドラを追加する。onkeyup ハンドラは Enter キーが押下された際、アクションを実行する。div 要素を見つけて変更するには、div 要素が DOM の中に読み込まれた状態でなければならないことに注意する。これは、通常、body 要素の onload イベントでスクリプトを呼び出すことで達成される。イベントハンドラを追加するスクリプトはユーザエージェントが JavaScript をサポートし、かつ有効にしている場合にのみ実行される。

コード例:


...
<script type="text/javascript">
 // これはアクションを実行する関数である。このシンプルな例はメッセージを開閉する。
 function doSomething(event) {
   var msg=document.getElementById("message");
   msg.style.display = msg.style.display=="none" ? "" : "none";
   // リンクのhref属性が実行されないよう、関数からfalseを返す
   return false;
 }
 // これは Enter キーが押された際にアクションが実行される関数である。
 function doSomethingOnEnter(event) {
   var key = 0;
   // window.event 又はイベントオブジェクトが使用されているかに応じて押されたキーを判定する。
   if (window.event) {
     key = window.event.keyCode;
   } else if (event) {
     key = event.keyCode;
   }
   // Enter キーが押されたか?
   if (key == 13) {
     return doSomething(event);
   } 
   // イベントが処理されなかったため、trueを返す
   return true;
 }
 // このsetUpActions()関数は存在するdiv要素にonclick及びonkeyupイベントハンドラを設定するために呼び出されなければならない。
 // この関数はid="active"の付与されたdiv要素がDOMに読み込まれた後に呼び出されなければならない。
 // この例では、setUpActions()関数はbody要素のonloadイベントから呼び出されている。
 function setUpActions() {
   // divオブジェクトを取得する
   var active=document.getElementById("active");
   // onclickハンドラをオブジェクトに割り当てる
   // 関数が返された後、href属性を止めるため、onclickハンドラからfalseを返すことが重要である
   active.onclick=doSomething;
   // onkeyupハンドラをオブジェクトに割り当てる
   active.onkeyup=doSomethingOnEnter;
 }
 </script>

 <body onload="setUpActions();">
 <p>Here is the link to modify with a javascript action:</p>
 <div>
  <span id="active" tabindex="0">Do Something</span>
 </div>
 <div id="message">Hello, world!</div>
...

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

訳注 1: HTML 4.01 は Superseded Recommendation としてマークされ、廃止された仕様である。上記はそれぞれ、HTML 5.2§4.12. ScriptingHTML 5.2§5.4.3. The tabindex attribute を代わりに参照できる。

訳注 2: 「WAI-ARIA Primer, Provision of the keyboard or input focus」が挙げられているが、WAI-ARIA 1.0 Primer は作成が破棄されている。代わりに、WAI-ARIA Authoring Practices 1.1 §5. Developing a Keyboard Interface を参照できる。

訳注 3: DOM 仕様は現在、WHATWG で策定されている。DOM Standard も参照のこと。

訳注 4: MSDN のページ「Internet Explorer, HTML and DHTML Reference, tabIndex Property」が MDN にリダイレクトされているが、これは MSDN の文書が MDN に統合されたためである。このリダイレクト処理の詳細については、Microsoft Edge Dev Blog 及びマイナビニュースを参照されたい。

検証

手順

スクリプトをサポートするユーザエージェントで:

  1. マウスを用い、コントロールをクリックする。

  2. スクリプトのアクションが適切に実行されることを確認する。

  3. キーボードでコントロールに移動して、フォーカスを与えることが可能であることを確認する。

  4. キーボードのフォーカスをコントロールに設定する。

  5. Enter キーを押すことで、スクリプトのアクションを呼び出すことを確認する。

期待される結果

  • 手順全ての結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR30: リンクテキストを変更するために、スクリプトを使用する

適用 (対象)

HTML 及び XHTML で使用されるクライアントサイドスクリプト

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、リンクが文脈以外でも理解可能になるように、追加情報をリンクテキストに加えることを利用者が選択できるようにすることである。

一部の利用者は、リンクの文脈を参照する必要がないように、リンクがすべてを含んでいることを好む。別の利用者は、それぞれのリンクに文脈に関する情報が含まれていると、反復されてサイトの使い勝手が低下すると感じている。支援技術の利用者の間では、どちらが好ましいかに関して、ワーキンググループへのフィードバックは分かれている。この達成方法は、利用者自身にとって良い方法を選ぶことを可能にする。

どのようなリンクの目的を理解する場合でも追加の文脈が必要とならないようにするため、そのページのリンクのリンクテキストを展開するページの先頭近くにリンクが提供される。展開されるリンクの目的がそのリンクテキストから、常に直接理解可能でなければならない。

この達成方法では、現在表示されているページのリンクだけを展開する。利用者がそのサイトに対して 1 度だけ設定を行えば良いようにするために、設定情報を Cookie 又はサーバーサイドのユーザプロファイルに保存することも可能であり、場合によってはそれが望ましい。

事例

事例 1

この例では、JavaScript を用いて直接リンクのテキストに文脈上の情報を追加する。link クラスはどのテキストを追加するかを決定する。「リンクを展開する」リンクが選択されたとき、ページ内のそれぞれのリンクにテキストを追加すべきかがテストされる。

コード例:


...
<script type="text/javascript">
var expanded = false;
var linkContext = {
	"hist":" version of The History of the Web",
	"cook":" version of Cooking for Nerds"
};

function doExpand() {
	var links = document.links;
	
	for (link of links) {
		var cn = link.className;
		if (linkContext[cn]) {
			span = link.appendChild(document.createElement("span"));
			span.setAttribute("class", "linkexpansion");
			span.appendChild(document.createTextNode(linkContext[cn]));
		}
	}
	objUpdate = document.getElementById('expand');
	if (objUpdate)
	{
		objUpdate.childNodes[0].nodeValue = "Collapse links";
	}
	expanded = true;
}

function doCollapse() {
	objUpdate = document.getElementById('expand');
	var spans = document.getElementsByTagName("span");
	var span;

	// リンク一式を戻り、文頭から削除することで配列の添え数を変更する
	// そして処理を乱す
	for (i = spans.length - 1; i >= 0; i--) {
		span = spans[i];
		if (span.getAttribute("class") == "linkexpansion")
			span.parentNode.removeChild(span);
	}
	if (objUpdate)
	{
		objUpdate.childNodes[0].nodeValue = "Expand links";
	}
	expanded = false;
}

function toggle() {
	if (expanded) doCollapse();
	else doExpand();
}
</script>

...

<h1>Books for download</h1>
<p><button id="expand" onclick="toggle();">Expand Links</button></p>
<ul>
	<li>The History of the Web: <a href="history.docx" class="hist">Word</a>, <a href="history.pdf" class="hist">PDF</a>, <a href="history.html" class="hist">HTML</a> </li>

	<li>Cooking for Nerds: <a href="history.docx" class="cook">Word</a>, <a href="history.pdf" class="cook">PDF</a>, <a href="history.html" class="cook">HTML</a> </li>
</ul>
...

このコードの実装サンプル: 要求に応じてリンクを展開する

検証

手順

  1. ページの先頭近くに、リンクを展開するリンクがあることを確認する

  2. 手順 1. で特定したリンクがリンクテキストだけで特定できることを確認する

  3. リンクテキストだけで特定できないリンクをページ中から探す

  4. 手順 1. で特定したコントロールを有効にする

  5. 手順 3. で特定したリンクの目的が、リンクテキストだけで特定できることを確認する

期待される結果

  • 1.、2. 及び 5. の結果が真である

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR31: フォーカスのある要素の背景色又はボーダーを変更するために、スクリプトを使用する

適用 (対象)

HTML 及び XHTML、CSS、Script

これは、次の達成基準に関連する達成方法である:

ユーザエージェント及び支援技術によるサポート

SCR31 に関するユーザエージェントサポートノートを参照のこと。

解説

この達成方法の目的は、コンテンツ制作者が CSS を適用してフォーカス表示を通常よりもより見やすくするために JavaScript を使えるようにすることである。要素がフォーカスを受ける時、背景色またはボーダーは視覚的に異なるように変化する。要素からフォーカスがはずれたとき元のスタイルにもどる。この達成方法は :focus 疑似クラスをサポートしているいないに関わらず、スクリプトや CSS をサポートしているどんな HTML のユーザエージェントでも用いることができる。

事例

事例 1

この事例において、リンクにフォーカスが当たった時、背景は黄色に変わる。フォーカスがはずれたとき、黄色ではなくなる。もしリンクに背景色がある場合は、スクリプト内で””よりむしろその色を用いることに注意する。

コード例:

...
<script>
 function toggleFocus(el)
 {
  el.style.backgroundColor =  el.style.backgroundColor=="yellow" ? "inherit" : "yellow";
 }
</script>

...

<a href="example.html" onfocus="toggleFocus(this)" onblur="toggleFocus(this)">focus me</a>
...

検証

手順

  1. ページ内の各要素にタブ移動する。

  2. フォーカス表示が可視であることを確認する。

期待される結果

  • 2.の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR32: クライアントサイドのバリデーションを提供し、DOM を介してエラーテキストを追加する

適用 (対象)

HTML 又は XHTML で使用されるスクリプト。

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、クライアントサイドでフォームフィールドの検証に失敗したときにエラーメッセージを表示する方法について説明することである。アンカー要素はリスト中でエラーメッセージを表示させる際に使用され、検証が必要なフィールドの上に挿入される。フォーカスをエラーメッセージの場所に移し、利用者の注意を引くために、アンカー要素がエラーメッセージに使用される。アンカー要素の href は、エラーがみつかったフィールドへのページ内リンクを含む。

配置されたアプリケーションにおいて、もし JavaScript が無効になっていれば、クライアントサイドの検証は行われない。そのため、この達成方法はスクリプトが適合性において信頼できる、又はサーバーサイドの検証技術があらゆるエラーを発見し、エラーを含むフィールドの情報とともにページを返すように用いられている場合のみ、十分であるといえる。

訳注: WAIC では SCR32 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR32 では、「達成可能」と評価されている。WAIC はこの達成方法が検証した環境で広く動作すると判断している。

事例

事例 1

この事例は必須のフィールドを検証し、さらに特定の書式が必要なフィールドを検証する。エラーがみつかったとき、スクリプトはエラーメッセージの一覧を DOM に挿入し、フォーカスをそこへ移動する。

サンプルの画面イメージ: スクリーンショットは、正しく記入が行われていないいくつかのフィールドのエラーメッセージをあらわしている。エラーメッセージはリンクリストでフォームの先頭近くに現れる。

HTML 及び Javascript のコード

これは事例のフォームの HTML である:

コード例:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <title>Form Validation</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link href="css/validate.css" rel="stylesheet" type="text/css"/>
        <script type="text/javascript" src="scripts/validate.js"/>
    </head>
    <body>

        <h1>Form Validation</h1>

        <p>The following form is validated before being submitted if scripting is available,
            otherwise the form is validated on the server. All fields are required, except those
            marked optional. If errors are found in the submission, the form is cancelled and 
            a list of errors is displayed at the top of the form.</p>

        <p> Please enter your details below. </p>

        <h2>Validating Form</h2>

        <form id="personalform" method="post" action="index.php">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Personal Details</legend>
                <p>
                    <label for="forename">Please enter your forename</label>
                    <input type="text" size="20" name="forename" id="forename" class="string"
                        value=""/>
                </p>
                <p>
                    <label for="age">Please enter your age</label>
                    <input type="text" size="20" name="age" id="age" class="number" value=""/>
                </p>
                <p>
                    <label for="email">Please enter your email address</label>
                    <input type="text" size="20" name="email" id="email" class="email" value=""/>
                </p>
            </fieldset>
            <p>
                <input type="submit" name="signup" value="Sign up"/>
            </p>
        </form>
        <h2>Second Form</h2>
        <form id="secondform" method="post" action="index.php#focuspoint">
            <div class="validationerrors"/>
            <fieldset>
                <legend>Second Form Details</legend>
                <p>
                    <label for="suggestion">Enter a suggestion</label>
                    <input type="text" size="20" name="suggestion" id="suggestion" 
                      class="string" value=""/>
                </p>
                <p>
                    <label for="optemail">Please enter your email address (optional)</label>
                    <input type="text" size="20" name="optemail" id="optemail"
                        class="optional email" value=""/>
                </p>
                <p>
                    <label for="rating">Please rate this suggestion</label>
                    <input type="text" size="20" name="rating" id="rating" 
                      class="number" value=""/>
                </p>
                <p>
                    <label for="jibberish">Enter some jibberish (optional)</label>
                    <input type="text" size="20" name="jibberish" id="jibberish" value=""/>
                </p>

            </fieldset>
            <p>
                <input type="submit" name="submit" value="Add Suggestion"/>
            </p>
        </form>
    </body>
</html>                      

以下は検証を行ってエラーメッセージを挿入する JavaScript である:

コード例:


window.onload = initialise;

function initialise()
{
   var objForms = document.getElementsByTagName('form');
   var iCounter;

   // フォームそれぞれにイベントハンドラを追加
   for (iCounter=0; iCounter<objForms.length; iCounter++)
   {
      objForms[iCounter].onsubmit = function(){return validateForm(this);};
   }
}


// フォームのイベントハンドラ
function validateForm(objForm)
{
   var arClass = [];
   var iErrors = 0;
   var objField = objForm.getElementsByTagName('input');
   var objLabel = objForm.getElementsByTagName('label');
   var objList = document.createElement('ol');
   var objError, objExisting, objNew, objTitle, objParagraph, objAnchor, objPosition;
   var strLinkID, iFieldCounter, iClassCounter, iCounter;

   // 部分識別子を固有にするため、
   // フォームのid又はnameを取得する
   if (objForm.id)
   {
      strLinkID = objForm.id + 'ErrorID';
   }
   else
   {
      strLinkID = objForm.name + 'ErrorID';
   }

   // validationクラスを探索するため、inputフォームコントロールをループする
   for (iFieldCounter=0; iFieldCounter<objField.length; iFieldCounter++)
   {
      // フィールドのクラスを取得し、適切なクラスを探す
      arClass = objField[iFieldCounter].className.split(' ');
      for (iClassCounter=0; iClassCounter<arClass.length; iClassCounter++)
      {
         switch (arClass[iClassCounter])
         {
            case 'string':
               if (!isString(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
            case 'number':
               if (!isNumber(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;

            case 'email' :
               if (!isEmail(objField[iFieldCounter].value, arClass))
               {
                  if (iErrors === 0)
                  {
                     logError(objField[iFieldCounter], objLabel, objList, strLinkID);
                  }
                  else
                  {
                     logError(objField[iFieldCounter], objLabel, objList, '');
                  }
                  iErrors++;
               }
               break;
         }
      }
   }

   if (iErrors > 0)
   {
      // validではない場合、エラーメッセージを表示する
      objError = objForm.getElementsByTagName('div');
      
      // 存在しているエラーを探す
      for (iCounter=0; iCounter<objError.length; iCounter++)
      {
         if (objError[iCounter].className == 'validationerrors')
         {
            objExisting = objError[iCounter];
         }
      }

      objNew = document.createElement('div');
      objTitle = document.createElement('h2');
      objParagraph = document.createElement('p');
      objAnchor = document.createElement('a');

      if (iErrors == 1)
      {
         objAnchor.appendChild(document.createTextNode('1 Error in Submission'));
      }
      else
      {
         objAnchor.appendChild(document.createTextNode(iErrors + ' Errors in Submission'));
      }
      objAnchor.href = '#' + strLinkID;
      objAnchor.className = 'submissionerror';

      objTitle.appendChild(objAnchor);
      objParagraph.appendChild(document.createTextNode('Please review the following'));

      objNew.className = 'validationerrors';

      objNew.appendChild(objTitle);
      objNew.appendChild(objParagraph);
      objNew.appendChild(objList);
      
      // 既にエラーがある場合、新しいエラーと交換する。
      // それ以外の場合、フォームの先頭に新しいエラーを追加する。
      if (objExisting)
      {
         objExisting.parentNode.replaceChild(objNew, objExisting);
      }
      else
      {
         objPosition = objForm.firstChild;
         objForm.insertBefore(objNew, objPosition);
      }

      // 待ち時間の設定
      setTimeout(function() { objAnchor.focus(); }, 50);
      
      // フォームを送信しない
      objForm.submitAllowed = false;
      return false;
   }

   // フォームを送信
   return true;
}

// 問題のあるフィールドコントロールを指すリスト項目にリンクを追加する関数
function addError(objList, strError, strID, strErrorID)
{
   var objListItem = document.createElement('li');
   var objAnchor = document.createElement('a');
   
   // フォームコントロールへの部分識別子
   objAnchor.href='#' + strID;

   // エラーの見出しに向けたターゲットにする
   if (strErrorID.length > 0)
   {
      objAnchor.id = strErrorID;
   }

   // エラーメッセージ用のラベルプロンプトを使う
   objAnchor.appendChild(document.createTextNode(strError));
   // フォームコントロールにフォーカスを当てるために、キーボード及びマウスイベントを追加する
   objAnchor.onclick = function(event){return focusFormField(this, event);};
   objAnchor.onkeypress = function(event){return focusFormField(this, event);};
   objListItem.appendChild(objAnchor);
   objList.appendChild(objListItem);
}

function focusFormField(objAnchor, objEvent)
{
   var strFormField, objForm;

   // キーボードでもリンクが機能するようにする
   if (objEvent &amp;&amp; objEvent.type == 'keypress')
   {
      if (objEvent.keyCode != 13 &amp;&amp; objEvent.keyCode != 32)
      {
         return true;
      }
   }

   // フォームコントロールにフォーカスを当てる
   strFormField = objAnchor.href.match(/[^#]\w*$/);
   objForm = getForm(strFormField);
   objForm[strFormField].focus();
   return false;
}

// 与えられたフォームフィールドの名前から、フォーム要素を返す関数
function getForm(strField)
{
   var objElement = document.getElementById(strField);

   // 適切なフォームを探す
   do
   {
      objElement = objElement.parentNode;
   } while (!objElement.tagName.match(/form/i) &amp;&amp; objElement.parentNode);

   return objElement;
}

// リスト中のエラーを記録する関数
function logError(objField, objLabel, objList, strErrorID)
{
   var iCounter, strError;

   // エラープロンプトのラベルを探す
   for (iCounter=0; iCounter<objLabel.length; iCounter++)
   {
      if (objLabel[iCounter].htmlFor == objField.id)
      {
         strError = objLabel[iCounter].firstChild.nodeValue;
      }
   }

   addError(objList, strError, objField.id, strErrorID);
}

// 検証ルーティン - 要求事項として

function isString(strValue, arClass)
{
   var bValid = (typeof strValue == 'string' &amp;&amp; strValue.replace(/^\s*|\s*$/g, '') 
     !== '' &amp;&amp; isNaN(strValue));

   return checkOptional(bValid, strValue, arClass);
}

function isEmail(strValue, arClass)
{
   var objRE = /^[\w-\.\']{1,}\@([\da-zA-Z\-]{1,}\.){1,}[\da-zA-Z\-]{2,}$/;
   var bValid = objRE.test(strValue);

   return checkOptional(bValid, strValue, arClass);
}

function isNumber(strValue, arClass)
{
   var bValid = (!isNaN(strValue) &amp;&amp; strValue.replace(/^\s*|\s*$/g, '') !== '');

   return checkOptional(bValid, strValue, arClass);
}

function checkOptional(bValid, strValue, arClass)
{
   var bOptional = false;
   var iCounter;

   // optionalについて確認
   for (iCounter=0; iCounter<arClass.length; iCounter++)
   {
      if (arClass[iCounter] == 'optional')
      {
         bOptional = true;
      }
   }

   if (bOptional &amp;&amp; strValue.replace(/^\s*|\s*$/g, '') === '')
   {
      return true;
   }

   return bValid;
   }

このコードの実装サンプルは、PHP、JavaScript、CSS 及び XHTML で実装されている: フォーム検証の例

検証

手順

アンカータグを用いてエラーメッセージを作成し、上記の達成方法による適切なスクリプトを使用する。

  1. ページを読み込む。

  2. エラーメッセージに関連付けられたフィールドに有効な値を入力し、エラーメッセージが表示されないことを確認する。

  3. エラーメッセージに関連付けられたフィールドに無効な値を入力し、そのフィールドに正確なエラーメッセージが表示されることを確認する。

  4. エラーメッセージがフォーカスを受け取ることを確認する。

  5. 表示されたエラーメッセージと関連付けられたフィールドに有効な値を入力し、エラーメッセージが除去されることを確認する。

  6. アンカータグによって作例されたエラーメッセージと関連付けられた全てのフィールドに対して、繰り返す。

注記: 上記の手順を、支援技術を用いて実行することも推奨する。

期待される結果

  • 2.、3.、4. 及び 5. の全ての結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR33: コンテンツをスクロールし、かつそれを一時停止するメカニズムを提供するためにスクリプトを使用する

適用 (対象)

スクリプトでコントロールされる、コンテンツのスクロールをサポートするウェブコンテンツ技術

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、スクロールするコンテンツがスクリプトで作成されている場合に、利用者にそのスクロールを停止する手段を提供することである。スクロールするコンテンツは、ロービジョンや認知障害の利用者にとって読みにくかったり、全く読めなかったりする。また、動くものは、一部の人々にとって、ウェブページのほかの部分に集中することへの妨げとなる。

事例

事例 1

この例では、CSS 及び JavaScript を用いて、いくつかのテキストを視覚的にスクロールさせている。スクロールの移動を停止するためのリンクが含まれている。

この方法では、JavaScript 又は CSS がサポートされていないか有効になっていないときは、すべてのテキストを表示し、リンクを省略する。

下のコードは、webSemantic によるアクセシブルなスクローラー (2008 年 7 月) の修正版である。

XHTML 部分:

コード例:

...
<div id="scroller">
<p id="tag">This text will scroll and a Pause/Scroll link will be present 
when Javascript and CSS are supported and active.</p>
</div>
...

CSS部分:

コード例:

...
body {font:1em verdana,sans-serif; color:#000; margin:0}

/* position:relative及びoverflow:hiddenは必須 */
#scroller { position:relative; overflow:hidden; width:15em; border:1px solid #008080; }

/* スクロールするテキスト用のフォーマットを追加 */
#tag { margin:2px 0; }

/* #testPは#tagのテキスト変更に関するプロパティを全て含む */
#testP { visibility:hidden; position:absolute; white-space:nowrap; } 

/* ページ先頭の目印として利用され、かつ幅を制限する */
#top { width:350px; margin:auto; }
...

JavaScript 部分:

コード例:


var speed=50        // スクロール速度
var step=3          // 動きのスムーズ度合い
var StartActionText= "Scroll"  // 開始させるリンクのテキスト
var StopActionText = "Pause"   // 停止させるリンクのテキスト

var x, scroll, divW, sText=""

function onclickIE(idAttr,handler,call){
  if ((document.all)&amp;&amp;(document.getElementById)){idAttr[handler]="Javascript:"+call}
}

function addLink(id,call,txt){
  var e=document.createElement('a')
  e.setAttribute('href',call)
  var linktext=document.createTextNode(txt)
  e.appendChild(linktext)
  document.getElementById(id).appendChild(e)
}

function getElementStyle() {
    var elem = document.getElementById('scroller');
    if (elem.currentStyle) {
        return elem.currentStyle.overflow;
    } else if (window.getComputedStyle) {
        var compStyle = window.getComputedStyle(elem, '');
        return compStyle.getPropertyValue("overflow");
    }
    return "";
}

function addControls(){
// 最初にCSSサポートをテスト
// style要素又は外部ファイルで定義されたoverflowプロパティ値をテスト
if (getElementStyle()=="hidden") {
  var f=document.createElement('div');
  f.setAttribute('id','controls');
  document.getElementById('scroller').parentNode.appendChild(f);
  addLink('controls','Javascript:clickAction(0)',StopActionText);
  onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction(0)');
  document.getElementById('controls').style.display='block';
  }
}

function stopScroller(){clearTimeout(scroll)}

function setAction(callvalue,txt){
  var c=document.getElementById('controls')
  c.childNodes[0].setAttribute('href','Javascript:clickAction('+callvalue+')')
  onclickIE(document.getElementById('controls').childNodes[0],"href",'clickAction

('+callvalue+')')
  c.childNodes[0].firstChild.nodeValue=txt
}

function clickAction(no){
  switch(no) {
    case 0:
      stopScroller();
      setAction(1,StartActionText);
      break;
    case 1:
      startScroller();
      setAction(0,StopActionText);
  }
}

function startScroller(){
  document.getElementById('tag').style.whiteSpace='nowrap'
  var p=document.createElement('p')
  p.id='testP'
  p.style.fontSize='25%' //mozilla向け修正 使用する前に4倍する
  x-=step
  if (document.getElementById('tag').className) p.className=document.getElementById

('tag').className
  p.appendChild(document.createTextNode(sText))
  document.body.appendChild(p)
  pw=p.offsetWidth
  document.body.removeChild(p)
  if (x<(pw*4)*-1){x=divW}
  document.getElementById('tag').style.left=x+'px'
  scroll=setTimeout('startScroller()',speed)
}

function initScroller(){
  if (document.getElementById &amp;&amp; document.createElement &amp;&amp; document.body.appendChild) {
    addControls();
    divW=document.getElementById('scroller').offsetWidth;
    x=divW;
    document.getElementById('tag').style.position='relative';
    document.getElementById('tag').style.left=divW+'px';
    var ss=document.getElementById('tag').childNodes;
    for (i=0;i<ss.length;i++) {sText+=ss[i].nodeValue+" "};
    scroll=setTimeout('startScroller()',speed);
  }
}

function addLoadEvent(func) {
  if (!document.getElementById | !document.getElementsByTagName) return
  var oldonload = window.onload
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload()
      func()
    }
  }
}

addLoadEvent(initScroller)

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. スクロールするコンテンツを一時停止するメカニズムが提供されていることを確認する。

  2. 一時停止するメカニズムを用いて、コンテンツのスクロールを一時停止する。

  3. スクロールが停止し、自動的に再起動しないことを確認する。

  4. 一時停止中のコンテンツを再起動できるメカニズムが提供されていることを確認する。

  5. 提供されている再起動のメカニズムを用いて、コンテンツのスクロールを再起動する。

  6. 停止していた位置からスクロールが再開されることを確認する。

期待される結果

  • 3. 及び 6. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR34: テキストサイズに応じて拡大縮小するように、サイズ及びポジションを定める

適用 (対象)

クライアントサイドスクリプティング

これは、次の達成基準に関連する達成方法である:

ユーザエージェント及び支援技術によるサポート

SCR34 に関するユーザエージェントサポートノートを参照のこと。

解説

この達成方法の目的は、文字サイズが拡大縮小されるのに従って、適切に拡大縮小する方法で要素のサイズ及びポジションを計算することである。

ここに要素のサイズとポジションを決める JavaScript の四つのプロパティがある:

  • offsetHeight (ピクセルでの要素の高さ)

  • offsetWidth (ピクセルでの要素の幅)

  • offsetLeft (ピクセルでの親要素 (offsetParent) の左からの距離)

  • offsetTop (ピクセルでの親要素 (offsetParent) の上からの距離)

offsetHeightoffsetWidth を用いて高さや幅を定めることは簡単である、しかし、オブジェクトの左とトップの位置を絶対配置の値として定める時、親要素を考える必要がある。下記において、calculatePosition 関数は、要素におけるすべての親ノードの最終的な値が決定するまで繰り返されている。その関数は objElement (当該の要素の名前) とオフセットプロパティ (offsetLeft 又は offsetTop ) の二つの引数を取っている。

事例

事例 1

Javascript の関数:

コード例:


function calculatePosition(objElement, strOffset)
{
    var iOffset = 0;

    if (objElement.offsetParent)
    {
        do 
        {
            iOffset += objElement[strOffset];
            objElement = objElement.offsetParent;
        } while (objElement);
    }

    return iOffset;
}

次の事例は、上の関数がオブジェクトを、参照オブジェクトの下、かつ、左から同じ距離に配置するために用いられていることを示している:

コード例:


// Get a reference object
var objReference = document.getElementById('refobject');
// Get the object to be aligned
var objAlign = document.getElementById('lineup');

objAlign.style.position = 'absolute';
objAlign.style.left = calculatePosition(objReference, 'offsetLeft') + 'px';
objAlign.style.top = calculatePosition(objReference, 'offsetTop') + objReference.offsetHeight + 'px';

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

訳注: 「MSDN: Fix the Box Instead of Thinking Outside It」はリソースがリダイレクトされているが適切に処理されていない。代わりに、MDN の HTMLElement.offsetHeightHTMLElement.offsetWidthHTMLElement.offsetLeftHTMLElement.offsetTop をそれぞれ参照できる。

検証

手順

  1. テキストサイズの変更とともにテキストコンテナのサイズを調整するように設計されているページを開く。

  2. ブラウザのテキストサイズ調節を使って 200% のサイズまで大きくする。(ズーム機能は使用しない)

  3. テキストコンテナのサイズがテキストサイズに合わせて調整されることを確認する。

  4. テキストサイズを大きくした結果、どのテキストも「切り取られ」たり、見えなくなっていたりしないことを確認する。

期待される結果

  • 3.及び 4.の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR35: アンカー及びボタンの onclick イベントを用いて、アクションをキーボード操作可能にする

適用 (対象)

HTML 又は XHTML で使用されるスクリプト。

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、キーボードでアクセス可能なコントロールに加えることで、キーボードでアクセス可能になるスクリプトの関数を呼び出す方法について説明することである。スクリプトによる動きが確実にキーボードから呼び出されるように、それらの動きは「ネイティブに実行可能な」HTML 要素 (リンク及びボタン) に関連付けられている。これらの要素の onclick イベントは機器に依存していない。「onclick」という表現はマウスに関連付けられているようにも思えるが、onclick イベントは実際のところ、リンク又はボタンのデフォルトの動きにマッピングされている。デフォルトの動きは、利用者がマウスで要素をクリックしたときに発生するが、要素にフォーカスして Enter キーやスペースキーを押したとき及び、他のアクセシビリティ API によってトリガーされたときにも発生する。

この達成方法はクライアントサイドスクリプトに依存しているが、スクリプトが利用できない環境に対する、代替としての実装又は説明として意味がある。アンカー要素を使って JavaScript によるアクションを呼び出すとき、代替としての実装又は説明は href 属性によって提供される。ボタンを使用するときは、フォームの送信によって提供される。

事例

事例 1

スクリプトを実行するリンクで、スクリプトをサポートしていないブラウザに対して代替手段を持たないもの。この方法は、スクリプトがアクセシビリティ サポーテッドな技術に依存しているときのみに使用されるべきである。

このリンクからナビゲートしたくないのではあるが、これを実際のリンクにし、適切なイベントを得るために、a 要素上の href 属性を使わなければならない。この事例では、我々は「#」をリンクターゲットとして使用しているが、何を使用しても良い。このリンクからナビゲートされることはない。

doStuff() イベントハンドリング関数の最後にある「return false;」は、ブラウザにその URI へ移動しないよう指示している。それがなければ、ページはスクリプト実行後に再読み込みされることになる。

コード例:


<script> 
function doStuff()
 {
  //do stuff
    return false;
  }
</script>
<a href="#" onclick="return doStuff();">do stuff</a> 

事例 2

スクリプトを実行するリンクであるが、スクリプトが実行可能でなければ他のページに移動させるもの。この方法はスクリプトに依存しないサイトで、移動先がスクリプトと同じ機能を提供している場合にのみ使用される。この例は、href が実在するページである dostuff.htm に設定されていること以外は、事例 1と同じである。dostuff.htmでは、スクリプトと同じ機能を提供しなければならない。doStuff() イベントハンドリング関数の最後にある「return false;」が、ブラウザにその URI へ移動しないように指示している。そうでなければ、ブラウザはスクリプト実行後に dostuff.htm に移動してしまう。

コード例:


<script> 
function doStuff() 
 {  
  //do stuff  
  return false; 
 }
</script>
<a href="dostuff.htm" onclick="return doStuff();">do stuff</a> 

このコードの実装サンプル: JavaScriptを用いてアクションリンクを作成

事例 3

スクリプトを実行して、かつスクリプトを使わない利用者のためにフォーム送信を代替とするボタン。このアプローチは、スクリプトに依存しないサイトで、フォームの送信がスクリプトと同じ機能を提供できる場合にのみ使用できる。onsubmit="return false;" はフォームから送信されるのを防ぐ。

コード例:


<script>
  function doStuff()
 {
     //do stuff
 }
</script>
<form action="doStuff.aspx" onsubmit="return false;">
 <input type="submit" value="Do Stuff" onclick="doStuff();" />
</form> 

このコードの実装サンプル: JavaScript を用いてアクションボタンを作成

事例 4

スクリプトを実行するボタンで、input type="image" を用いて実装されているもの。input には、画像と等価のテキストを提供するために、タイトル属性を追加しなければならないことに注意する。この方法は、スクリプトに依存しているときのみに利用すべきである。

コード例:


<script>
  function doStuff()
  {
     //do stuff
   return false;
  }
</script>
<input type="image" src="stuff.gif" title="Do stuff" onclick="return doStuff();" /> 

事例 5

スクリプトを実行するボタンで、input type="submit"input type="reset" 又は input type="button" のいずれかを用いて実装されているもの。この方法は、スクリプトに依存しているときのみに利用すべきである。

コード例:


<input type="submit" onclick="return doStuff();" value="Do Stuff" />

事例 6

スクリプトを実行するボタンで、button/button を用いて実装されているもの。これは、ボタンの見た目をより詳細に調整したいときに有効である。この特定の例では、ボタンはアイコンとテキストの両方を含んでいる。この方法は、スクリプトに依存しているときのみに利用すべきである。

コード例:


<button onclick="return doStuff();">
 <img src="stuff.gif" alt="stuff icon">
 Do Stuff
</button>

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

訳注 1: HTML 4.01 は Superseded Recommendation としてマークされ、廃止された仕様である。上記はそれぞれ、HTML 5.2§4.12. ScriptingHTML 5.2§4.10. FormsHTML 5.2§4.8. Linksを代わりに参照できる。

訳注 2: DOM 仕様は現在、WHATWG で策定されている。DOM Standard も参照のこと。

検証

手順

abutton、又は input 要素と関連付けられたすべてのスクリプトのアクションについて:

  1. スクリプトをサポートするユーザエージェントで:

    • マウスを用い、コントロールをクリックする。

    • スクリプトのアクションが適切に実行されることを確認する。

    • コントロールがアンカー要素である場合、アンカー要素の href 属性の URI が呼び出されないことを確認する。

    • キーボードでコントロールに移動して、フォーカスを与えることが可能であることを確認する。

    • キーボードのフォーカスをコントロールに設定する。

    • Enter キーを押すことで、スクリプトのアクションを呼び出すことを確認する。

    • コントロールがアンカー要素である場合、アンカー要素の href 属性の URI が呼び出されないことを確認する。

  2. スクリプトをサポートしていないユーザエージェントで:

    • マウスでコントロールをクリックする。

    • コントロールがアンカー要素である場合、アンカー要素の href 属性の URI が呼び出されることを確認する。

    • キーボードでコントロールに移動して、フォーカスを与えることが可能であることを確認する。

    • キーボードのフォーカスをコントロールに設定する。

    • コントロールがアンカー要素である場合、Enter キーを押すことでアンカー要素の href 属性の URI が呼び出されることを確認する。

期待される結果

  • 上記の手順全ての結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR36: 静的なウィンドウ又は領域にある、動きのあるテキスト、スクロールするテキスト、又は自動更新されるテキストを利用者が表示できるメカニズムを提供する

適用 (対象)

動く、点滅する、又はテキストを更新し、静的なテキストブロックを生成する全てのウェブコンテンツ技術

これは、次の達成基準に関連する達成方法である:

解説

スペースが限られているために、スクロールするテキストを表示するウェブページがある。小さなテキストウィンドウの中でテキストをスクロールさせることにより、その速度にあわせて読むことができる利用者にはコンテンツが利用可能となるが、それよりも速度が読むのが遅い利用者や、支援技術の利用者にとっては問題となる。この達成方法では、動きを止めて、テキストブロック全体を静的に利用可能にするメカニズムを提供する。テキストは別ウィンドウかページ中の (より大きな) セクションで利用可能になるだろう。そうすることで、利用者はテキストを自分の速度で読むことができる。

この達成方法は、動いているテキストが全て同時に画面に表示できない場合 (例: 長いチャットでの会話) には適用されない。

注記: この達成方法は、不適合のコンテンツのための適合している代替版のページを表示するためのスタイルスイッチの達成方法とあわせて利用できる。詳細については、C29: 適合している代替版を提供するために、スタイルスイッチャーを使用する (CSS) 及び適合している代替版を理解するを参照のこと。

事例

事例 1: スクロールするテキストを展開する

大きなテキストブロックがページ中の小さなマーキーの範囲をスクロールする。ボタンにより、利用者はスクロールを止め、テキストブロック全体を表示することができる。

注記: このコード例では CSS と JavaScript の両方が利用可能で有効になっている必要がある。

CSS 部分:

コード例:


#scrollContainer {
        visibility: visible;
        overflow: hidden;
        top: 50px; left: 10px;
        background-color: darkblue;
      }
      .scrolling {
        position: absolute;
        width: 200px;
        height: 50px;
      }
      .notscrolling {
        width: 500px;
        margin:10px;
      }
      #scrollingText {
        top: 0px;
        color: white;
      }
      .scrolling #scrollingText {
        position: absolute;
      }
      </a> 

スクリプト及び HTML コンテンツ:

コード例:

<script type="text/javascript">

      var tid;
      function init() {
        var st = document.getElementById('scrollingText');
        st.style.top = '0px';
        initScrolling();
      }
      function initScrolling () {
        tid = setInterval('scrollText()', 300);
      }
      function scrollText () {
        var st = document.getElementById('scrollingText');
        if (parseInt(st.style.top) > (st.offsetHeight*(-1) + 8)) {
          st.style.top = (parseInt(st.style.top) - 5) + 'px';
        } else {
          var sc = document.getElementById('scrollContainer');
          st.style.top = parseInt(sc.offsetHeight) + 8 + 'px';
        }
      }
      function toggle() {
        var scr = document.getElementById('scrollContainer');
        if (scr.className == 'scrolling') {
          scr.className = 'notscrolling';
          clearInterval(tid);
           document.getElementById('scrollButton').value="Shrink";
        } else {
          scr.className = 'scrolling';
          initScrolling();
          document.getElementById('scrollButton').value="Expand";
        }
      }
  <input type="button" id="scrollButton" value="Expand" onclick="toggle()" />
  <div id="scrollContainer" class="scrolling">
    <div id="scrollingText" class="on">
    .... Text to be scrolled ...
    </div>
  </div>
...

このコードの実装サンプル: スクロールするテキストを展開

検証

この達成方法に利用可能な検証はない。


SCR37: デバイス非依存な方法でカスタムダイアログを作成する

適用 (対象)

スクリプトで使用される HTML 及び XHTML

これは、次の達成基準に関連する達成方法である:

解説

コンテンツ制作者はしばしば、ブラウザによって提供されるポップアップウインドウを使わずに、独自のダイアログを作成したがる。これは通常、ダイアログのコンテンツを div の中に収めて、その div をコンテンツの上に CSS による重なり順及び絶対配置を用いて配置するというやり方でおこなわれる。

これらのダイアログをアクセシブルにするには、いくつかの簡単なルールに従う必要がある。

  1. リンクやボタンの onclick イベントからダイアログを起動するスクリプトをトリガーにする。

  2. ダイアログの div を Document Object Model (DOM) の中、トリガーした要素の直後に配置する。トリガーした要素がフォーカスを保持し、ダイアログのコンテンツをその要素のあとに挿入することで、ダイアログの中のコンテンツがスクリーンリーダーの読み上げ順序で次になり、タブ順序も次になる。それでも、ダイアログは視覚的にページ上のあらゆる場所に絶対配置できる。これは、下の例のようにダイアログを HTML の中で作成し、CSS で非表示にする方法又は、トリガーした要素の直後にスクリプトで挿入する方法のどちらでも実装できる。

  3. ダイアログの div 内部の HTML が、その他のコンテンツと同じアクセシビリティガイドラインの要件を満たしていることを保証する。

リンクがダイアログを開閉できたり、キーボードのフォーカスが外れるとダイアログが閉じるようにしたりすることはすばらしいが、必ずしも必要なわけではない。

訳注: WAIC では SCR37 に関するアクセシビリティ・サポーテッド(AS)情報を提供している。

2014 年 6 月版のアクセシビリティ・サポーテッド(AS)情報: SCR37 では、「要注意」と評価されている。WAIC はウェブ制作者にこの達成方法が一部の環境では動作しないことに注意を促すものである。

事例

事例 1: ダイアログを開くオプションボタン

この例の HTML には、トリガーとなる要素、この場合はボタンとダイアログのフレームとして機能する div がある。

トリガーとなる要素はボタンで、スクリプトは onclick イベントのトリガーである。これは適切なイベントをオペレーティングシステムに送るので、支援技術は DOM の中の変化に気がつくことができる。

この例では、ダイアログ内の送信及びリセットボタンは単純に div に隠れている。

コード例:

...
<button onclick="TogglePopup(event,true)"
	name="pop0001">Options</button>
<div class="popover" id="pop0001">
  <h3>Edit Sort Information</h3>
  <form action="default.htm" onsubmit="this.parentNode.style.display='none'; return false;" onreset="this.parentNode.style.display='none'; return false;">
    <fieldset>
      <legend>Sort Order</legend> 
      <input type="radio" name="order" id="order_alpha" /><label for="order_alpha">Alphabetical</label>
      <input type="radio" name="order" id="order_default" checked="true" /><label for="order_default">Default</label>
    </fieldset>
<div class="buttons">
  <input type="submit" value="OK" />
  <input type="reset" value="Cancel" />
</div>
</form>
</div>
...

div、見出し、及び form 要素は CSS でダイアログに見えるようにスタイル付けされている。

コード例:

...
a { color:blue; }
a.clickPopup img { border:none; width:0; }

div.popover { position:absolute; display:none; border:1px outset; background-color:beige; font-size:80%; background-color:#eeeeee; color:black; }
div.popover h3 { margin:0; padding:0.1em 0.5em; background-color:navy; color:white; }
#pop0001 { width:20em; }
#pop0001 form { margin:0; padding:0.5em; }
#pop0001 fieldset { margin-bottom:0.3em; padding-bottom:0.5em; }
#pop0001 input, #pop0001 label { vertical-align:middle; }
#pop0001 div.buttons { text-align:right; }
#pop0001 div.buttons input { width:6em; }
...

スクリプトはポップアップする div の表示を切り替え、表示させたり隠したりする。

コード例:

...
function TogglePopup(evt,show)
{
	HarmonizeEvent(evt);
	var src = evt.target;
	if ("click" == evt.type)
	{
		evt.returnValue = false;
	}
	var popID = src.getAttribute("name");
	if (popID)
	{
		var popup = document.getElementById(popID);
		if (popup)
		{
			if (true == show)
			{
				popup.style.display = "block";
			}
			else if (false == show)
			{
				popup.style.display = "none";
			}
			else
			{
				popup.style.display = "block" == popup.style.display ? "none" : "block";
			}
			if ("block" == popup.style.display)
			{
				//window.alert(document.documentElement.scrollHeight);
				popup.style.top = ((document.documentElement.offsetHeight - popup.offsetHeight) / 2 ) + 'px';
				popup.style.left = ((document.documentElement.offsetWidth - popup.offsetWidth) / 2) + 'px';
			}
		}
	}
}

function SubmitForm(elem)
{ 
	elem.parentNode.style.display='none'; 
	return false;
}

function ResetForm(elem)
{ 
	elem.parentNode.style.display='none'; 
	return false;
}
...

このコードの実装サンプル: ダイアログを開くオプションボタン

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. ポップアップウインドウでないダイアログのトリガーとなるものページ内の全ての場所を探す。

  2. Tab キーでその場所に移動して Enter キーを押下することで、ダイアログを開くことができることを確認する。

  3. 一度開いたら、タブ順序でダイアログが次の位置にあることを確認する。

  4. ダイアログがボタン又はリンクのクリックイベントからトリガーされていることを確認する。

  5. スクリプトによって生成された DOM を検証できるツールを用いて、DOM 内でダイアログが次にあることを確認する。

期待される結果

  • 2.、3.、4. 及び 5. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。


SCR38: プログレッシブエンハンスメントで設計されたウェブページに対して、適合している代替版を作成する

適用 (対象)

HTML with scripting.

これは、次の達成基準に関連する達成方法である:

解説

この達成方法の目的は、プログレッシブエンハンスメントで設計されたウェブページに適合する代替バージョンを提供することである。この達成方法は、スクリプトを用いて達成する方法を次のように示している:

  1. ウェブページの初期拡張バージョンを格納することで、後に拡張されたコンテンツのバージョンに対して「適合した代替バージョン」として機能できるようにし、かつ

  2. すべての拡張されたバージョンのウェブページに対して、利用者がコンテンツを格納された初期拡張の代替バージョンに戻すことができる機能を実装する。

プログレッシブエンハンスメントで設計されたウェブページはサポートされたウェブ技術を HTML 基盤のレイヤーに適用できるようにするため、ウェブ対応機器 (サイズ、機能及びソフトウェア) の特徴を検出する。より高度なアクセス機器のさまざまな機能に合わせて拡張バージョンのページが作成される一方で、そのようなウェブページの基本的なコンテンツと機能は、よりシンプルなウェブ対応機器を使用している人なら誰でも HTML 基盤を通じて利用することができる。

現在の代替バージョンのウェブページの要件は次のようになっている: 「注記 4: 様々な技術環境又は利用者層に対応するために、複数の代替バージョンを提供してもよい。この場合、各バージョンは可能なかぎり適合したものでなければならず、適合要件 1 を満たすためには、そのうちの一つのバージョンが完全に適合したものでなければならない。」プログレッシブエンハンスメントで設計されたウェブページは、どのバージョンを完全に適合したものとして選ぶかという問題を残しているが、どんな利用者においても不利な状況におかれないようにする。

この課題の解決策の一つは、広範囲のウェブ対応機器がコンテンツにアクセス可能なため、拡張前のウェブページ (例: スクリプト、スタイル、HTML ではないプラグインが無効時に作成される HTML のソースコードの DOM の状態) を「完全に適合したバージョン」として選択することである。

注記: この達成方法はすべてのスクリプト、スタイル、プラグインを除外するが、これは WCAG 2.0 に適合するために必須ではないことを示す必要がある。制作者は類似した技術を使用することができるが、還元されたスタイルとスクリプトを「拡張前」のバージョンで保つことができる。

この技術は一つのバージョンで適合表明を行う方法を提供するが、制作者は各拡張版のウェブページが可能な限り適合するために作業し続けるべきである。

事例

事例 1: JavaScript を使用する

この事例は「accToggle.js」ファイル内で JavaScript を使用し、HTML ソースコードのみで作成された拡張前のウェブページを格納することで、後に拡張されたウェブページの「適合した代替バージョン」として機能させることができる。そして、利用者がウェブページを最初の拡張前の「適合した代替バージョン」に戻せるよう、すべての拡張されたウェブページに切り替えリンクを設置する。注記: 「sayhello.js」ファイルは単なる外部のペイロードファイルの例であり、必要な他の外部スクリプトに置き換えられる。

accToggle.js ファイル内のスクリプトは拡張前のバージョンを格納し、このバージョンの URL に #accessible という接尾辞を付与する。「WCAG 2.0 適合する代替版」という (すべての拡張されたバージョンのページにおいて、body 要素の最初の子要素として設置される) リンクをクリックすることにより、接尾辞に「#accessible」とついた URL に変化し、body 要素と head 要素内の HTML を拡張前のコードに初期化する。拡張前の状態はリンクから、又は URL をブラウザに直接入力することでアクセスできる。さらに、拡張前の「適合する代替版」にリンクが追加され、利用者がウェブページを拡張版にすることができる (これはブラウザの戻るボタンからでも可能)。

acctoggle.js ソースコード:


window.onload = function(event) {

    // 拡張前のコンテンツを保管する
    var initialHead = document.head.innerHTML;
    var initialBody = document.body.innerHTML;
    var initialURL = location.href;
    
    var runOnce = function() {
         // ページ読み込み毎に実行したいペイロード 例: Google Analytics コード
    }
    
    var setup = function() {
         // 適合している代替版のリンクを作成する

        var toggleEnhanced = document.querySelector("#toggle_enhanced");
        if (toggleEnhanced) {
            toggleEnhanced.outerHTML = "";
        }
        
        var nel = document.createElement("a");
        nel.id = "acctoggle";
        nel.setAttribute("href", "#accessible");
        nel.innerHTML = "WCAG 2.0 conforming alternate version";
        document.body.insertBefore(nel, document.body.firstChild);
        
         // ペイロード
        var s = document.createElement("SCRIPT");
        s.setAttribute("src", "sayhello.js");
        document.querySelector("HEAD").appendChild(s);   
       }
    
    setup();
    runOnce();
    
    window.onpopstate = function(event) {
        if (location.href.indexOf("#accessible") != -1) {
             // コンテンツを拡張前のバージョンに戻す
            document.head.innerHTML = initialHead;
            document.body.innerHTML = initialBody;
            
            // create enhanced version link
            var el = document.createElement("a");
            el.id = "toggle_enhanced";
            el.setAttribute("href", "");
            el.innerHTML = "Enhanced version";
            var back = function(e) {
                 e.preventDefault();
                 window.history.back();
            }
            el.addEventListener("click", back, false);
            document.body.insertBefore(el, document.body.firstChild);
        }
        if (location.href == initialURL) {
            setup();
        }
    };
}
		 

HTML ウェブページソースコード:

<!DOCTYPE html>
  <html lang="en">
    <head>
        <title>Evaluera Ltd</title>
        <meta charset="UTF-8" />
        <script src="accSwitch.js"></script>
    </head>
    <body> 
        <h1>Test Page</h1>
        <p>Say: <span id="change">Goodbye</span></p>
    </body>
</html>			
		 

sayhello.js ソースコード


var change = document.querySelector("#change");
change.innerText = "Hello";		
		 

事例 2: EnhanceJS を使用する―プログレッシブエンハンスメントのアプリケーションを改善するために設計された Javascript フレームワーク

EnhanceJS は「高度なスタイルとスクリプトをページに適用する前に、JavaScript の主要な機能と CSS のサポートを最初にテストすることで、プログレッシブエンハンスメントのアプリケーションを改善するように設計された」オープンソースの JavaScript フレームワークである。さらに、デフォルトの EnhanceJS スクリプトは、利用者が拡張前のウェブページの状態に戻すことがでるよう、すべての拡張版のページに自動的に切り替えリンクを作成する。(EnhanceJS でデフォルトで設定されるこれを「低帯域幅版」と呼ぶ)。EnhanceJS ではこの設定は拡張前の状態が「低帯域幅版」ではなく、「WCAG 2.0 の適合している代替版」として認識されるよう変更されている。

HTML コンポーネント:

<!DOCTYPE html>
<html lang="en">
    <head>
    <script type="text/javascript" src="enhance.js"></script>
    <script type="text/javascript">
        // Run capabilities test
        enhance({
            loadStyles: [
                "example.css"
            ], 
            loadScripts: [
                "example.js"
            ],
            // text shown in enhanced mode
            forceFailText: "WCAG 2.0 conforming alternate version",
            // text shown in accessible mode
            forcePassText: "Enhanced version"
        });
    </script>
    </head>
    ....

参考リソース

この参考リソースは、あくまでも情報提供のみが目的であり、推薦などを意味するものではない。

検証

手順

  1. 拡張されたウェブページが「適合している代替版」へのリンクを含んでいる。

  2. 代替版が、オリジナルページの適合している代替版であり、かつ要求された適合レベルで WCAG 2.0 に適合していることを確認する。

期待される結果

  • 1. 及び 2. の結果が真である。

この達成方法が「十分な達成方法」の一つである場合、この手順や期待される結果を満たしていなければ、それはこの達成方法が正しく用いられていないことを意味するが、必ずしも達成基準を満たしていないことにはならない。場合によっては、別の達成方法によってその達成基準が満たされていることもありうる。