カテゴリとフォルダを混合して並べ替えるカスタマイズ - グローバルナビゲーション

Movable Type でカテゴリを並べ替えるには、プラグインを利用したり、カテゴリ名の頭に数字をいれて、カテゴリ名を表示させるときにその数字を取っ払うなど、以下のようないくつかの方法があると思います。 プラグインを使う カテゴリーとフォルダを並べ替えるプラグイン(MT4以降用) - The blog of H.Fujimoto参照 カテゴリの「説明」欄やカスタムフィールドを利用して並べ替える ...

Movable Type でカテゴリを並べ替えるには、プラグインを利用したり、カテゴリ名の頭に数字をいれて、カテゴリ名を表示させるときにその数字を取っ払うなど、以下のようないくつかの方法があると思います。

プラグインを使う

カテゴリーとフォルダを並べ替えるプラグイン(MT4以降用) - The blog of H.Fujimoto参照

カテゴリの「説明」欄やカスタムフィールドを利用して並べ替える

Movable Type 4.2 パーフェクトガイド参照

カテゴリ名の頭に <0100> などをいれて並べ替え、remove_html モディファイアで取っ払う

MT でカテゴリーの並び替え | WWW WATCH参照

カテゴリ名の頭に (0100) などを入れて並べ替え、regex_replace モディファイアで取っ払う

MT でカテゴリーの並び替え | WWW WATCH参照

今回は、カテゴリ名の頭に数字を入れて並べ替え、regex_replace モディファイアで取っ払う方法をベースに、グローバルナビゲーションを作りました。

ポイントは、「カテゴリもフォルダも混合して並べ替えることができ、サブカテゴリやサブフォルダが何階層になっても大丈夫」なところです。

また、グローバルナビゲーションを「カテゴリ」と「フォルダ」にすることによって、「ブログ公開ディレクトリにあるウェブページ」はグローバルナビゲーションとは別にガイドナビとして使い分けられます。これにより、企業サイトでいえば「サイトマップ」や「プライバシーポリーシー」のような1ページものはグローバルナビゲーションとは別枠のメニューで自動生成することができるというのも便利です。

カテゴリとフォルダの並べ替え

カテゴリとフォルダの頭に「0100_」のように数字をつけて並べ替えます。

このように、頭に数字をつけるカテゴリの並べ替えの方法は、「<0100>」をつけて remove_html="1" で除去する方法もありますが、これだと管理画面側では数字が表示されないというデメリットがあります。

また、「説明」欄に数字を入れて、再構築する際に並べ替える方法もありますが、こちらは管理画面側では並び替えが反映されず、さらに数字も表示もされないデメリットがあります。

その点、頭に「0100_」をつける方法であれば、管理画面側でも並べ替えが反映され、さらに数字も表示され、さらに可読性も良いというメリットがあるのでお勧めです。

完成したソース

まずはじめに、完成したソースを置いておきます。テンプレートの仕組みを分かりやすくするために回りくどい記述があったり、そもそも他にもっといい方法があるかもしれませんが、こんな方法もあるんだということで参考になれば幸いです。でも、これでもかなり試行錯誤して練ってはいます。

<mt:IfArchiveType archive_type="Category">
 <mt:HasParentCategory>
 <mt:TopLevelParent>
 <mt:SetVarBlock name="currentCat"><$mt:CategoryLabel$></mt:SetVarBlock>
 </mt:TopLevelParent>
 </mt:HasParentCategory>
 <mt:HasNoParentCategory>
 <mt:SetVarBlock name="currentCat"><$mt:CategoryLabel$></mt:SetVarBlock>
 </mt:HasNoParentCategory>
</mt:IfArchiveType>
<mt:IfArchiveType archive_type="Individual">
 <mt:SetVarBlock name="currentCat"><mt:ParentCategories glue=","> <$mt:CategoryLabel$></mt:ParentCategories></mt:SetVarBlock>
 <mt:SetVarBlock name="currentCat"><$mt:GetVar name="currentCat" regex_replace="/,.*/",""$></mt:SetVarBlock>
</mt:IfArchiveType>
<mt:IfArchiveType archive_type="Page">
 <mt:SetVarBlock name="currentFld"><mt:ParentFolders glue=","> <$mt:FolderLabel$></mt:ParentFolders></mt:SetVarBlock>
 <mt:SetVarBlock name="currentFld"><$mt:GetVar name="currentFld" regex_replace="/,.*/",""$></mt:SetVarBlock>
</mt:IfArchiveType>


<mt:TopLevelCategories>
<mt:SetVarBlock name="listCat"><$mt:CategoryLabel$></mt:SetVarBlock>
<mt:SetVarBlock name="gNavKey"><$mt:CategoryLabel regex_replace="/_.+/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="gNav" key="$gNavKey"><li class="topLevel<mt:If name="currentCat" like="$listCat"> current</mt:If>"><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><$mt:CategoryLabel$></a><mt:HasSubCategories>@subcat@</mt:HasSubCategories></mt:SetVarBlock>
</mt:TopLevelCategories>

