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

達成方法に関する重要な情報

この達成方法 (参考) の使用法と、この達成方法が WCAG 2.1 達成基準 (規定) とどのように関係するのかに関する重要な情報については、WCAG 達成基準の達成方法を理解するを参照のこと。適用 (対象) のセクションは、その達成方法の範囲について説明しており、特定の技術に関する達成方法の存在は、その技術があらゆる状況で WCAG 2.1 を満たすコンテンツを作成するために使用できることを意味するものではない。

適用 (対象)

HTML および XHTML、スクリプト

これは達成基準 2.4.3: フォーカス順序に関する達成方法である。(書かれていない達成方法を満たす慣習的な達成方法)

解説

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

メニューはリンクリストで、コンテンツを再配置するスクリプトのトリガーとなる、機器に依存しない 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 && swap.nodeType != 1)
            {
                swap = swap.previousSibling;
            }
            break;
        }
        case 'down':
        {
            swap = module.nextSibling;
            while (swap && swap.nodeType != 1)
            {
                swap = swap.nextSibling;
            }
            break;
        }
    }
    if (swap && 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. の結果が真である。