WAI-ARIAを加えたアコーディオンを例にステート(状態)を変更する【jQuery】

このエントリーはjQuery Advent Calendar 2013向けに書いたものです。

このエントリーでは、WAI-ARIAを加えたアコーディオンを例にしてステート(状態)を変更をjQueryで行うというものです。

WAI-ARIAについて

WAI-ARIAがどういったことなのかは、下記のエントリーに書いていますのでそちらを参照ください。

ステート(状態)を変更する

ステートというのは、現在のページにある何かのUIがどのような状態にあるかをブラウザに知らせるWAI-ARIAの仕組みです(例:パネルが開いているのか/閉じているのか、など)。今回使うステートのaria-*属性は以下の3つです。

aria-hidden
要素が表示であるか非表示であるかの状態を示します。表示されている場合の値は「false」、非表示の場合は「true」
aria-expanded
要素、もしくは要素のグループが展開されているか、折りたためられているかの状態を示します。展開されている場合の値は「true」、折りたためられている場合は「false」
aria-selected
現在選択された状態であることを示します。選択されている場合の値は「true」、選択されていない場合は「false」

アコーディオンのHTMLは仮に下記のようにとします。

<div id="accordion-block" role="tablist">
<h1 role="tab"
   id="accordion-tab01"
   aria-controls="accordion-panel01"
   aria-selected="false">
<a href="#">
セクション1
</a>
</h1>
<p
   role="tabpanel"
   id="accordion-panel01"
   aria-labelledby="accordion-tab01"
   aria-expanded="true"
   aria-hidden="false">
パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。
</p>

<h1 role="tab"
   id="accordion-tab02"
   aria-controls="accordion-panel02"
   aria-selected="false">
<a href="#">
セクション2
</a>
</h1>
<p
   role="tabpanel"
   id="accordion-panel02"
   aria-labelledby="accordion-tab02"
   aria-expanded="true"
   aria-hidden="false">
パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。
</p>

<h1 role="tab"
   id="accordion-tab03"
   aria-controls="accordion-panel03"
   aria-selected="false">
<a href="#">
セクション3
</a>
</h1>
<p
   role="tabpanel"
   id="accordion-panel03"
   aria-labelledby="accordion-tab03"
   aria-expanded="true"
   aria-hidden="false">
パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。パネルの中身です。
</p>

<!-- /#accordion-block --></div>

JSオフ時のことを考慮して、aria-selectedは「false」、aria-expandedは「true」、aria-hiddenは「false」にします。

ちなみに他のaria-*属性はプロパティです。アコーディオンのタブとパネルの関連付け等に使います。

aria-controls
制御されている要素の因果関係を定義します。(例:タブとタブパネル、ラジオボタンやチェックボックスによって表示が切り替わる等)
aria-labelledby
ラベル付けする要素の因果関係を定義します。

jQueryですること

アコーディオンの初期の状態として一番目のパネルだけ展開されて、他のパネルは展開されていないようにします。そのためjQueryでやることはだいたい以下のようになります。

  • 初期の状態にするために、アコーディオンのパネルを折り畳み、一番目のパネルを展開する
  • パネルのaria-expandedを「false」、aria-hiddenを「true」にする
  • 一番目のタブを選択状態にするために「aria-selected」を「true」にする
  • タブをクリックしたときに、パネルを折り畳む、クリックしたタブのパネルを展開する
  • クリックされたタブ以外の「aria-selected」を「false」にし、クリックされたタブの「aria-selected」を「true」にする
  • クリックされたタブ以外のパネルのaria-expandedを「false」、aria-hiddenを「true」にし、クリックされたタブのパネルのaria-expandedを「true」、aria-hiddenを「false」にする

デモ

このエントリーjQueryの内容はほんのわずかで(というかjQueryは全くもって関係がない内容になっているとか...)、主にWAI-ARIAについてなので、Web Accessibility Advent Calendar向けのほうが良かったのではないかと思ったり思わなかったり...。

ちなみに、 jQuery UIのAccordionがWAI-ARIAを実装していますので、jQuery UIを使うだけで、上記でやったことが適用されますので、気になる方は一度jQuery UIを使ってみてください。

ちなみにデモのjQueryは下記です。

$(function(){

var $accordion = $("#accordion-block");
var $tab       = $accordion.find('h1');
var $panel     = $accordion.find('p');

//最初のパネル以外を非表示
$panel.hide().eq(0).show();
$tab.eq(0).attr('aria-selected','true');
$panel.not(':first').attr({
				'aria-expanded' : 'false',
				'aria-hidden'   : 'true'
			});

//Accordionの実行
Accordion();

function Accordion() {

	//パネルの表示の処理
	var openPanel = function(e) {
		e.preventDefault();
		if($(this).attr('aria-selected') === 'false') {
			//全パネルを非表示
			$panel.slideUp(200);
			//ARIAのStateを非表示に切り替える処理の実行
			changeCloseARIAState();
			//クリックされたパネルを表示
			$(this).next().slideDown(200);
			//ARIAのStateを表示に切り替える処理の実行
			changeOpenARIAState($(this));
		}
	};

	//ARIAのStateを非表示に切り替える処理
	var changeCloseARIAState = function() {
		$tab.attr('aria-selected','false');
		$panel.attr({
				  'aria-expanded' : 'false',
				  'aria-hidden'   : 'true'
			});
	};

	//ARIAのStateを表示に切り替える処理
	var changeOpenARIAState = function(elem) {
		elem.attr('aria-selected', 'true')
			  .next().attr({
				  'aria-expanded' : 'true',
				  'aria-hidden'   : 'false'
			});
	}

	//パネルの表示の処理の実行
	$tab.on('click', openPanel);
}


});