多階層型タブページ

もっと編集しやすい方法を模索中です

実装

使途不明ですが id 単位ではなく class 単位でタブ化すれば色々な用途が生まれるのではないかと思って作ってみました。
サンプルなのでそれほど多くはありませんが、仕組み上どこまでも階層化できます。
  • Tab1
  • Tab2
  • Tab3
Tab1
Tab2
  • Tab2-1
  • Tab2-2
  • Tab2-3
Tab2-1
  • Tab2-1-1
  • Tab2-1-2
Tab2-1-1
Tab2-1-2
Tab2-2
Tab2-3
  • Tab2-3-1
  • Tab2-3-2
Tab2-3-1
Tab2-3-2
  • Tab2-3-2-1
  • Tab2-3-2-2
Tab2-3-2-1
Tab2-3-2-2
Tab3
  • Tab3-1
  • Tab3-2
Tab3-1
Tab3-2

基本構造

<div>
<ul class="tab">
<li>Tab1</li>
<li>Tab2</li>
...
</ul>
<div>Tab1の内容</div>
<div>Tab2の内容</div>
...
</div>
 これが最小単位です。
 ul に tab クラスをつけるだけの簡単な仕組みです。

CSS

 デザイン関係で他にも色々追加していますが、タブ化で重要なのは次の2点になると思います。
.tab li{
display:inline;
}
 通常リストはブロック表示で縦に並んでしまうため、インライン表示にして横並びにしています。

■display:block

  • Tab1
  • Tab2

■display:inline

  • Tab1
  • Tab2

 次に選択中のタブを強調するためのスタイルです。
.tab .select{
background:#ccc;
}

JavaScript

 タブ化のためのスクリプトは以下のようになると思います。
 セレクターの仕組みを極めていないので甘いかもしれません。
$(function(){
$(".tab").each(function(){
$(this).nextAll(":not(:first)").hide();
$(this).children(":first").addClass("select");
});
$(".tab > li").click(function(){
var ul = $(this).parent();
var index = ul.children().index(this);
ul.children().removeClass("select");
ul.children(":eq(" + index + ")").addClass("select");
ul.nextAll().hide();
ul.nextAll(":eq(" + index + ")").show();
});
});
 少し長いので以下一行ずつ確認していきます。

スタート

<div>
<ul class="tab">
<li>Tab1</li>
<li>Tab2</li>
</ul>
<div>Tab1の内容</div>
<div>Tab2の内容</div>
</div>
 上記の結果は以下のようになります。(デザイン別途)
  • Tab1
  • Tab2
Tab1の内容
Tab2の内容

JavaScript

$(".tab").each(function(){
//タブの初期化
});
 セレクター + .each(function(){}); を使います。
 これで階層でも多数設置されても初期化できます。

必要ないタブを隠す

$(this).nextAll(":not(:first)").hide();
 1番目のタブ以外を隠します。
  • Tab1
  • Tab2
Tab1の内容
 上記の命令でTab2以降の内容が隠れてTab1だけが残ります。

1番目のタブボタンを選択状態にする

$(this).children(":first").addClass("select");
 タブボタンの1番目に選択状態を設定したクラスを追加して強調します。
Tab1の内容
 Tab1ボタンが強調表示されます。
 これで初期化は完了です。

クリック時にイベントを発生させる

$(".tab > li").click(function(){
//クリック時の処理
});
 以下で Tab2 をクリックしたと仮定して処理を進めてみます。

使いまわすので変数へ格納

var ul = $(this).parent();
var index = ul.children().index(this);

クリックした li のインデックスとその親である ul は複数回使用するので変数に格納しています。
今回は Tab2 をクリックしたので index に 1 が代入されます。

選択状態の解除

ul.children().removeClass("select");
 現在選択中のタブの選択状態を解除したいのですが、一度に選択できるタブは一つのみです。
 よって、すべての選択状態を解除するほうが早いです。
Tab1の内容

選択状態の設定

ul.children(":eq(" + index + ")").addClass("select");
 クリックした li にクラスを追加して選択状態にしています。
Tab1の内容

すべての内容を隠す

ul.nextAll().hide();
 先ほどの選択状態切り替えと同様、現在の表示状態は結果に影響を与えないので全て非表示状態にします。

内容表示

ul.nextAll(":eq(" + index + ")").show();
 クリックした li と同じ index を持つ div を表示します。
Tab2の内容

以上のような流れで Tab1 から Tab2 へ切り替わります。

その他

共通項目A
Tab1の内容
  • Tab2-1
  • Tab2-2
共通項目B
Tab2-1の内容
Tab2-2の内容
 タブの切り替えに関わらず表示させたい共通項目があるような場合は
<div class="info">共通項目</div>
 目印となるクラスを追加して、
...
$(this).nextAll(":not(.info, div:first)").hide();
...
ul.nextAll(":not(.info)").hide();
ul.nextAll(":not(.info):eq(" + index + ")").show();
...
 

目印部分を :not() で除外するようにしてあげればOKです。

ささいなこと

<!--Ex1-->
<li>TabA</li><li>TabB</li>
<!--Ex2-->
<li>TabA</li>
<li>TabB</li>

改行の有無でデザインが異なる場合があるようです。

<li>TabA</li><!--
--><li>TabB</li>

半角スペースが入らないように改行したい場合は、コメントを利用することを教えてもらいました。