<mt:TopLevelFolders>
<mt:SetVarBlock name="listFld"><$mt:FolderLabel$></mt:SetVarBlock>
<mt:SetVarBlock name="gNavKey"><$mt:FolderLabel regex_replace="/_.+/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="gNav" key="$gNavKey"><li class="topLevel<mt:If name="currentFld" like="$listFld"> current</mt:If>"><a href="<$mt:BlogURL$><$mt:FolderPath$>/"<mt:If tag="FolderDescription"> title="<$mt:FolderDescription$>"</mt:If>><$mt:FolderLabel$></a><mt:HasSubFolders>@subfld@</mt:HasSubFolders></mt:SetVarBlock>
</mt:TopLevelFolders>

<div id="globalNav">
<ul id="nav">
<mt:If name="main_index">
<li class="home current"><a href="#page" title="このページの先頭へ戻る">ホーム</a></li>
<mt:Else>
<li class="home"><a href="<$mt:BlogURL$>" title="トップページへ戻る">ホーム</a></li>
</mt:If>

<mt:Loop name="gNav" sort_by="key">
<$mt:GetVar name="__value__" regex_replace="/([0-9]+_)|(@subcat@)|(@subfld@)/g",""$>
<mt:If name="__value__" like="@subcat@">

<mt:SetVarBlock name="catName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<\/a>@subcat@/",""$></mt:SetVarBlock>

<mt:SubCategories include_current="0" category="$catName">
<mt:SubCatIsFirst><ul></mt:SubCatIsFirst>
<li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><$mt:CategoryLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubCatsRecurse$></li>
<mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:SubCategories>

<mt:ElseIf name="__value__" like="@subfld@">
<mt:SetVarBlock name="fldName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<\/a>@subfld@/",""$></mt:SetVarBlock>

<mt:Folders show_empty="1">
<mt:SetVarBlock name="thisFld"><$mt:FolderLabel$></mt:SetVarBlock>
<mt:If name="thisFld" eq="$fldName">
<mt:SubFolders>
<mt:FolderHeader><ul></mt:FolderHeader>
<li><a href="<$mt:BlogURL$><$mt:FolderPath$>/"<mt:If tag="FolderDescription"> title="<$mt:FolderDescription$>"</mt:If>><$mt:FolderLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubFolderRecurse$></li>
<mt:FolderFooter></ul></mt:FolderFooter></mt:SubFolders>
</mt:If>
</mt:Folders>
</mt:If>
</li>
</mt:Loop>
<!-- / #nav --></ul>
<!-- / #globalNav --></div>

解説

では順を追って解説してみます。

現在表示されているページの最上位のカテゴリを記憶

まず最初のブロックで、現在表示されているページが属するトップレベルカテゴリまたはトップレベルフォルダを、それぞれ変数 currentCat 、currentFld に記憶させます。

これは、グローバルナビゲーション上で、現在表示されているページが属するカテゴリに特定のクラス名をつけて、CSS で表示を変えられるようにするためです。

gnav01.jpg

【表示されているページがカテゴリアーカイブの場合】

<mt:IfArchiveType archive_type="Category">
 【そのカテゴリに親カテゴリがある場合】
 <mt:HasParentCategory>
 <mt:TopLevelParent>【最上位の親カテゴリのカテゴリ名を currentCat に代入】
 <mt:SetVarBlock name="currentCat"><$mt:CategoryLabel$></mt:SetVarBlock>
 </mt:TopLevelParent>
 </mt:HasParentCategory>
 【そのカテゴリに親カテゴリがない場合】
 <mt:HasNoParentCategory>【そのカテゴリのカテゴリ名を currentCat に代入】
 <mt:SetVarBlock name="currentCat"><$mt:CategoryLabel$></mt:SetVarBlock>
 </mt:HasNoParentCategory>
</mt:IfArchiveType>

【表示されているページがブログ記事の場合】

<mt:IfArchiveType archive_type="Individual">
 【そのブログ記事が属するカテゴリをトップレベルから順に「 , 」で区切ってリストアップし、currentCat に代入】
 <mt:SetVarBlock name="currentCat"><mt:ParentCategories glue=","><$mt:CategoryLabel$></mt:ParentCategories></mt:SetVarBlock>
 【上で currentCat に代入された値の最初の「 , 」以下を削除してトップレベルのみにして、再度 currentCat に代入】
 <mt:SetVarBlock name="currentCat"><$mt:GetVar name="currentCat" regex_replace="/,.*/",""$></mt:SetVarBlock>
</mt:IfArchiveType>

【表示されているページがウェブページの場合】

