Skip to content

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

このテクニックについて

このテクニックは 2.4.3: フォーカス順序 (ウェブページを動的に変更するために用いる場合、十分なテクニック) に関連する。

このテクニックは、HTML 及びスクリプトに適用される。

解説

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

メニューはリンクリストで、コンテンツを再配置するスクリプトのトリガーとなる、機器に依存しない 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 {
  list-item-style:none;
  margin:0px;
  padding:0px;
}

ul#swapper li {
  border:1px solid black;
  height:5em;
  list-style:none;
  margin:1em;
  padding:0;
  width:15em;
}

ul#swapper li a {
  color:white;
  font-size:90%;
  text-decoration:none;
}
    
ul#swapper li div.module_header {
  padding:0 0.2em;
  text-align:right;
}

ul#swapper li div.module_body {
  padding:0.2em;
}
    
ul#swapper ul.menu {
  background-color:#eeeeee; 
  border:1px solid gray;
  display:none;
  height:auto;
  list-style:none;
  margin:0;
  padding:0;
  position:absolute;
  text-align:left;
}

ul#swapper ul.menu li {
  border:none;
  font-weight:normal;
  height:auto;
  margin:0;
  text-align:left;
  width:5em;
}

ul#swapper ul.menu li a {
  color:black;
  display:block;
  padding:0 0.1em;
  text-decoration:none;
  width:100%;
}

検証

手順

  1. ドラッグ&ドロップで再配置可能なウェブユニット内のすべてのコンポーネントを探す。
  2. リンクのリストで構成されたメニューを用いて、それらが再配置可能なメカニズムがあることをチェックする。
  3. メニューが DOM 内の再配置可能な項目の中に含まれていることをチェックする。
  4. 再配置のスクリプトはリンクの onclick イベントだけをトリガーにしていることをチェックする。
  5. 視覚的にだけではなく、項目が DOM の中でも再配置されていることをチェックする。

期待される結果

  • 2 ~ 5 が真である。
Back to Top