カテゴリ一覧のアコーディオン表示(解説その3)

カテゴリ一覧のアコーディオン表示について、解説の最終回をお送りします。

1.2階層目のカテゴリだけ処理を分ける

今回取り上げている例では、トップレベルのカテゴリはh2要素でマークアップし、それ以下の階層のカテゴリはul/li要素でマークアップします。
また、トップレベル直下のul要素全体を、<div class="pane">~</div>のdiv要素で囲むようにします。

この処理を行うためには、トップレベル直下(=2階層目)だけ、処理を分けることが必要になります。
前回の解説で、カテゴリの階層の深さを変数depthに保存するようにしました。
したがって、「変数depthの値が2」という条件を判断すれば、2階層目のカテゴリだけ処理を分けることができます。

テンプレートにその処理を追加すると、以下のリストのようになります。
6~8行目のMTIfタグで、変数depthの値が2かどうかを判断し、2の時には<ul>タグの直前に<div class="pane">のタグを出力しています。
また、24~26行目のMTIfタグで、変数depthの値が2の時には、</ul>タグの直後に</div>タグを出力しています。

<mt:SetVar name="depth" value="0">
<mt:TopLevelCategories>
<mt:SubCatIsFirst>
  <mt:SetVar name="depth" op="++">
  <mt:HasParentCategory>
    <mt:If name="depth" eq="2">
    <div class="pane">
    </mt:If>
    <ul>
  </mt:HasParentCategory>
</mt:SubCatIsFirst>
<mt:HasParentCategory>
  <li><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
<mt:Else>
  <h2><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a></h2>
</mt:HasParentCategory>
<$mt:SubCatsRecurse$>
<mt:HasParentCategory>
  </li>
</mt:HasParentCategory>
<mt:SubCatIsLast>
  <mt:HasParentCategory>
    </ul>
    <mt:If name="depth" eq="2">
    </div>
    </mt:If>
  </mt:HasParentCategory>
  <mt:SetVar name="depth" op="--">
</mt:SubCatIsLast>
</mt:TopLevelCategories>

2.スタイルの設定

最後に、以下の規則に従って、いくつかの要素にスタイルを割り当てます。

  • 最初のトップレベルカテゴリを出力する際に、h2要素に「class="current"」のclass属性を割り当てます。
  • 最初のトップレベルカテゴリの直下のdiv要素を出力する際に、「style="display:block"」のstyle属性を割り当てます。
  • 上記以外のdiv要素を出力する際に、「style="display:none"」のstyle属性を割り当てます。

h2要素は、これまでに作ったテンプレートで、トップレベルカテゴリの時だけ出力するようにしています。
したがって、h2要素を出力する部分に、「トップレベルカテゴリの中で最初のカテゴリかどうか」を判断する処理を追加して(MTSubCatIsFirstタグ)、条件が成立しているときだけ、class="current"の属性を出力すれば良いです。

一方、「最初のトップレベルカテゴリの直下のdiv要素」は、「一番最初に出力するdiv要素」と等しいです。
そこで、以下のような方法で処理を組みます。

  • 「最初のdiv要素」ということを、変数にfirst_divで表すことにし、値を1に初期化しておきます。
  • div要素を出力し終えたら、変数first_divの値を0にします。
  • div要素を出力する際に、変数first_divの値が1なら、まだdiv要素を1つも出力していないことを意味しますので、「style="display:block"」のstyle属性を出力します。
  • div要素を出力する際に、変数first_divの値が0なら、div要素の出力が終わっていることを意味しますので、「style="display:none"」のstyle属性を出力します。

これらの処理を追加すると、アコーディオン表示するためのテンプレートが完成します(以下のリスト)。

<mt:SetVar name="depth" value="0">
<mt:SetVar name="first_div" value="1">
<mt:TopLevelCategories>
  <mt:SubCatIsFirst>
    <mt:SetVar name="depth" op="++">
    <mt:HasParentCategory>
      <mt:If name="depth" eq="2">
      <div class="pane" style="display:<mt:If name="first_div">block<mt:Else>none</mt:If>">
      <mt:SetVar name="first_div" value="0">
      </mt:If>
      <ul>
    </mt:HasParentCategory>
  </mt:SubCatIsFirst>
  <mt:HasParentCategory>
    <li><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
  <mt:Else>
    <h2<mt:SubCatIsFirst> class="current"</mt:SubCatIsFirst>><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a></h2>
  </mt:HasParentCategory>
  <$mt:SubCatsRecurse$>
  <mt:HasParentCategory>
    </li>
  </mt:HasParentCategory>
  <mt:SubCatIsLast>
    <mt:HasParentCategory>
      </ul>
      <mt:If name="depth" eq="2">
      </div>
      </mt:If>
    </mt:HasParentCategory>
    <mt:SetVar name="depth" op="--">
  </mt:SubCatIsLast>
</mt:TopLevelCategories>

17行目で、MTSubCatIsFirstタグを使って、最初のトップレベルカテゴリの時だけh2要素に「class="current"」のclass属性を割り当てています。
また、8行目で、MTIfタグを使って、変数first_divの値が1かどうかで、「style="display:block"」と「style="display:none"」の出力を切り分けています。

変数first_divの値を設定する処理は、2行目と9行目にあります。
2行目では、カテゴリ一覧を出力する前の時点で、変数first_divを1に初期化しています。
また、9行目では、div要素を出力した後に、変数first_divを0にしています。
したがって、最初のdiv要素を出力する時点ではfirst_divの値は1で、出力が終わったらそれ以後はずっと0のままになります。