<mt:IfArchiveType archive_type="Page">
 【そのブログ記事が属するフォルダをトップレベルから順に「 , 」で区切ってリストアップし、currentFld に代入】
 <mt:SetVarBlock name="currentFld"><mt:ParentFolders glue=","><$mt:FolderLabel$></mt:ParentFolders></mt:SetVarBlock>
 【上で currentFld に代入された値の最初の「 , 」以下を削除してトップレベルのみにして、再度 currentFld に代入】
 <mt:SetVarBlock name="currentFld"><$mt:GetVar name="currentFld" regex_replace="/,.*/",""$></mt:SetVarBlock>
</mt:IfArchiveType>

トップレベルカテゴリをリストアップ

<mt:TopLevelCategories>
 【リストアップされているカテゴリ名を listCat に代入】
 <mt:SetVarBlock name="listCat"><$mt:CategoryLabel$></mt:SetVarBlock>
 【カテゴリを並べ替えるための先頭の数字「0100_」などを gNavKey に代入】
 <mt:SetVarBlock name="gNavKey"><$mt:CategoryLabel regex_replace="/_.+/",""$></mt:SetVarBlock>
 【配列変数 gNav を作成。
  キー : 先ほど「0100_」などを記憶した gNavKey を代入
  値 : <li><a href="カテゴリアーカイブへのリンク" title="カテゴリの説明(説明欄に値があるものだけ)">カテゴリ名</a>
  ※ここで、「現在表示されているページが属するトップレベルカテゴリ」と「今リストアップされているトップレベルカテゴリ」が同じ場合は、li 要素に class="current" を付けます。(赤字部分)
  ※さらに、サブカテゴリを持っているトップレベルカテゴリに関しては、行末に「@subcat@」を付けます。(青字部分)
 <mt:SetVarBlock name="gNav" key="$gNavKey"><li<mt:If name="currentCat" like="$listCat"> class="current"</mt:If>><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><$mt:CategoryLabel$></a><mt:HasSubCategories>@subcat@</mt:HasSubCategories></mt:SetVarBlock>
</mt:TopLevelCategories>

トップレベルフォルダをリストアップ

トップレベルカテゴリをリストアップするときと同様にトップレベルフォルダをリストアップして配列変数 gNav に代入します。

<mt:TopLevelFolders>
 <mt:SetVarBlock name="listFld"><$mt:FolderLabel$></mt:SetVarBlock>
 <mt:SetVarBlock name="gNavKey"><$mt:FolderLabel regex_replace="/_.+/",""$></mt:SetVarBlock>
 <mt:SetVarBlock name="gNav" key="$gNavKey"><li<mt:If name="currentFld" like="$listFld"> class="current"</mt:If>><a href="<$mt:BlogURL$><$mt:FolderPath$>/"<mt:If tag="FolderDescription"> title="<$mt:FolderDescription$>"</mt:If>><$mt:FolderLabel$></a><mt:HasSubFolders>@subfld@</mt:HasSubFolders></mt:SetVarBlock>
</mt:TopLevelFolders>

トップレベルカテゴリとトップレベルフォルダを 1 つにまとめる

ここまででリストアップしたトップレベルカテゴリ(変数 gNav )とトップレベルフォルダ(変数 gNav )を、それぞれ mt:Loop タグを使って、まとめて gNav に代入し、配列変数を作成します。

このとき、gNav のキーには gNav と gNav のキー(「0100_」などの数字)を当てます。

<mt:Loop name="gNav" sort_by="key">
 <mt:SetVarBlock name="gNav" key="$__key__"><$mt:GetVar name="__value__"$></mt:SetVarBlock>
</mt:Loop>

<mt:Loop name="gNav" sort_by="key" regex_replace="/\n/g","">
 <mt:SetVarBlock name="gNav" key="$__key__"><$mt:GetVar name="__value__"$></mt:SetVarBlock>
</mt:Loop>

トップページへ戻る「HOME」の挿入

グローバルナビゲーションでトップページへ戻る「HOME」は欠かせないでしょうから、最初に記述します。

<mt:If name="main_index">
 <li class="home current"><a href="#page" title="このページの先頭へ戻る">ホーム</a></li>
<mt:Else>
 <li class="home"><a href="<$mt:BlogURL$>" title="トップページへ戻る">ホーム</a></li>
</mt:If>

グローバルナビゲーションの出力

さて、ここから mt:Loop タグを使って、配列変数 gNav の値を、キーを基準にソートして出力します。このとき、regex_replace モディファイアを使用して、頭の数字とアンダーバーと、トップレベルカテゴリなどをリストアップした時に追加した @subcat@、@subfld@ (サブカテゴリやサブフォルダがあるというマーク)を削除します。

<mt:Loop name="gNav" sort_by="key">
<$mt:GetVar name="__value__" regex_replace="/([0-9]+_)|(@subcat@)|(@subfld@)/g",""$>

続いて、Loop の中で、もし @subcat@ があったら、つまりサブカテゴリを持っていたら、そのサブカテゴリを表示します。

<mt:If name="__value__" like="@subcat@">
【次の3行で、余分なタグを削除してカテゴリ名だけを catName に代入する】
<mt:SetVarBlock name="catName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<\/a>@subcat@/",""$></mt:SetVarBlock>
【そのカテゴリ( catName の値)のサブカテゴリを階層分すべてリストアップする】
<mt:SubCategories include_current="0" category="$catName">
 <mt:SubCatIsFirst><ul></mt:SubCatIsFirst>
 <li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><$mt:CategoryLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubCatsRecurse$></li>
 <mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:SubCategories>

同様に、フォルダに関してもリストアップします。

<mt:ElseIf name="__value__" like="@subfld@">

<mt:SetVarBlock name="fldName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<\/a>@subfld@/",""$></mt:SetVarBlock>

<mt:Folders show_empty="1">
 <mt:SetVarBlock name="thisFld"><$mt:FolderLabel$></mt:SetVarBlock>
 <mt:If name="thisFld" eq="$fldName">
 <mt:SubFolders>
 <mt:FolderHeader><ul></mt:FolderHeader>
 <li><a href="<$mt:BlogURL$><$mt:FolderPath$>/"<mt:If tag="FolderDescription"> title="<$mt:FolderDescription$>"</mt:If>><$mt:FolderLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubFolderRecurse$></li>
 <mt:FolderFooter></ul></mt:FolderFooter></mt:SubFolders>
 </mt:If>
</mt:Folders>
</mt:If>

最後に、div や ul で囲って終了です。


<div id="globalNav">
<ul id="nav">
<mt:If name="main_index">
<li class="home current"><a href="#page" title="このページの先頭へ戻る">ホーム</a></li>
<mt:Else>
<li class="home"><a href="<$mt:BlogURL$>" title="トップページへ戻る">ホーム</a></li>
</mt:If>

<mt:Loop name="gNav" sort_by="key">
<$mt:GetVar name="__value__" regex_replace="/([0-9]+_)|(@subcat@)|(@subfld@)/g",""$>
<mt:If name="__value__" like="@subcat@">

<mt:SetVarBlock name="catName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="catName"><$mt:GetVar name="catName" regex_replace="/<\/a>@subcat@/",""$></mt:SetVarBlock>

<mt:SubCategories include_current="0" category="$catName">
<mt:SubCatIsFirst><ul></mt:SubCatIsFirst>
<li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:If>><$mt:CategoryLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubCatsRecurse$></li>
<mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:SubCategories>

<mt:ElseIf name="__value__" like="@subfld@">
<mt:SetVarBlock name="fldName"><$mt:GetVar name="__value__" regex_replace="/<li.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<a.+\">/",""$></mt:SetVarBlock>
<mt:SetVarBlock name="fldName"><$mt:GetVar name="fldName" regex_replace="/<\/a>@subfld@/",""$></mt:SetVarBlock>

<mt:Folders show_empty="1">
<mt:SetVarBlock name="thisFld"><$mt:FolderLabel$></mt:SetVarBlock>
<mt:If name="thisFld" eq="$fldName">
<mt:SubFolders>
<mt:FolderHeader><ul></mt:FolderHeader>
<li><a href="<$mt:BlogURL$><$mt:FolderPath$>/"<mt:If tag="FolderDescription"> title="<$mt:FolderDescription$>"</mt:If>><$mt:FolderLabel regex_replace="/[0-9]+_/",""$></a><$mt:SubFolderRecurse$></li>
<mt:FolderFooter></ul></mt:FolderFooter></mt:SubFolders>
</mt:If>
</mt:Folders>
</mt:If>
</li>
</mt:Loop>
<!-- / #nav --></ul>
<!-- / #globalNav --></div>

まとめ

このグローバルナビゲーション、すこしややこしいソースになってしまいましたが、配列や mt:Loop タグ、条件分岐、regex_replace をうまく使えれば、色々なことが可能になるというのを感じました。

ちなみに、このブログのグローバルナビゲーションは、jQuerydroppy - Nested drop down menusというプラグインを使用しています。

【2008-09-05 追記】
ウェブページに適用させたいときの archive_type モディファイアの値が「 webpage 」になっていたので、「 Page 」に修正しました。
【2008-08-20 追記】

ソースの無駄を少し省きました。トップレベルカテゴリ、トップレベルフォルダをリストアップするときに、直接 gNav に代入するようにしました。

最初は、分かりやすいために gNavCat などに一度代入していたのですが、無駄な Loop が増えるのでやめました。

Published 2008-08-16
Updated 2019-06-25