Movable Typeのカテゴリリストで階層別に背景画像を変更する
Movable Typeのカテゴリリストで階層別に背景画像を変更する方法を紹介します。
1.カテゴリリストの完成サンプル
このカスタマイズでは次のようなカテゴリリストを出力します。

カテゴリリストのli要素のclass属性には、階層別に異なる値を設定します。class属性値にスタイルを適用すれば、階層別に異なる背景画像を適用できます。
また、サンプルでは第3階層の最後のli要素に「last」というclass属性値も付与しています。
<ul>
<li class="parent"><a href="http://user-domain/cat1/">親カテゴリ</a>
<ul>
<li class="child"><a href="http://user-domain/cat1/1/">子カテゴリ1</a>
<ul>
<li class="grandchild"><a href="http://user-domain/cat1/1/1/">孫カテゴリ1</a></li>
<li class="grandchild"><a href="http://user-domain/cat1/1/2/">孫カテゴリ2</a></li>
<li class="grandchild last"><a href="http://user-domain/cat1/1/3/">孫カテゴリ3</a></li>
</ul>
</li>
<li class="child"><a href="http://user-domain/cat1/2/">子カテゴリ2</a>
<ul>
<li class="grandchild"><a href="http://user-domain/cat1/2/1/">孫カテゴリ1</a></li>
<li class="grandchild"><a href="http://user-domain/cat1/2/2/">孫カテゴリ2</a></li>
<li class="grandchild last"><a href="http://user-domain/cat1/2/3/">孫カテゴリ3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
2.カスタマイズ
1項のカテゴリリストを出力するには、次のサブテンプレートを利用します。
<$mt:SetVar name="depth" value="1"$>
<mt:TopLevelCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<mt:if name="depth" eq="1">
<li class="parent"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
</mt:if>
<mt:if name="depth" eq="2">
<li class="child"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
</mt:if>
<mt:if name="depth" eq="3">
<mt:SubCatIsLast>
<li class="grandchild last"><a href="<$MTCategoryArchiveLink$>"><mt:CategoryLabel></a>
<mt:else>
<li class="grandchild"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
</mt:SubCatIsLast>
</mt:if>
<$mt:SetVar name="depth" op="++"$>
<$mt:SubCatsRecurse$>
<$mt:SetVar name="depth" op="--"$>
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:TopLevelCategories>
ポイントは青色で示した変数depthの制御で、これで階層の深さを判断しています。変数をインクリメントしているのはMTSubCatsRecurseの直前のMTSetVarタグ、デクリメントしているのがMTSubCatsRecurseの直後のMTSetVarタグです。
また、赤色で示したMTSubCatIsLastタグで、第3階層の「last」を付与を制御しています。
ちなみに、
<mt:SubCatIsLast>
<li class="grandchild last"><a href="<$MTCategoryArchiveLink$>"><mt:CategoryLabel></a>
<mt:else>
<li class="grandchild"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
</mt:SubCatIsLast>
の5行は、実際には次の1行に置き換えて書くこともできます。
<li class="grandchild<mt:SubCatIsLast> last</mt:SubCatIsLast>"><a href="<$MTCategoryArchiveLink$>"><mt:CategoryLabel></a>
第1階層・第2階層の判定処理の中に、第3階層の処理と同じようにMTSubCatIsLastタグを使えば、「parent」や「child」に「last」を付与することができます。
3.カスタマイズ(第1階層をh3要素にする)
第1階層のみをh3要素にするには、次のサブテンプレートを利用します。
<$mt:SetVar name="depth" value="1"$>
<mt:TopLevelCategories>
<mt:SubCatIsFirst>
<mt:if name="depth" ne="1">
<ul>
</mt:if>
</mt:SubCatIsFirst>
<mt:if name="depth" eq="1">
<h3><mt:CategoryLabel></h3>
</mt:if>
<mt:if name="depth" eq="2">
<li class="child"><MTCategoryLabel>
</mt:if>
<mt:if name="depth" eq="3">
<mt:SubCatIsLast>
<li class="grandchild last"><a href="<$MTCategoryArchiveLink$>"><mt:CategoryLabel></a>
<mt:else>
<li class="grandchild"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
</mt:SubCatIsLast>
</mt:if>
<$mt:SetVar name="depth" op="++"$>
<mt:SubCatsRecurse>
<$mt:SetVar name="depth" op="--"$>
<mt:if name="depth" ne="1">
</li>
</mt:if>
<mt:SubCatIsLast>
<mt:if name="depth" ne="1">
</ul>
</mt:if>
</mt:SubCatIsLast>
</mt:TopLevelCategories>
2項のサブテンプレートの違いは、赤色で示しました。違いは、第1階層の処理でh3要素を出力することと、ul要素を出力しないことです。
4.その他
このエントリーのカスタマイズでは変数を利用して階層を判断していますが、次のタグを利用しても実現可能です。
- MTHasParentCategory
- MTHasNoParentCategory
- MTHasSubCategories
- MTHasNoSubCategories
例えば、第2階層の判定にはMTHasParentCategoryタグとMTHasSubCategoriesタグ、第3階層の判定にはMTHasNoSubCategoriesタグを使用します。ただし、第2階層までしかないカテゴリがあると、第2階層がMTHasNoSubCategoriesタグの判定にひっかかってしまい、期待通りの出力にならない可能性があるので気をつけてください。
Movable Typeで製品情報のテーブルを作る
Movable Typeで、次のように製品別に各情報(ソフトウェア/FAQ/ダウンロード)の有無を、テーブル形式で表示する方法を紹介します。
| ソフトウェア | FAQ | ダウンロード | |
|---|---|---|---|
| 製品A | ○ | × | ○ |
| 製品B | ○ | ○ | × |
| 製品C | × | ○ | ○ |
このエントリーは、MTQのフォーラムで質問された回答の情報展開です。
1.ブログの構造
まず「製品」ブログがあり、そこに投稿されているブログ記事のタイトルは次のようになっています。
- 製品A
- 製品B
- 製品C
「製品」ブログと別に、「ソフトウェア」「FAQ」「ダウンロード」の各ブログがあり、そこに「製品」ブログと同じブログ記事タイトルのブログ記事を必要に応じて作成します。ここでは次のような状態になっていると仮定します。また各ブログ記事にはブログ名と同じカテゴリもひもづいています。
- 「ソフトウェア」ブログ
ブログ記事:製品A・製品B(カテゴリ:ソフトウェア) - 「FAQ」ブログ
ブログ記事:製品B・製品C(カテゴリ:FAQ) - 「ダウンロード」ブログ
ブログ記事:製品A・製品C(カテゴリ:ダウンロード)
上記の状態で、冒頭のような製品別に情報有無を示すテーブルを作成します。
| ソフトウェア | FAQ | ダウンロード | |
|---|---|---|---|
| 製品A | ○ | × | ○ |
| 製品B | ○ | ○ | × |
| 製品C | × | ○ | ○ |
2.テンプレート
テーブルを作成するためのテンプレートは次のようになります。
<mt:SetHashVar name="list">
<$mt:SetVar name="1" value="ソフトウェア"$>
<$mt:SetVar name="2" value="カタログ"$>
<$mt:SetVar name="3" value="FAQ"$>
</mt:SetHashVar>
<mt:SetVarTemplate name="foo">
<$mt:SetVar name="pname_cat" value="0"$>
<mt:TopLevelCategories category="$category">
<$mt:CategoryLabel setvar="catname"$>
<mt:If name="catname" eq="$pname">
<$mt:SetVar name="pname_cat" value="1"$>
<mt:If tag="CategoryCount">
<td>○</td>
<mt:Else>
<td>×</td>
</mt:If>
</mt:If>
<$mt:SubCatsRecurse$>
</mt:TopLevelCategories>
<mt:Unless name="pname_cat">
<td>×</td>
</mt:Unless>
</mt:SetVarTemplate>
<table>
<thead>
<tr>
<th></th>
<mt:Loop name="list">
<th><$mt:GetVar name="__value__"$></th>
</mt:Loop>
</tr>
</thead>
<tbody>
<mt:Entries>
<$mt:EntryTitle setvar="pname"$>
<tr><td><$mt:GetVar name="pname"$></td>
<mt:Loop name="list">
<$mt:GetVar name="__key__" setvar="blog_id"$>
<$mt:GetVar name="__value__" setvar="category"$>
<mt:Blogs include_blogs="$blog_id">
<$mt:GetVar name="foo"$>
</mt:Blogs>
</mt:Loop>
</tr>
</mt:Entries>
</tbody>
</table>
3.テンプレートの解説
まず、最初のMTSetHashVarタグでブログIDとブログ名のハッシュを用意します。
<mt:SetHashVar name="list">
<$mt:SetVar name="1" value="ソフトウェア"$>
<$mt:SetVar name="2" value="カタログ"$>
<$mt:SetVar name="3" value="FAQ"$>
</mt:SetHashVar>
サンプルテンプレートでは、MTSetHashVarタグの次にMTSetVarTemplateタグがありますが、この説明は後回しにして、最後のtable要素出力用のサブテンプレートについて説明します。
<table>
<thead>
<tr>
<th></th>
<mt:Loop name="list">
<th><$mt:GetVar name="__value__"$></th>
</mt:Loop>
</tr>
</thead>
<tbody>
<mt:Entries>
<$mt:EntryTitle setvar="pname"$>
<tr><td><$mt:GetVar name="pname"$></td>
<mt:Loop name="list">
<$mt:GetVar name="__key__" setvar="blog_id"$>
<$mt:GetVar name="__value__" setvar="category"$>
<mt:Blogs include_blogs="$blog_id">
<$mt:GetVar name="foo"$>
</mt:Blogs>
</mt:Loop>
</tr>
</mt:Entries>
</tbody>
</table>
MTLoopタグで、さきほどのハッシュを読み込んでthead要素とth要素を出力します。
<mt:Loop name="list">
<th><$mt:GetVar name="__value__"$></th>
</mt:Loop>
tbody要素ではMTEntriesタグでブログ記事を順番に読み出します。テーブルの一番左にブログ記事タイトルを出力するため、一旦変数pnameにブログ記事タイトルを保持して、それを出力します。
<mt:Entries>
<$mt:EntryTitle setvar="pname"$>
<tr><td><$mt:GetVar name="pname"$></td>
次のMTLoopタグでは、ハッシュ変数listのキーと値をそれぞれ読み出して、変数blog_idと変数categoryに保持します。変数blog_idはMTBlogsタグのblog_idモディファイアに利用して各ブログの情報を読み出します。
<mt:Loop name="list">
<$mt:GetVar name="__key__" setvar="blog_id"$>
<$mt:GetVar name="__value__" setvar="category"$>
<mt:Blogs include_blogs="$blog_id">
<$mt:GetVar name="foo"$>
</mt:Blogs>
</mt:Loop>
MTBlogsタグブロックで冒頭の表の○×部分の情報を出力しますが、ここでさきほどスキップしたMTSetVarTemplateタグの内容(変数foo)を利用します。
<mt:SetVarTemplate name="foo">
<$mt:SetVar name="pname_cat" value="0"$>
<mt:TopLevelCategories category="$category">
<$mt:CategoryLabel setvar="catname"$>
<mt:If name="catname" eq="$pname">
<$mt:SetVar name="pname_cat" value="1"$>
<mt:If tag="CategoryCount">
<td>○</td>
<mt:Else>
<td>×</td>
</mt:If>
</mt:If>
<$mt:SubCatsRecurse$>
</mt:TopLevelCategories>
<mt:Unless name="pname_cat">
<td>×</td>
</mt:Unless>
</mt:SetVarTemplate>
MTSetVarTemplateタグではTopLevelCategoriesタグを使って各ブログのカテゴリを順次読み出します。
<mt:TopLevelCategories category="$category">
<$mt:CategoryLabel setvar="catname"$>
読み出したカテゴリがブログ名と等しいカテゴリ名であれば、そのカテゴリに属するブログ記事数をMTIfタグとMTCategoryCountを組み合わせて判定し、記事が投稿されていれば○を、投稿されていなければ×をtd要素と組み合わせて出力します。
<mt:If name="catname" eq="$pname">
<$mt:SetVar name="pname_cat" value="1"$>
<mt:If tag="CategoryCount">
<td>○</td>
<mt:Else>
<td>×</td>
</mt:If>
</mt:If>
また、ブログ名と等しいカテゴリが1つも存在しない場合を考慮して、次の部分で×を出力します。
<mt:Unless name="pname_cat">
<td>×</td>
</mt:Unless>
変数pname_catはカテゴリ繰り返し処理の前に「0」を設定して、カテゴリ名とブログ名が等しい場合に「1」を設定するようにしています。
<$mt:SetVar name="pname_cat" value="0"$>
…中略…
<mt:If name="catname" eq="$pname">
<$mt:SetVar name="pname_cat" value="1"$>
最終的な形は、これに「Movable TypeでMTPagesタグとMTEntriesタグを入れ子にして動作させる方法」を組み合わせています。
具体的には、table要素全体をMTPagesタグで括って、ウェブページに作成した製品情報からブログ記事を取り出し、さらに各ブログの情報を取り出しています。ブログ記事を取り出す際にMTPagesのコンテキストと競合しないよう、MTEntriesタグにinclude_blogsモディファイアを与えます。
そのサブテンプレートについては以下の記事のコメント欄の最後の部分をご覧ください。
前述の記事や本エントリーで紹介するテンプレートを組み合わせれば、ブログ・カテゴリ・ウェブページ・ブログ記事の情報を組み合わせた、さまざまなテーブルを作ることができると思います。色々試してみてください。
Movable Typeのフォルダリストで特定のフォルダを表示しない方法
Movable Typeのフォルダリストで特定のフォルダ(またはフォルダ)を表示しない方法を紹介します。このカスタマイズはカテゴリにも適用可能です。
1.カスタマイズイメージ
このエントリーでは次の条件のカスタマイズを行います。
- 2階層のフォルダに1つ以上のウェブページが属する
- フォルダリストではサブフォルダを表示しない
- ウェブページのカスタムフォールドを使って、フォルダリスト上のフォルダの表示・非表示を制御
以下、具体的なカスタマイズ例です。
トップレベルフォルダが国名、サブフォルダが首都名で、サブフォルダの中にウェブページがひとつずつ入ってるフォルダリスト(カスタマイズ前)があります。
カスタマイズ前

まず、このフォルダリストからサブフォルダをすべて非表示にします。
サブフォルダを非表示

次に、各ウェブページには「foo」というカスタムフィールドがあり、fooに値を設定していない場合は、ウェブページとウェブページが属する親フォルダをすべて非表示にします。
例えば、上の一覧で「ソウル」ウェブページのfooに値が設定されていない場合、次のように「韓国」フォルダと「ソウル」ウェブページを非表示します。
特定のフォルダとウェブページを非表示

順不同リストのマークアップもvalidな内容で出力します。
2.サブフォルダを表示しないカスタマイズ
フォルダリストですべてのサブフォルダを表示しないようにするには、次のサブテンプレートを使用します。
<mt:TopLevelFolders>
<mt:SubCatIsFirst>
<mt:HasParentFolder>
<mt:else>
<ul>
</mt:HasParentFolder>
</mt:SubCatIsFirst>
<mt:HasParentFolder>
<mt:else>
<li><$mt:FolderLabel$>
</mt:HasParentFolder>
<mt:Pages>
<mt:PagesHeader>
<ul>
</mt:PagesHeader>
<li><mt:PageTitle></li>
<mt:PagesFooter>
</ul>
</mt:PagesFooter>
</mt:Pages>
<$mt:SubFolderRecurse$>
<mt:HasParentFolder>
<mt:else>
</li>
</mt:HasParentFolder>
<mt:SubCatIsLast>
<mt:HasParentFolder>
<mt:else>
</ul>
</mt:HasParentFolder>
</mt:SubCatIsLast>
</mt:TopLevelFolders>
青色の部分がサブフォルダを非表示にするための制御で、MTHasParentFolderタグで親フォルダがない場合、つまりトップレベルのフォルダのみ表示するようにしています。
3.特定のフォルダとウェブページを表示しないカスタマイズ
フォルダリストで、ウェブページのカスタムフィールド「foo」に値が入っていないフォルダとウェブページを非表示にするには、次のサブテンプレートを使用します。赤色は2項から追加した部分です。
<mt:TopLevelFolders>
<mt:Pages>
<mt:unless tag="foo">
<$mt:PageTitle setvar="pages" append="1"$>
<mt:TopLevelFolder>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
<mt:SubFolders>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
</mt:SubFolders>
</mt:TopLevelFolder>
</mt:unless>
</mt:Pages>
<$mt:SubFolderRecurse$>
</mt:TopLevelFolders>
<mt:TopLevelFolders>
<$mt:FolderLabel setvar="folder"$>
<mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
<ul>
</mt:HasParentFolder>
</mt:unless>
</mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
<li><$mt:FolderLabel$>
</mt:HasParentFolder>
</mt:unless>
<mt:unless name="folders" like="$folder">
<mt:Pages>
<mt:PagesHeader>
<ul>
</mt:PagesHeader>
<li><mt:PageTitle></li>
<mt:PagesFooter>
</ul>
</mt:PagesFooter>
</mt:Pages>
</mt:unless>
<$mt:SubFolderRecurse$>
<$mt:FolderLabel setvar="folder"$>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
</li>
</mt:HasParentFolder>
</mt:unless>
<mt:SubCatIsLast>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
</ul>
</mt:HasParentFolder>
</mt:unless>
</mt:SubCatIsLast>
</mt:TopLevelFolders>
4.サブテンプレートの流れ
サブテンプレートの大きな流れは次の通りです。
- 1回目のフォルダ一覧の繰り返し処理でfooに値が設定されていないウェブページをみつけ、その上位フォルダ(すべて)を変数foldersに保持。ウェブページタイトルも変数pagesに保持。
- 2回目のフォルダ一覧の繰り返し処理で、変数foldersをチェックし、該当フォルダの処理になった時点でトップレベルフォルダを表示しないよう制御
以下、ブロック別に処理を解説します。
5.フォルダ情報の取得
次のMTTopLevelFoldersタグで、1回目のフォルダ一覧の繰り返し処理を行います。
<mt:TopLevelFolders>
<mt:Pages>
<mt:unless tag="foo">
<mt:TopLevelFolder>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
<mt:SubFolders>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
</mt:SubFolders>
</mt:TopLevelFolder>
</mt:unless>
</mt:Pages>
<$mt:SubFolderRecurse$>
</mt:TopLevelFolders>
MTUnlessタグでfooに値がない場合のみ、MTTopLevelFolderタグでトップレベルフォルダのフォルダ名と、MTSubFoldersでその次のフォルダのフォルダ名を変数foldersに保持します。
6.ul開始タグの出力
次のMTTopLevelFoldersタグで、2回目のフォルダ一覧の繰り返し処理を行います。最初にul開始タグの出力部分から解説します。
<mt:TopLevelFolders>
<$mt:FolderLabel setvar="folder"$>
<mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
<ul>
</mt:HasParentFolder>
</mt:unless>
</mt:SubCatIsFirst>
MTFolderLabelタグで処理中のフォルダ名を変数folderに保持します。MTSubCatIsFirstタグ内の中のMTUnlessタグで、変数folderと1回目のフォルダ一覧の繰り返し処理で設定した変数foldersを比較し、一致するフォルダ名がなければ、さらに親フォルダの有無を判定し、トップレベルフォルダであればul要素を出力します。
7.li要素の開始タグとフォルダ名の出力
次の部分でli要素の開始タグとフォルダ名の出力を行います。変数folderと変数foldersを比較し、一致するフォルダ名がなければフォルダ名を出力します。一致するフォルダ名がある場合でも、MTHasParentFolderで判定し、サブフォルダであればフォルダ名を出力します。これは「アメリカ」フォルダを出力せず、「ニューヨーク」フォルダを出力させるためです。
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
<li><$mt:FolderLabel$>
</mt:HasParentFolder>
</mt:unless>
8.ウェブページタイトル出力
ウェブページタイトルは、処理中のフォルダ(変数folder)と変数foldersを比較し、一致するフォルダ名がなければ出力します。
<mt:unless name="folders" like="$folder">
<mt:Pages>
<mt:PagesHeader>
<ul>
</mt:PagesHeader>
<li><mt:PageTitle></li>
<mt:PagesFooter>
</ul>
</mt:PagesFooter>
</mt:Pages>
</mt:unless>
9.li終了タグの出力
再帰処理用のMTSubFolderRecurseの後にli終了タグの出力制御を行っています。
<$mt:FolderLabel setvar="folder"$>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
</li>
</mt:HasParentFolder>
</mt:unless>
先程と同様、変数folderと変数foldersを比較し、一致するフォルダ名がなければさらに親フォルダの有無を判定し、トップレベルフォルダであればli要素の終了タグを出力します。
10.ul終了タグの出力
最後にul終了タグの出力制御を行います。MTSubCatIsLastタグ内の中のMTUnlessタグで、変数folderと1回目のフォルダ一覧の繰り返し処理で設定した変数foldersを比較し、一致するフォルダ名がなければ、さらに親フォルダの有無を判定し、トップレベルフォルダであればul要素の終了タグを出力します。
<mt:SubCatIsLast>
<mt:unless name="folders" like="$folder">
<mt:HasParentFolder>
<mt:else>
</ul>
</mt:HasParentFolder>
</mt:unless>
</mt:SubCatIsLast>
</mt:TopLevelFolders>
11.サブフォルダを出力したい場合
3項のサブテンプレートは、2項の「サブフォルダを出力しないカスタマイズ」を含んでます。
「特定のフォルダとウェブページは表示したくないけど、表示するフォルダについてはサブフォルダも出力したい」という場合は、3項のサブテンプレートから青色のタグをすべて除去してください。
Movable Typeのカテゴリ・フォルダで特定の最上位階層を表示しない方法
Movable Typeのカテゴリ・フォルダで特定の最上位階層を表示しない方法を紹介します。
1.カスタマイズイメージ
トップレベルフォルダが国名、サブフォルダが首都名で、サブフォルダの中にウェブページがひとつずつ入ってるフォルダ一覧(カスタマイズ前)があります。
カスタマイズ前

各ウェブページにはfooというカスタムフィールドがあり、fooに値を設定していない場合は、このフォルダ一覧でウェブページが属するトップレベルフォルダを表示しません。
例えば、「ニューヨークウェブページ」と「ソウルウェブページ」のfooに値が設定されていない場合、次のように「アメリカ」と「韓国」というトップレベルフォルダを非表示します。
カスタマイズ後

順不同リストのマークアップもvalidな内容で出力します。
2.カスタマイズ
1項のカスタマイズを行うには次のサブテンプレートを使用します。ベストプラクティスではないかもしれませんが予めご容赦ください。
<$mt:SetVar name="counter" value="0"$>
<mt:TopLevelFolders>
<mt:Pages>
<mt:unless tag="foo">
<mt:TopLevelFolder>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
<mt:SubFolders>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
</mt:SubFolders>
</mt:TopLevelFolder>
</mt:unless>
</mt:Pages>
<$mt:SubFolderRecurse$>
<$mt:SetVar name="counter" op="++"$>
</mt:TopLevelFolders>
<$mt:GetVar name="counter" setvar="max"$>
<mt:TopLevelFolders>
<$mt:FolderLabel setvar="folder"$>
<mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<ul>
<mt:else>
<mt:if name="max" eq="$counter">
<mt:HasParentFolder>
<ul>
</mt:HasParentFolder>
</mt:if>
</mt:unless>
</mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<li><$mt:FolderLabel$>
<mt:else>
<mt:HasParentFolder>
<li><$mt:FolderLabel$>
</mt:HasParentFolder>
</mt:unless>
<mt:Pages>
<mt:PagesHeader>
<ul>
</mt:PagesHeader>
<li><mt:PageTitle></li>
<mt:PagesFooter>
</ul>
</mt:PagesFooter>
</mt:Pages>
<$mt:SubFolderRecurse$>
<$mt:SetVar name="counter" op="--"$>
<$mt:FolderLabel setvar="folder"$>
<mt:unless name="folders" like="$folder">
</li>
<mt:else>
<mt:HasParentFolder>
</li>
</mt:HasParentFolder>
</mt:unless>
<mt:SubCatIsLast>
<mt:unless name="folders" like="$folder">
</ul>
<mt:else>
<mt:unless name="counter">
</ul>
</mt:unless>
</mt:unless>
</mt:SubCatIsLast>
</mt:TopLevelFolders>
3.サブテンプレートの流れ
サブテンプレートの大きな流れは次の通りです。
- 1回目のフォルダ一覧の繰り返し処理でfooに値が設定されていないウェブページをみつけ、その上位フォルダ(すべて)を変数foldersに保持
- 2回目のフォルダ一覧の繰り返し処理で変数foldersをチェックし、該当フォルダの処理になった時点でトップレベルフォルダを表示しないよう制御
苦労したのは、トップレベルフォルダを非表示にしたときに、関連するul要素の数をあわせる部分です。非表示のトップレベルフォルダが順不同リストの先頭の場合はul開始タグを表示し、非表示のトップレベルフォルダが順不同リストの最後の場合、ul終了タグを表示する必要があります。
文章では分かりにくいので、順不同リストで示します。
次のマークアップは非表示のトップレベルフォルダが順不同リストの先頭の場合です。単純な制御では赤色の部分が表示されません。
<ul>
<li>ソウル
<ul>
<li>ソウルウェブページ</li>
</ul>
</li>
<li>日本
<ul>
<li>東京
<ul>
<li>東京ウェブページ</li>
</ul>
</li>
</ul>
</li>
</ul>
非表示のトップレベルフォルダが順不同リストの最後の場合です。単純な制御では赤色の部分が表示されません。
<ul>
<li>日本
<ul>
<li>東京
<ul>
<li>東京ウェブページ</li>
</ul>
</li>
</ul>
</li>
<li>ソウル
<ul>
<li>ソウルウェブページ</li>
</ul>
</li>
</ul>
以下、ブロック別に処理を解説します。
4.フォルダ情報の取得
次のMTTopLevelFoldersタグで、1回目のフォルダ一覧の繰り返し処理を行います。
<$mt:SetVar name="counter" value="0"$>
<mt:TopLevelFolders>
<mt:Pages>
<mt:unless tag="foo">
<mt:TopLevelFolder>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
<mt:SubFolders>
<$mt:FolderLabel setvar="label"$>
<$mt:SetVar name="folders" value="$label" append="1"$>
</mt:SubFolders>
</mt:TopLevelFolder>
</mt:unless>
</mt:Pages>
<$mt:SubFolderRecurse$>
<$mt:SetVar name="counter" op="++"$>
</mt:TopLevelFolders>
MTUnlessタグでfooに値がない場合のみ、MTTopLevelFolderタグでトップレベルフォルダのフォルダ名と、MTSubFoldersでその次のフォルダのフォルダ名を変数foldersに保持します。
先頭のMTSetVarタグで扱っている変数counterは、すべてのフォルダ数をカウントするためのものです。
5.ul開始タグの出力
次のMTTopLevelFoldersタグで、2回目のフォルダ一覧の繰り返し処理を行います。最初にul開始タグの出力部分から解説します。
<$mt:GetVar name="counter" setvar="max"$>
<mt:TopLevelFolders>
<$mt:FolderLabel setvar="folder"$>
<mt:SubCatIsFirst>
<mt:unless name="folders" like="$folder">
<ul>
<mt:else>
<mt:if name="max" eq="$counter">
<mt:HasParentFolder>
<ul>
</mt:HasParentFolder>
</mt:if>
</mt:unless>
</mt:SubCatIsFirst>
まず、変数counterを変数maxに保持します(変数counterは繰り返し処理内で減算させるため)。
MTFolderLabelタグで処理中のフォルダ名を変数folderに保持します。MTSubCatIsFirstタグ内の中のMTUnlessタグで、変数folderと1回目のフォルダ一覧の繰り返し処理で設定した変数foldersを比較し、一致するフォルダ名がなければul要素を出力します。
一致するフォルダ名がある場合は、さらにMTIfタグでフォルダ数の最大値であることを比較し、値が等しければ順不同リストの初回処理とみなしてul要素を出力します。MTHasParentFolderタグで括っているのはul要素を重複して出力させないためです。
6.li要素の開始タグとフォルダ名の出力
次の部分でli要素の開始タグとフォルダ名の出力を行います。変数folderと変数foldersを比較し、一致するフォルダ名がなければフォルダ名を出力します。一致するフォルダ名がある場合でも、MTHasParentFolderで判定し、サブフォルダであればフォルダ名を出力します。これは「アメリカ」フォルダを出力せず、「ニューヨーク」フォルダを出力させるためです。
<mt:unless name="folders" like="$folder">
<li><$mt:FolderLabel$>
<mt:else>
<mt:HasParentFolder>
<li><$mt:FolderLabel$>
</mt:HasParentFolder>
</mt:unless>
7.ウェブページタイトル出力
ウェブページタイトルの出力は、特筆すべきことはありません。
<mt:Pages>
<mt:PagesHeader>
<ul>
</mt:PagesHeader>
<li><mt:PageTitle></li>
<mt:PagesFooter>
</ul>
</mt:PagesFooter>
</mt:Pages>
8.li終了タグの出力
再帰処理用のMTSubFolderRecurseの後に変数counterの減算処理をいれてます。その後li終了タグの出力制御を行っています。
<$mt:SubFolderRecurse$>
<$mt:SetVar name="counter" op="--"$>
<$mt:FolderLabel setvar="folder"$>
<mt:unless name="folders" like="$folder">
</li>
<mt:else>
<mt:HasParentFolder>
</li>
</mt:HasParentFolder>
</mt:unless>
先程と同様、変数folderと変数foldersを比較し、一致するフォルダ名がなければli要素の終了タグを出力します。一致するフォルダ名がある場合でも、MTHasParentFolderで判定し、サブフォルダであればli要素の終了タグを出力します。これはさきほどの「アメリカ」フォルダを出力せず、「ニューヨーク」フォルダを出力させるための制御で、li要素の開始タグに対応する終了タグを出力させるためです。
9.ul終了タグの出力
最後にul終了タグの出力制御を行います。MTSubCatIsLastタグ内の中のMTUnlessタグで、変数folderと1回目のフォルダ一覧の繰り返し処理で設定した変数foldersを比較し、一致するフォルダ名がなければul要素の終了タグを出力します。
一致するフォルダ名がある場合は、さらにMTUnlessタグでフォルダ数が「0」であることを判定し、「0」であれば順不同リストの最後の処理とみなしてul要素の終了タグを出力します。
<mt:SubCatIsLast>
<mt:unless name="folders" like="$folder">
</ul>
<mt:else>
<mt:unless name="counter">
</ul>
</mt:unless>
</mt:unless>
</mt:SubCatIsLast>
</mt:TopLevelFolders>
Movable Typeのカテゴリリストにダミーの親カテゴリを表示する
Movable Typeのカテゴリリストにダミーの親カテゴリを表示するカスタマイズを紹介します。
1.カスタマイズのイメージ
まず、次のようなカテゴリ構成を想定します。
アメリカ
└ ニューヨーク
カナダ
└ バンクーバー
日本
└ 東京
中国
└ 北京
韓国
└ ソウル
このカテゴリ構成について、親カテゴリのみを次のように「北米」「アジア」などの地域名でグルーピング表示するように変更します。
北米
├ アメリカ
└ カナダ
アジア
├ 日本
├ 中国
└ 韓国
「アメリカ」「日本」などの親カテゴリのURLは変更しません。つまり「北米」「アジア」はカテゴリとして追加するのではなく、元のカテゴリをまとめるためだけに付与するタイトルです。
2.カスタマイズ
各親カテゴリの説明欄に、グルーピングしたい地域名を設定します。念のため子カテゴリの説明欄には何も設定しないでください。
「カナダ」の場合

「日本」の場合

設定後、次のようなサブテンプレートを作成します。
<mt:TopLevelCategories>
<mt:if tag="CategoryDescription">
<$mt:CategoryDescription setvar="area"$>
<mt:SetVarBlock name="list{$area}" append="1">
<li>
<a href="<$mt:CategoryArchiveLink$>"title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"><$mt:CategoryLabel$></a>
</li>
</mt:SetVarBlock>
</mt:If>
</mt:TopLevelCategories>
<mt:loop name="list">
<h2><mt:GetVar name="__key__"></h2>
<ul><mt:GetVar name="__value__"></ul>
</mt:loop>
これを再構築すれば、次のように表示されると思います。

3.サブテンプレートの説明
まず、MTTopLevelCategoriesタグで親カテゴリの一覧を取得します。次にMTIfタグを使って、カテゴリの説明欄に設定がある場合のみ、MTCategoryDescriptionタグの内容を変数areaに保持します。そして変数areaの値をハッシュ変数listのキーとして使い、ハッシュの値にカテゴリ名を設定します。
例えば「カナダ」カテゴリは、ハッシュ変数listに次のような感じで設定されます(イメージです)。
list{"北米"} = "<li><a href="...">カナダ</a></li>"
さらに「アメリカ」カテゴリは次のようにlist{"北米"}に追加されます。追加されるのは、MTSetVarBlockタグに「append="1"」を使って、追記するよう指定しているためです。
list{"北米"} = "<li><a href="...">カナダ</a></li><li><a href="...">アメリカ</a></li>"
同じように、「日本」「中国」「韓国」は次のように設定されます。
list{"アジア"} = "<li><a href="...">日本</a></li><li><a href="...">中国</a></li><li><a href="...">韓国</a></li>"
あとは、MTLoopタグとMTGetVarタグを使ってハッシュ変数areaを出力すれば完成です。
このカスタマイズはMT4/MT5で使えます。MT5.1であればデフォルト機能のカテゴリの並び替えを行うことで、並び替えた順番で表示することができます。
4.カテゴリの説明欄が使えない場合
カテゴリの説明欄を他の用途ですでに使っていて、今回のカスタマイズで使えない場合は、カテゴリ用のカスタムフィールドを追加し、そこに地域名を設定して利用する方法があります。
MTEntriesタグのcategoryモディファイアに「AND」を含むカテゴリを指定する
MTEntriesタグのcategoryモディファイアに「AND」を含むカテゴリ名を指定した場合の動作について紹介します。
例として、「foo and bar」というカテゴリが登録されており、MTEntriesタグのcategoryモディファイアにこのカテゴリ名を設定します。
<mt:Entries category="foo and bar">
<mt:EntryTitle>
</mt:Entries>
1.MTEntriesタグのcategoryモディファイアについて
MTEntriesタグのcategoryモディファイアに「AND」「OR」「NOT」を設定すれば、複雑な条件によるフィルタリングが可能です。
例えば、fooカテゴリと、barカテゴリに属するブログ記事を取得する場合は、次のように記述します。「AND」は小文字でも構いません。
<mt:Entries categories="foo AND bar">
fooカテゴリ以外のカテゴリに属する記事を取得する場合は次のようにします。
<mt:Entries categories="NOT foo">
2.カテゴリ名に「AND」が含まれる場合の動作
「AND」や「OR」をカテゴリ名に含んでいる場合、これらは条件としてではなく、先にカテゴリ名として評価するようです。
よって冒頭のサブテンプレートは、「foo and bar」というカテゴリに属するブログ記事を出力します。
<mt:Entries category="foo and bar">
<mt:EntryTitle>
</mt:Entries>
ただし大文字・小文字を区別するようなので、categoryモディファイアを次のように設定すれば、「foo and bar」というカテゴリではフィルタリングされず、「foo」と「bar」の両方が設定されたブログ記事を取得します。
<mt:Entries category="foo AND bar">
<mt:EntryTitle>
</mt:Entries>
この動作は、MT4.27/5.06/5.12で確認しています。
ブログ記事ページに自分が属するカテゴリのツリーと直属カテゴリの他のブログ記事一覧を表示する
Movable Typeのブログ記事ページに、自分が属するカテゴリのツリーと直属カテゴリの他のブログ記事一覧を表示するカスタマイズです。
例えば「業務提携に関するお知らせ」というブログ記事ページを表示したとき、図のように、ブログ記事ページのサイドバーに自分が属するカテゴリ「親カテゴリ」「子カテゴリ」と、直属のカテゴリ「孫カテゴリ」に属する他のブログ記事「オフィシャルサイトオープン」「ホームページリニューアル」を表示します。

カスタマイズ
ウィジェットテンプレートに次の内容を貼り付けてください。
<mt:if name="entry_archive">
<mt:IfArchiveTypeEnabled archive_type="Category">
<mt:EntryCategory setvar="category" />
<mt:ParentCategories>
<mt:SetVarBlock name="push(label)"><mt:CategoryLabel /></mt:SetVarBlock>
<mt:SetVarBlock name="push(list)"><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a></mt:SetVarBlock>
<mt:if tag="CategoryLabel" eq="$category">
<mt:CategoryID setvar="category_id">
</mt:if>
</mt:ParentCategories>
<div class="widget-archive widget-archive-category widget">
<h3 class="widget-header">カテゴリ</h3>
<div class="widget-content">
<mt:loop name="list">
<mt:SetVar name="end_tag" value="</ul></li>" append="1" />
<ul><li><mt:GetVar name="__value__" />
<mt:if name="__last__">
<mt:GetVar name="label" glue="/" setvar="category" />
<mt:Entries category="$category">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryPermalink>"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
<mt:GetVar name="end_tag" />
</mt:if>
</mt:loop>
</div>
</div>
</mt:IfArchiveTypeEnabled>
</mt:if>
最初のMTParentCategoriesの部分で自分が属するカテゴリのIDと、上位カテゴリの一覧を配列変数listに取得します。配列変数labelは、あとでブログ記事一覧を取得するときのcategoryモディファイアに設定するために取得します。
<mt:EntryCategory setvar="category" />
<mt:ParentCategories>
<mt:SetVarBlock name="push(label)"><mt:CategoryLabel /></mt:SetVarBlock>
<mt:SetVarBlock name="push(list)"><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a></mt:SetVarBlock>
<mt:if tag="CategoryLabel" eq="$category">
<mt:CategoryID setvar="category_id">
</mt:if>
</mt:ParentCategories>
MTLoopタグでは、配列変数listの内容を順番に出力し、最後のカテゴリ(=自分が属するカテゴリ)でMTEntriesタグを使ってブログ記事一覧を出力します。MTEntriesタグのcaetgoryモディファイアには配列変数labelの値を与え、glueモディファイアに区切り文字「/」を与えて、サブカテゴリを再現します。
<mt:loop name="list">
<mt:SetVar name="end_tag" value="</ul></li>" append="1" />
<ul><li><mt:GetVar name="__value__" />
<mt:if name="__last__">
<mt:GetVar name="label" glue="/" setvar="category" />
<mt:Entries category="$category">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryPermalink>"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
<mt:GetVar name="end_tag" />
</mt:if>
</mt:loop>
MT4.xの場合、categoryモディファイアにサブカテゴリを設定できるのは比較的新しいバージョンだけだったと記憶してますので注意してください。MT5では正常に動作します。
Movable Type 5.1ベータ2リリースとMTEntryPrimaryCategoryタグ・MTEntryCategoriesタグのtypeモディファイアについて
Movable Type 5.1ベータ2がリリースされました。
ベータ2のトピックとして、MTEntryPrimaryCategoryタグとMTEntryCategoriesタグにtypeモディファイアが追加されましたので簡単に紹介します。
1.MTEntryPrimaryCategoryタグ
MTEntryPrimaryCategoryは、ブログ記事のメインカテゴリの情報を取得するためのブロックタグです。
これまでメインカテゴリの情報は、MTEntryCategoryファンクションタグでメインカテゴリのカテゴリ名を取得するか、それ以外の情報はMTEntryCategoryタグ・MTEntryCategoriesタグ・条件タグを組み合わせて取得するか、「EntryCategoryIDプラグイン」などのプラグインで取得する必要がありましたが、このタグを使えばメインカテゴリの情報を簡単に取得できます。
例:ブログ記事タイトルにメインカテゴリ名とメインカテゴリのIDを表示
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:EntryPrimaryCategory>
<li><mt:EntryTitle> [<mt:CategoryLabel />(<mt:CategoryID />)]</li>
</mt:EntryPrimaryCategory>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
2.MTEntryCategoriesタグのtypeモディファイア
MTEntryCategoriesタグに「type="primary"」を付与できるようになりました。これにより、MTEntryPrimaryCategoryタグと同様の効果を得ることができます。
例:ブログ記事タイトルにメインカテゴリ名とメインカテゴリのIDを表示
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:EntryCategories type="primary">
<li><mt:EntryTitle> [<mt:CategoryLabel />(<mt:CategoryID />)]</li>
</mt:EntryCategories>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
3.関連記事
Movable Typeでカテゴリ別+ブログ記事別に新着コメントを表示する
Movable Typeでカテゴリ別+ブログ記事別に新着コメントを表示するカスタマイズを紹介します。
ここでは「お知らせ」「イベント」という2つのカテゴリがあり、それぞれ最新の10件をブログ記事別に出力する例を示します(サンプル画像は投稿コメントが10件に満たないので少なくなってます)。

このカスタマイズは「「最近のコメント」をネイティブタグのみで適正に表示する」の応用です。
1.サブテンプレート
カテゴリ別に新着コメントを表示するには、次のサブテンプレートをコピー&ペーストしてください。赤色部分が出力したいカテゴリになりますので適宜変更してください。
<mt:SetVar name="count1" value="0" />
<mt:SetVar name="count2" value="0" />
<mt:Comments>
<mt:CommentEntry>
<mt:SetVarBlock name="entry_title"><a href="<mt:EntryPermalink />"><mt:EntryTitle /></a></mt:SetVarBlock>
<mt:SetVarBlock name="entry_comment">
<li><a href="<mt:EntryPermalink />#c<mt:CommentID />"><mt:CommentAuthor default="Anonymous"></a> <mt:CommentDate format="%m/%d"></li>
</mt:SetVarBlock>
<mt:If tag="EntryCategory" eq="お知らせ">
<mt:If name="count1" lt="10">
<mt:SetVar name="comment_list1{$entry_title}" value="$entry_comment" prepend="1" />
<mt:SetVar name="count1" op="++" />
</mt:If>
<mt:SetVar name="flag1" value="0" />
<mt:loop name="title_list1">
<mt:if name="__value__" eq="$entry_title">
<mt:setVar name="flag1" value="1" />
</mt:if>
</mt:loop>
<mt:unless name="flag1">
<mt:setVar name="push(title_list1)" value="$entry_title" />
</mt:unless>
</mt:If>
<mt:If tag="EntryCategory" eq="イベント">
<mt:If name="count2" lt="10">
<mt:SetVar name="comment_list2{$entry_title}" value="$entry_comment" prepend="1" />
<mt:SetVar name="count2" op="++" />
</mt:If>
<mt:SetVar name="flag2" value="0" />
<mt:loop name="title_list2">
<mt:if name="__value__" eq="$entry_title">
<mt:setVar name="flag2" value="1" />
</mt:if>
</mt:loop>
<mt:unless name="flag2">
<mt:setVar name="push(title_list2)" value="$entry_title" />
</mt:unless>
</mt:If>
</mt:CommentEntry>
</mt:Comments>
<h2>お知らせ</h2>
<mt:loop name="title_list1">
<li>
<mt:getVar name="__value__" />
<ul>
<mt:getVar name="comment_list1{$__value__}" />
</ul>
</li>
</mt:loop>
<h2>イベント</h2>
<mt:loop name="title_list2">
<li>
<mt:getVar name="__value__" />
<ul>
<mt:getVar name="comment_list2{$__value__}" />
</ul>
</li>
</mt:loop>
2.解説
まず、カテゴリ別にコメント数をカウントするためのカウンタとして、変数count1と変数count2を初期化します。カウンタは出力させたいカテゴリ分用意します。
<$mt:SetVar name="count1" value="0"$>
<$mt:SetVar name="count2" value="0"$>
MTCommentsタグを使って最新のコメントから処理します。その中でMTCommentEntryタグを使い、コメントが投稿されたブログ記事のコンテキストに移動します。その中でブログ記事タイトルを変数entry_title、コメント情報を変数entry_commentに設定します。
<mt:Comments>
<mt:CommentEntry>
<mt:SetVarBlock name="entry_title"><a href="<mt:EntryPermalink />"><mt:EntryTitle /></a></mt:SetVarBlock>
<mt:SetVarBlock name="entry_comment">
<li><a href="<mt:EntryPermalink />#c<mt:CommentID />"><mt:CommentAuthor default="Anonymous"></a> <mt:CommentDate format="%m/%d"></li>
</mt:SetVarBlock>
次にブログ記事のメインカテゴリをMTIfタグで判定し、該当のカテゴリ(ここでは「お知らせ」)であれば、さらにカウンタの値が10以下であることを判定し、10以下であれば先程の2つの変数をハッシュ変数comment_list1に設定し、カウンタをインクリメントします。「10」の部分を変更すれば出力するコメント数を変更できます。
注:このカスタマイズではMTCommentsタグにlastnモディファイアを与えていないので、ブログに大量のコメントがある場合は「lastn=100」などを追加して、処理が重くならないようにしてください。
<mt:If tag="EntryCategory" eq="お知らせ">
<mt:If name="count1" lt="10">
<mt:SetVar name="comment_list1{$entry_title}" value="$entry_comment" prepend="1" />
<mt:SetVar name="count1" op="++" />
</mt:If>
さらに、MTLoopタグで配列変数title_list1を処理し、現在処理中のブログ記事タイトルが含まれていなければ、配列変数title_list1に追加します。この配列変数title_list1は新着コメントがついたブログ記事の順番を記憶するために利用しています。
<mt:SetVar name="flag1" value="0" />
<mt:loop name="title_list1">
<mt:if name="__value__" eq="$entry_title">
<mt:setVar name="flag1" value="1" />
</mt:if>
</mt:loop>
<mt:unless name="flag1">
<mt:setVar name="push(title_list1)" value="$entry_title" />
</mt:unless>
上記の処理は「イベント」カテゴリについても同様の処理を行います。
最後に、MTLoopタグで変数title_list1を処理し、その中でブログ記事タイトル順に変数comment_list1の内容を出力します。「イベント」カテゴリについても同様の処理を行います。
<h2>お知らせ</h2>
<mt:loop name="title_list1">
<li>
<mt:getVar name="__value__" />
<ul>
<mt:getVar name="comment_list1{$__value__}" />
</ul>
</li>
</mt:loop>
3.カテゴリを増やしたい場合
表示するカテゴリを増やしたい場合は、次の青色の内容をMTCommenEntryタグの終了タグの直前に追加してください。赤色の「x」にはすべて同じ半角数字(または半角英文字)を設定してください。
<mt:If tag="EntryCategory" eq="カテゴリ名">
<mt:If name="countx" lt="10">
<mt:SetVar name="comment_listx{$entry_title}" value="$entry_comment" prepend="1" />
<mt:SetVar name="countx" op="++" />
</mt:If>
<mt:SetVar name="flagx" value="0" />
<mt:loop name="title_listx">
<mt:if name="__value__" eq="$entry_title">
<mt:setVar name="flagx" value="1" />
</mt:if>
</mt:loop>
<mt:unless name="flagx">
<mt:setVar name="push(title_listx)" value="$entry_title" />
</mt:unless>
</mt:If>
</mt:CommentEntry>
</mt:Comments>
また、出力する部分として次の内容を追加してください。
<h2>カテゴリ名</h2>
<mt:loop name="title_listx">
<li>
<mt:getVar name="__value__" />
<ul>
<mt:getVar name="comment_listx{$__value__}" />
</ul>
</li>
</mt:loop>
Movable Type 5でのMTEntriesタグのcategory/catgoriesモディファイアの動作改善について
Movable Type 5で、MTEntriesタグのcategoryモディファイア(catgoriesモディファイア)の動作が、Movable Type 4から改善されています。
ここではサンプルデータを用いて、MT4とMT5の動作比較を行った結果を紹介します。
1.サンプルデータ
次のような6つのブログ記事と、5つのカテゴリを用意しました。
| ブログ記事 | カテゴリ |
|---|---|
| モバイルサイトオープン | ニュース |
| 業務提携に関するお知らせ | ニュース |
| ソリューションセミナー | お知らせ/ニュース |
| Movable Type 入門セミナー | お知らせ/ニュース |
| オフィシャルサイトオープン | イベント/ニュース |
| シンポジウム2010 | イベント/ニュース |
最初の2つのブログ記事は「ニュース」カテゴリに属し、次の2つのブログ記事は「お知らせ」とう親カテゴリ配下にある「ニュース」カテゴリに属し、最後の2つのブログ記事は「イベント」とう親カテゴリ配下にある「ニュース」カテゴリに属しています。カテゴリーツリーで示すと、次の通りです。
ニュース
├ モバイルサイトオープン
└ 業務提携に関するお知らせ
お知らせ
└ ニュース
├ リューションセミナー
└ Movable Type 入門セミナー
イベント
└ ニュース
├ オフィシャルサイトオープン
└ シンポジウム2010
実験の観点は、それぞれの記事が属する「ニュース」というカテゴリをcategory(またはcategories)モディファイアで指定したときに、Movable Type 4とMovable Type 5でどのような出力結果になるか、という点です。
MT4のバージョンは4.27、MT5のバージョンは5.031です。categoriesモディファイアの動作はcategoryモディファイアと同じなので、以下の実験では省略しています。
2.categoryモディファイアに直属するカテゴリ名を指定
次のようなサブテンプレートを実行します。MTEntriesタグにcategoryモディファイアを与え、モディファイアの値に「ニュース」を設定します。
<mt:Entries category="ニュース">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><mt:EntryTitle />[<mt:ParentCategories glue="/"><mt:CategoryLabel /></mt:ParentCategories>]</li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
Movable Type 4.27の出力結果

Movable Type 5.031の出力結果

MT4では「ニュース」というカテゴリ名のすべてのブログ記事が出力されるのに対し、MT5では、トップカテゴリにある「ニュース」に属するブログ記事のみが出力されるように改善されています。
3.categoryモディファイアに親カテゴリを含めて指定
2項のサブテンプレートのcategoryモディファイアの値に、親カテゴリを含めた「お知らせ/ニュース」を設定します。親カテゴリと子カテゴリは半角スラッシュ「/」で区切ります。
<mt:Entries category="お知らせ/ニュース">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><mt:EntryTitle />[<mt:ParentCategories glue="/"><mt:CategoryLabel /></mt:ParentCategories>]</li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
Movable Type 4.27の出力結果
(出力なし)
Movable Type 5.031の出力結果

このように、MT5では期待通りの出力結果が得られます。
4.MT5で同一カテゴリに属するブログ記事一覧を出力する
ブログ記事アーカイブページに、同一カテゴリに属するブログ記事一覧を出力する場合、MT4までは「特定のカテゴリーに属するブログ記事一覧を表示する(改)」に示すように、かなり複雑なサブテンプレートを設定する必要がありましたが、MT5では次のように比較的シンプルなサブテンプレートで実現できます。
<mt:EntryID setvar="entryID" />
<mt:ParentCategories glue="/" setvar="entryCategories"><mt:CategoryLabel /></mt:ParentCategories>
<mt:Entries category="$entryCategories">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<mt:if tag="EntryID" ne="$entryID">
<li><a href="<mt:EntryPermaLink />"><mt:EntryTitle /></a></li>
</mt:if>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
親カテゴリーアーカイブにサブカテゴリーのブログ記事を表示する場合に特定のサブカテゴリーのブログ記事をフィルタリングする
Movable Type(MT)のカテゴリ別ブログ記事リスト(カテゴリーアーカイブ)で、MTEntriesWithSubCategoriesタグを使って、親カテゴリーアーカイブページにサブカテゴリーのブログ記事を表示する場合、特定のサブカテゴリーのブログ記事をフィルタリングする方法を紹介します。
この方法はバージョン4以降で有効です。
1.基本
カテゴリの判定にはMTIfタグとtagモディファイアを使い、tagモディファイアの値に「EntryCategory」を与えます。これで処理中のブログ記事のメインカテゴリを判定できます。
<mt:if tag="EntryCategory" ・・・>
ただし、サブカテゴリがそのブログ記事のメインカテゴリでない場合、この判定にひっかかりません。例えば、親カテゴリが「A」、サブカテゴリが「X」「Y」「Z」という構成で、あるブログ記事のメインカテゴリが、「A」「X」「Y」「Z」とは無関係な「B」で、副カテゴリに「X」が設定されている場合です。
ブログ記事が属するすべてのカテゴリを判定したい場合は、例えば次のようにします。
<mt:EntryCategories>
<mt:if tag="CategoryLabel" ・・・>
</mt:EntryCategories>
以下、メインカテゴリを判定する例でいくつかのパターンを紹介します。副カテゴリを判定したい場合は、判定箇所を上記のリストに入れ替えてください。
2.「foo」「bar」カテゴリのブログ記事のみを出力する
MTIfタグにlikeモディファイアを組み合わせます。モディファイアの値にヒットさせたいカテゴリを「|」で区切って記述します。ただし、この方法では「foo2」や「bari」など、指定した文字列を含むカテゴリも対象になります。
<mt:EntriesWithSubCategories>
<mt:if tag="EntryCategory" like="foo|bar">
<$mt:Include module="ブログ記事の概要"$>
</mt:if>
</mt:EntriesWithSubCategories>
完全一致したカテゴリだけをフィルタリングしたい場合は、MTIfタグとMTElseifタグを組み合わせるとよいでしょう。ヒットさせたいカテゴリ分、MTElseifタグを増やします。MTElseifタグのtagモディファイアを省略すると正常に動作しないので気をつけましょう。
<mt:EntriesWithSubCategories>
<mt:if tag="EntryCategory" eq="foo">
<$mt:Include module="ブログ記事の概要"$>
<mt:elseif tag="EntryCategory" eq="bar">
<$mt:Include module="ブログ記事の概要"$>
</mt:if>
</mt:EntriesWithSubCategories>
副カテゴリも判定したい場合は次のようにします。
<mt:EntriesWithSubCategories>
<mt:EntryCategories>
<mt:if tag="CategoryLabel" eq="foo">
<$mt:Include module="ブログ記事の概要"$>
<mt:elseif tag="CategoryLabel" eq="bar">
<$mt:Include module="ブログ記事の概要"$>
</mt:if>
</mt:EntryCategories>
</mt:EntriesWithSubCategories>
上記のマークアップでは、ひとつのブログ記事にヒットするサブカテゴリが複数設定されていると、ブログ記事が重複して出力されるので、さらに次のような制御が必要です。
<mt:EntriesWithSubCategories>
<mt:SetVar name="flag" value="0" />
<mt:EntryCategories>
<mt:unless name="flag">
<mt:if tag="CategoryLabel" eq="foo">
<$mt:Include module="ブログ記事の概要"$>
<mt:SetVar name="flag" value="1" />
<mt:elseif tag="CategoryLabel" eq="bar">
<$mt:Include module="ブログ記事の概要"$>
<mt:SetVar name="flag" value="1" />
</mt:if>
</mt:unless>
</mt:EntryCategories>
</mt:EntriesWithSubCategories>
3.「foo」カテゴリ以外のブログ記事を出力する
MTIfタグにneモディファイアを組み合わせます。
<mt:EntriesWithSubCategories>
<mt:if tag="EntryCategory" ne="foo">
<$mt:Include module="ブログ記事の概要"$>
</mt:if>
</mt:EntriesWithSubCategories>
4.「foo」「bar」カテゴリ以外のブログ記事を出力する
MTUnlessタグにlikeモディファイアを組み合わせます。ただし「foo2」や「bari」など、指定した文字列を含むカテゴリも除外されます。
<mt:EntriesWithSubCategories>
<mt:unless tag="EntryCategory" like="foo|bar">
<$mt:Include module="ブログ記事の概要"$>
</mt:unless>
</mt:EntriesWithSubCategories>
完全一致したカテゴリだけを除外したい場合はちょっと技が必要になります。ここではMTIfタグとtestモディファイアを組み合わせた例を示します。
MTEntryCategoryタグの内容を一旦変数catに保持して、testモディファイアの中でPerlの条件文を使って判定します。testモディファイアの結果が真であれば、MTIfタグブロックを実行します。
<mt:EntriesWithSubCategories>
<mt:EntryCategory setvar="cat">
<mt:if test="$cat ne 'foo' && $cat ne 'bar'">
<$mt:Include module="ブログ記事の概要"$>
</mt:if>
</mt:EntriesWithSubCategories>
以上です。このようにカテゴリをフィルタリングする方法はバリエーションがあるので、色々な試してみてください。
EntryCategoryID プラグイン v0.10
現在のブログ記事のメインカテゴリーのID番号を出力する EntryCategoryID プラグインのMovable Type 5対応版を作成しました。このプラグインは、MTEntries ブロック内か、ブログ記事アーカイブで使用できます。
1.基本
このプラグインは次のように利用します。これでメインカテゴリーのID番号を出力します。
<mt:Entries>
<mt:EntryCategoryID />
</mt:Entries>
2.ブログ記事に同一カテゴリーのブログ記事リストを表示する
このプラグインは「ブログ記事に同一カテゴリーのブログ記事リストを表示(MT4版・改)」で紹介しているようなことを行いたい場合に便利です。
ブログ記事アーカイブに次のサブテンプレートを設定すれば、同一カテゴリーのブログ記事リストを表示します。
<mt:EntryCategoryID setvar="entry_category_id" />
<mt:Entries>
<mt:EntriesHeader>
<div class="comments">
<h2 class="comments-header">同一カテゴリのブログ記事</h2>
<div class="comments-content">
<ul>
</mt:EntriesHeader>
<mt:EntryCategoryID setvar="current_category_id">
<mt:if name="current_category_id" eq="$entry_category_id">
<li><a href="<mt:EntryPermalink />"><mt:EntryTitle /></a></li>
</mt:if>
<mt:EntriesFooter>
</ul>
</div>
</div>
</mt:EntriesFooter>
</mt:Entries>
3.ダウンロード
EntryCategoryID プラグインは以下のリンクからダウンロードしてください。
特定のカテゴリのブログ記事を表示する
Movable Typeで、「特定のカテゴリのブログ記事を昇順で表示することはできないでしょうか」というご質問を頂きましたので、本エントリーで紹介します。
1.特定のカテゴリのブログ記事を表示する
特定のカテゴリのブログ記事を表示するには、MTEntriesタグにcategoryモディファイアを設定し、モディファイアの値にカテゴリ名を設定します。例えば、「お知らせ」というカテゴリに属するブログ記事を表示させるには、次のように設定します。
<mt:Entries category="お知らせ">
…中略…
</mt:Entries>
2.ブログ記事を昇順で表示する
ブログ記事を昇順で表示するには、MTEntriesタグにsort_orderモディファイアを設定し、モディファイアの値に「ascend」を設定します。
<mt:Entries sort_order="ascend">
…中略…
</mt:Entries>
このモディファイアを設定しなければ降順で表示されます。
3.特定のカテゴリのブログ記事を昇順で表示する
ということで、特定のカテゴリのブログ記事を昇順で表示するには、1項のモディファイアと2項のモディファイアを組み合わせます。
<mt:Entries category="お知らせ" sort_order="ascend">
…中略…
</mt:Entries>
なお、表示する件数を絞りたい場合、次のようにlimitモディファイアで表示件数を指定するとよいでしょう。
<mt:Entries limit="10" category="お知らせ" sort_order="ascend">
…中略…
</mt:Entries>
より高度な設定を行いたい場合は、「特定のカテゴリーに属するブログ記事一覧を表示する(改)」を参照してください。
親カテゴリページにサブカテゴリページのリンクを表示する
親カテゴリページにサブカテゴリページのリンクを表示するカスタマイズを紹介します。ご質問をいただいたので、パターンをいくつか揃えてみました。
ここでは、次のようなカテゴリとブログ記事の構成をサンプルにします。

1.基本
親カテゴリ直下のサブカテゴリ名を表示します。サブカテゴリ名にはカテゴリアーカイブページへのリンクを設定します。
親カテゴリアーカイブページの表示

子カテゴリ1アーカイブページの表示
![]()
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a></li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
サイドバーのカテゴリリストはMTTopLevelCategoriesタグを用いますが、カテゴリアーカイブページでカテゴリの階層関係を制御する場合は、MTSubCategoriesタグを利用します。
2.基本(階層表示)
親カテゴリに含まれるサブカテゴリを階層表示する場合は、1項のサブテンプレートに、MTSubCatsRecurseタグを追加します。
親カテゴリアーカイブページの表示

<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a>
<mt:SubCatsRecurse />
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
3.サブカテゴリページにブログ記事タイトルを表示する
親カテゴリページには直下のサブカテゴリのカテゴリ名のみを表示し、最下層のサブカテゴリページはブログ記事タイトルのみを表示します。
孫カテゴリアーカイブページの表示

<mt:hasSubCategories>
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a></li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
<mt:else>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</mt:hasSubCategories>
MTHasSubCategoriesタグでサブカテゴリの有無を判定し、サブカテゴリがあれば、サブカテゴリ名のみを表示します。サブカテゴリがなければ最下層のカテゴリとみなし、ブログ記事タイトルを表示します。
4.サブカテゴリページにブログ記事タイトルを表示する(階層表示)
サブカテゴリを階層表示する場合は、3項のサブテンプレートに、MTSubCatsRecurseタグを追加します。
親カテゴリアーカイブページの表示

<mt:hasSubCategories>
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a>
<mt:SubCatsRecurse />
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
<mt:else>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</mt:hasSubCategories>
5.サブカテゴリ名とブログ記事タイトルをあわせて表示する
親カテゴリページには直下のサブカテゴリのカテゴリ名と、サブカテゴリに属するブログ記事タイトルを表示し、最下層のサブカテゴリページはブログ記事タイトルのみを表示します。
親カテゴリアーカイブページの表示

子カテゴリ1アーカイブページの表示

孫カテゴリアーカイブページの表示

<mt:hasSubCategories>
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
<mt:else>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</mt:hasSubCategories>
最下層のカテゴリでブログ記事タイトルを表示しない場合は次のようにします。
<mt:hasSubCategories>
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
</mt:hasSubCategories>
6.サブカテゴリ名とブログ記事タイトルをあわせて表示する(階層表示)
サブカテゴリを階層表示する場合は、5項のサブテンプレートに、MTSubCatsRecurseタグを追加します。
親カテゴリアーカイブページの表示

子カテゴリ1アーカイブページの表示

孫カテゴリアーカイブページの表示

<mt:hasSubCategories>
<mt:SubCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<li><a href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
<mt:SubCatsRecurse />
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:SubCategories>
<mt:else>
<mt:Entries>
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryLink />"><mt:EntryTitle /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
</mt:hasSubCategories>
Movable Type 5(MT5)のカテゴリ削除動作
ちょっと古い話ですが、Movable Type 3.x~4.1 の時代まで、サブカテゴリがあるカテゴリの削除はできませんでした。バージョン4.1で削除を実行すると、次のようなエラーが発生します。

よって、親カテゴリを削除する場合、削除前にサブカテゴリを削除するか、サブカテゴリを他のカテゴリへの移動する必要がありました。
しばらくその動作だと思い込んでいたのですが、Movable Type 5(MT5)では、サブカテゴリがある親カテゴリの削除が可能になっていました。ということで、いつのバージョンから削除可能になったのか、確認したところ、バージョン4.22ですでに削除可能になっていました。ということで全く気がついていませんでした…。
削除した場合、サブカテゴリは親カテゴリに昇格します。なお、サブフォルダは元々削除できていたようです。
sort_method モディファイア(その2)
Movable Type で、カテゴリやフォルダを並べ替えるための sort_method モディファイアの紹介です。「sort_method モディファイア(その1)」の続きです。
1.ソート条件に対応するプラグインの作成
指定した条件に対応するプラグインを作成します。ここでは「sort_method モディファイア(その1)」で紹介したソースコードを利用します。パッケージ名は少し変えてますが、次の2ファイルを作成します。
config.yaml
id: CategorySorting
name: CategorySorting
CategorySorting.pm
package CategorySorting;
my %category_priorities = (
'foo' => 1,
'bar' => 2,
);
sub cat_sort ($$) {
my ($a, $b) = @_;
my $a_pri = $category_priorities{$a->label} || 1000;
my $b_pri = $category_priorities{$b->label} || 1000;
unless ($a_pri == 1000 && $b_pri == 1000) {
return $a_pri <=> $b_pri;
}
return $a->label cmp $b->label;
}
ハッシュ変数 %category_priorities にカテゴリの優先度を設定します。このプラグインではカテゴリ名をソート条件にしており、「foo」というカテゴリを1番目に、「bar」というカテゴリを2番目に並ぶように、優先度を設定しています。
変数 $a と $b には、ソート対象のカテゴリオブジェクトが設定されます。ソートするカテゴリの優先度がハッシュ変数%category_prioritiesに設定されていれば、2つのカテゴリのソート結果を返却し、そうでない場合は直接カテゴリ名でのソート結果を返却します。
プラグイン作成後、次のようなディレクトリ構成になるように plugins ディレクトリに2つのファイルをアップロードします。
plugins/
CategorySorting/
config.yaml
lib/
CategorySorting.pm
システム管理画面の「ツール」→「プラグイン」で「CategorySorting」が表示されればOKです。
2.sort_method モディファイアの追加
MTTopLevelCategories タグなどに、sort_method モディファイアを追加し、ソートする条件を指定します。ここではソート条件として、作成したプラグインのメソッド名を指定します。
<mt:IfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
<h3 class="widget-header">カテゴリ</h3>
<div class="widget-content">
<mt:TopLevelCategories sort_method="CategorySorting::cat_sort">
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<mt:If tag="CategoryCount">
<li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"</mt:If>><$mt:CategoryLabel$> (<$mt:CategoryCount$>)</a>
<mt:Else>
<li><$mt:CategoryLabel$>
</mt:If>
<$mt:SubCatsRecurse$>
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:TopLevelCategories>
</div>
</div>
</mt:IfArchiveTypeEnabled>
ソート条件は各階層単位に適用されます。
sort_method モディファイア(その1)
Movable Type の MTSubCategories タグや MTTopLevelCategories タグでは sort_method というカテゴリを並び替えるモディファイアが利用可能です。
ネットで情報を検索すると、sort_method のサンプルで大体同じソースコードが登場するのですが、発信元は David Raynes 氏の SubCategories プラグインのようです。
また、よくみかけるソースコードは以下にありました。
SubCategories Plugin Documentation
package rayners::CategorySorting;
my %category_priorities = (
# I want 'MT Plugins' to appear before 'MT Brainstorming'
# followed by the rest
'MT Plugins' => 1
'MT Brainstorming' => 2,
# And I want 'SubCategories' to be the first plugin listed,
# followed by 'Entry' and then the rest of the plugins
'SubCategories' => 1,
'Entry' => 2,
);
sub cat_sort ($$) {
my ($a, $b) = @_;
my $a_pri = $category_priorities{$a->label} || 1000;
my $b_pri = $category_priorities{$b->label} || 1000;
unless ($a_pri == 1000 && $b_pri == 1000) {
# At least one of them has a defined priority
# so sort on that
return $a_pri <=> $b_pri;
}
# Both are the default value (1000)
# so sort alphabetically
return $a->label cmp $b->label;
}
Movable Type でカテゴリ別にブログ記事の背景画像を切り替える(カスタムフィールド編)
Movable Type 4 以降のバージョンで、カテゴリ別にブログ記事の背景画像を切り替えるカスタマイズを紹介します。
先日エントリーした「Movable Type でカテゴリ別にブログ記事の背景画像を切り替える」では、手動でアップロードした画像を利用する方法を紹介しましたが、このエントリーではカスタムフィールドを利用した場合の差分を示します。
1.カテゴリのカスタムフィールドの作成
ブログ管理画面の「カスタムフィールド」→「新規」で、次のようなカスタムフィールドを作成します。ここでは次のような設定にします。
- システムオブジェクト:カテゴリ
- カスタムフィールド名:背景画像
- 種類:画像
- テンプレートタグ名:CategoryBackgroundImage

2.背景画像のアップロード
カテゴリの編集画面の「背景画像」から、そのカテゴリの背景画像にしたい画像をそれぞれアップロードします。アップロード後は「変更を保存」をクリックするのを忘れないようにしてください。

3.スタイルシートの修正
「Movable Type でカテゴリ別にブログ記事の背景画像を切り替える」の2項と同じです。
4.スタイルシートの修正
「Movable Type でカテゴリ別にブログ記事の背景画像を切り替える」の3項の代わりに、スタイルシートに以下の内容を追加します。
<mt:Categories>
<mt:CategoryCustomFields>
<mt:If tag="CategoryBackgroundImage">
<mt:CategoryBackgroundImageAsset>
.img_<mt:CategoryDescription /> {
background: url(<mt:AssetURL />) no-repeat left top;
}
</mt:CategoryBackgroundImageAsset>
</mt:If>
</mt:CategoryCustomFields>
</mt:Categories>
追加後、スタイルシートの再構築を行ないます。これでカテゴリ別の背景画像用のセレクタが出来上がります。
5項以降の設定は「Movable Type でカテゴリ別にブログ記事の背景画像を切り替える」の4項以降と同様です。
Movable Type でカテゴリ別にブログ記事の背景画像を切り替える
Movable Type 4 以降のバージョンで、カテゴリ別にブログ記事の背景画像を切り替えるカスタマイズを紹介します。
この記事は、Twitter 上で immovabletype さんのつぶやきに対してお伝えした内容をまとめたものです。
まず、カテゴリ別に背景画像を適用するイメージを図に示します。

図の説明ですが、まずカテゴリ別の背景画像を用意します。ここでは「日記」「旅行」「趣味」の3つのカテゴリの背景画像を想定します。次に各背景画像を、カテゴリ別のセレクタとしてスタイルシートに設定します。そして、各ページのブログ記事の背景画像として適用します。例えば、「日記」カテゴリに属するブログ記事Aには、緑色の背景画像を適用します。
また、カテゴリの増減に対応できるよう、スタイルシートや各テンプレートにはテンプレートタグを利用して、再構築するだけで自動的に背景画像を適用できるようにします。手動で用意するのは背景画像のみです。
背景画像の設定にはカテゴリのカスタムフィールドを利用する手もありますが、ここでは MTOS でも利用可能な設定方法を紹介します。カスタムフィールドを用いた方法は別途エントリーしたいと思います。
1.背景画像のアップロード
背景画像にしたいカテゴリ別の画像を、メインページと同じディレクトリにアップロードします。
2.「カテゴリの説明」の設定
各カテゴリの「カテゴリの説明」欄に、背景画像のファイル名を設定します(拡張子は除く)。冒頭の例では、次のような設定になります。
| カテゴリ | カテゴリの説明 |
|---|---|
| 日記 | diary |
| 旅行 | travel |
| 趣味 | hobby |
カテゴリ名を背景画像のファイル名に使ってもよいのですが、カテゴリ名に全角を使っているとCSSのセレクタに使用できないので、「カテゴリの説明」欄を使用しています。
3.スタイルシートの修正
スタイルシートに以下の内容を追加します。
<mt:Categories>
.img_<$MTCategoryDescription$> {
background: url(<$MTBlogURL$><$MTCategoryDescription$>.jpg) no-repeat left top;
}
</mt:Categories>
追加後、スタイルシートの再構築を行ないます。これでカテゴリ別の背景画像用のセレクタが出来上がります。冒頭の例では次のようになります。
.img_diary {
background: url(http://user-domain/diary.jpg) no-repeat left top;
}
.img_travel {
background: url(http://user-domain/travel.jpg) no-repeat left top;
}
.img_hobby {
background: url(http://user-domain/hobby.jpg) no-repeat left top;
}
4.テンプレートの修正
3項で設定した背景画像用のセレクタを、各テンプレートのブログ記事部分に出力する設定を行ないます。設定内容はテンプレートによって微妙に異なるため、やや分かりにくいかもしれませんが次の表を参考にしてください。
| メインページ | カテゴリ アーカイブ | 月別 アーカイブ | ブログ記事 アーカイブ | |
|---|---|---|---|---|
| デフォルトテンプレート | ① | ① | ① | ② |
| 小粋空間テンプレート | ① | ① | ① | ③ |
| その他 (テンプレート別に設定) | ④ | ⑤ | ⑥ | ⑦ |
- ①「ブログ記事の概要」テンプレートモジュールを修正
- ②「ブログ記事」アーカイブテンンプレートを修正
- ③「ブログ記事の詳細」テンプレートモジュールを修正
- ④「メインページ」インデックステンプレートを修正
- ⑤カテゴリアーカイブテンプレートを修正
- ⑥月別アーカイブテンプレートを修正
- ⑦ブログ記事アーカイブテンプレートを修正
表の見方は、例えば、「既定のブログ」を使っていて、メインページ・カテゴリアーカイブ・月別アーカイブのブログ記事の背景画像を変更したい場合は、「ブログ記事の概要」テンプレートモジュールを修正する(=①の修正を行う)、という具合になります。
以下、①~⑦の番号別に修正内容を示します。
①:「ブログ記事の概要」テンプレートモジュールの修正
メインページ・カテゴリアーカイブ・月別アーカイブで、ブログ記事の表示に「ブログ記事の概要」テンプレートモジュールを利用している場合、ページによって処理を振り分ける必要があるため、次のサブテンプレートを使用します。このサブテンプレートは「ブログ記事の概要」テンプレートモジュールの背景画像を表示したい div 要素の開始タグに適用してください(改行はすべて除去してください)。
<div
<mt:if name="category_archive">
<mt:if tag="CategoryDescription">
class="img_<mt:CategoryDescription />"
</mt:if>
<mt:else>
<mt:setVar name="flag" value="0" />
<mt:EntryCategories><mt:unless name="flag">
<mt:if tag="CategoryDescription"> class="img_<$MTCategoryDescription$>"</mt:if>
<mt:setVar name="flag" value="1" />
</mt:unless>
</mt:EntryCategories>
</mt:if>>
最初の MTIf タグブロック内でカテゴリアーカイブの場合の処理を記述し、MTElse タグブロック内でカテゴリアーカイブ以外の処理を記述しています。
MTIf タグブロック内、つまりカテゴリアーカイブでは、表示するカテゴリが決まっているので、MTCategoryDescription タグをそのまま class 属性値に適用しています。なお、2つめのMTIf タグは tag モディファイアで MTCategoryDescription を判定し、カテゴリの説明が設定されている場合のみ、MTCategoryDescription タグを出力するようにしています。
MTElse タグブロック内、つまりメインページや月別アーカイブ・ブログ記事アーカイブでは、まず MTEntryCategories タグでブログ記事のカテゴリ一覧を処理し、一番最初に処理されるカテゴリ(メインカテゴリ)について MTCategoryDescription タグを class 属性値に適用しています。
なお、ブログ記事に複数のカテゴリを設定していると、class 属性値に複数のMTCategoryDescription タグの内容を設定してしまうため、変数 flag を使用し、変数flag の値が0のときだけ、MTCategoryDescription タグを出力するようにしています。
①で div 要素に既存の class 属性値を設定している場合
①で、適用したい div 要素に他の class 属性(ここでは hoge)をすでに設定している場合は、次の内容に書き換えます。hoge の部分は設定している値に書き換えてください。
<div class="hoge
<mt:if name="category_archive">
<mt:if tag="CategoryDescription">
img_<mt:CategoryDescription />
</mt:if>
<mt:else>
<mt:setVar name="flag" value="0" />
<mt:EntryCategories><mt:unless name="flag">
<mt:if tag="CategoryDescription"> img_<$MTCategoryDescription$></mt:if>
<mt:setVar name="flag" value="1" />
</mt:unless>
</mt:EntryCategories>
</mt:if>">
②③④⑥⑦の場合の修正
②③④⑥⑦は、①のように処理を振り分ける必要がないケースです。表に示したテンプレートにある div 要素の開始タグを、次の内容に入れ替えてください。改行はすべて除去してください。
<mt:setVar name="flag" value="0" />
<div
<mt:EntryCategories>
<mt:unless name="flag">
<mt:if tag="CategoryDescription"> class="img_<mt:CategoryDescription />"</mt:if>
<mt:setVar name="flag" value="1" />
</mt:unless>
</mt:EntryCategories>>
処理の内容は、①の MTElse タグブロックと同じです。
②③④⑥⑦で div 要素に既存の class 属性値を設定している場合
②③④⑥⑦で、適用したい div 要素に他の class 属性(ここでは hoge)をすでに設定している場合は、次の内容に書き換えます。hoge の部分は設定している値に書き換えてください。
<mt:setVar name="flag" value="0" />
<div class="hoge
<mt:EntryCategories>
<mt:unless name="flag">
<mt:if tag="CategoryDescription"> img_<mt:CategoryDescription /></mt:if>
<mt:setVar name="flag" value="1" />
</mt:unless>
</mt:EntryCategories>">
⑤:カテゴリアーカイブテンプレートの修正
カテゴリアーカイブテンプレートを直接修正する場合、選ばれるカテゴリが一意に決まっているので、修正内容は一番シンプルです。
<div<mt:if tag="CategoryDescription"> class="img_<mt:CategoryDescription />"</mt:if>>
</div>
処理の内容は、①の MTIf タグブロックと同じです。
⑤で div 要素に既存の class 属性値を設定している場合
適用したい div 要素に他の class 属性(ここでは hoge)をすでに設定している場合は、次の内容に書き換えます。hoge の部分は設定している値に書き換えてください。
<div class="hoge<mt:if tag="CategoryDescription"> img_<mt:CategoryDescription /></mt:if>">
</div>
5.設定例
4項までで、カスタマイズは完了ですが、「一体どの div 要素に設定すればいいの?」という疑問があると思うので、「既定のブログ」のメインページを例に、具体的な設定位置と、設定前後のキャプチャを掲載します。
ブログ記事の概要(変更前)
<$mt:EntryTrackbackData$>
<div id="entry-<$mt:EntryID$>" class="entry-asset asset hentry">
<div class="asset-header">
...後略...
ブログ記事の概要(変更後:青色が追加部分)
<$mt:EntryTrackbackData$>
<div id="entry-<$mt:EntryID$>" class="entry-asset asset hentry<mt:if name="category_archive"><mt:if tag="CategoryDescription"> img_<mt:CategoryDescription /></mt:if><mt:else><mt:setVar name="flag" value="0" /><mt:EntryCategories><mt:unless name="flag"><mt:if tag="CategoryDescription"> img_<$MTCategoryDescription$></mt:if><mt:setVar name="flag" value="1" /></mt:unless></mt:EntryCategories></mt:if>">
<div class="asset-header">
...後略...
メインページ(変更前)
![]()
メインページ(変更後)
![]()
以上です。元々の設定内容は immovabletype さんのブログでまとめられています。
2009.11.18
ファイル名およびクラス名の対応が誤っていたので修正しました。
親カテゴリーアーカイブに表示したサブカテゴリーのブログ記事にサブカテゴリー名を表示する
Movable Type の親カテゴリーアーカイブに表示したサブカテゴリーのブログ記事に、サブカテゴリー名を表示するカスタマイズです。「親カテゴリー名しか表示できません」というご質問を頂きましたので、本エントリーで紹介致します。
1.完成例
下のサンプルは、「days」という親カテゴリーアーカイブに、「days」カテゴリーのブログ記事と、そのサブカテゴリの「food」カテゴリーのブログ記事を表示したものです。
「food」カテゴリーのブログ記事「今日の晩ごはん」のカテゴリー名は「food」、「days」カテゴリーのブログ記事「ブログ始めました」のカテゴリー名は「days」になっています。
カテゴリー名にリンクがない場合

カテゴリー名にリンクがある場合

ちなみに、親カテゴリーアーカイブにサブカテゴリーのブログ記事を表示させるには、MTEntries タグの代わりに、MTEntriesWithSubCategories タグを利用しますが、詳細は下記の記事を参照願います。
2.カスタマイズ
冒頭の画面の位置にカテゴリを表示するには、ブログ管理画面の「デザイン」→「テンプレート」をクリックし、「ブログ記事の概要」をクリックして、以下の青色部分を追加します。
2.1 リンクなしのカテゴリー名を表示する場合
サブカテゴリに属するブログ記事のプライマリカテゴリを表示するには、MTEntryCategory を利用します。MTCategoryLabel では親カテゴリーのカテゴリー名が表示されてしまうので気をつけましょう。
...前略...
<div class="asset-meta">
<span class="byline">
<mt:If tag="EntryAuthorDisplayName">
<span class="vcard author"><$mt:EntryAuthorLink show_hcard="1"$></span> (<abbr class="published" title="<$mt:EntryDate format_name="iso8601"$>"><$mt:EntryDate format="%x %X"$></abbr>)
<mt:Else>
<abbr class="published" title="<$mt:EntryDate format_name="iso8601"$>"><$mt:EntryDate format="%x %X"$></abbr>
</mt:If>
</span>
<span class="separator">|</span> <mt:EntryCategory />
<mt:Unless name="hide_counts" eq="1">
<mt:IfCommentsActive><span class="separator">|</span> <a href="<$mt:EntryPermalink$>#comments"><$mt:EntryCommentCount singular="コメント(1)" plural="コメント(#)" none="コメント(0)"$></a></mt:IfCommentsActive>
<mt:IfPingsActive><span class="separator">|</span> <a href="<$mt:EntryPermalink$>#trackbacks"><$mt:EntryTrackbackCount singular="トラックバック(1)" plural="トラックバック(#)" none="トラックバック(0)"$></a></mt:IfPingsActive>
</mt:Unless>
</div>
...後略...
2.2 カテゴリーアーカイブへのリンクつきのカテゴリー名を表示する場合
カテゴリーアーカイブへのリンクつきのカテゴリー名を表示するには、さらに制御タグと MTCategoryArchiveLink タグ、MTCategoryLabel タグを組み合わせます。
...前略...
<div class="asset-meta">
<span class="byline">
<mt:If tag="EntryAuthorDisplayName">
<span class="vcard author"><$mt:EntryAuthorLink show_hcard="1"$></span> (<abbr class="published" title="<$mt:EntryDate format_name="iso8601"$>"><$mt:EntryDate format="%x %X"$></abbr>)
<mt:Else>
<abbr class="published" title="<$mt:EntryDate format_name="iso8601"$>"><$mt:EntryDate format="%x %X"$></abbr>
</mt:If>
</span>
<span class="separator">|</span>
<mt:EntryCategory setvar="category" />
<MTEntryCategories><mt:If tag="CategoryLabel" eq="$category"><a href="<$MTCategoryArchiveLink$>"></mt:If><$MTCategoryLabel$></a></MTEntryCategories>
<mt:Unless name="hide_counts" eq="1">
<mt:Unless name="hide_counts" eq="1">
<mt:IfCommentsActive><span class="separator">|</span> <a href="<$mt:EntryPermalink$>#comments"><$mt:EntryCommentCount singular="コメント(1)" plural="コメント(#)" none="コメント(0)"$></a></mt:IfCommentsActive>
<mt:IfPingsActive><span class="separator">|</span> <a href="<$mt:EntryPermalink$>#trackbacks"><$mt:EntryTrackbackCount singular="トラックバック(1)" plural="トラックバック(#)" none="トラックバック(0)"$></a></mt:IfPingsActive>
</mt:Unless>
</div>
...後略...
ブログ記事のない親カテゴリーに子カテゴリーのブログ記事を表示する(Movable Type 4.25~)
ブログ記事のない親カテゴリーに子カテゴリーを表示する方法です。
下の画像は、ブログ記事が1件も投稿されていない「日記」カテゴリーのアーカイブページの状態です。ブログ記事は何も表示されておらず、メインページとアーカイブのリンクのみが表示されています。

カテゴリーアーカイブ一覧は次のようになっています。

この「日記」カテゴリーには子カテゴリーとして「お知らせ」「イベント」があり、テンプレートをカスタマイズすることで、次のように子カテゴリーのブログ記事を表示できるようになります。

カテゴリーアーカイブ一覧も次のようにリンクを表示し、親カテゴリー名の横に、子カテゴリーのブログ記事数を表示します。

これを初めてご覧になった方は特段たいした機能ではないように思われますが、Movable Type ではこれまで、この「ブログ記事のない親カテゴリーに子カテゴリーのブログ記事を表示する」という機能がありませんでした(厳密には一時期ありました)。
以下、これまでの経緯とカスタマイズについて紹介します。
1.概要とこれまでのバージョンでの動作
親カテゴリーのアーカイブページに子カテゴリーのブログ記事を表示するには、MTEntries タグの代わりに MTEntriesWithSubCategories タグを利用します。
しかし、Movable Type 3 の時代には、ブログ記事のない親カテゴリーのアーカイブページに MTEntriesWithSubCategories タグを利用しても子カテゴリーを表示することができず、「エントリーのない親カテゴリーに子カテゴリーを表示する」という記事を書きました。記事は、親カテゴリーにダミーのブログ記事を作り、その記事は MTIfCategory タグで表示しないようにカスタマイズするといった内容です。
その後、バージョン 4.1 で、ブログ記事のない親カテゴリーのアーカイブページに子カテゴリーを表示することができるようになりました(関連記事:MTEntriesWithSubCategories タグの不具合などについて)。
しかし、バージョン 4.2 になってから再び表示することができなくなったのですが、4.25 から動作するようになりました。確認したところ、4.2 以降では、MTEntriesWithSubCategories タグの有無にかかわらず、ブログ記事のない親カテゴリーについては、冒頭の画像のように空のアーカイブページが生成されます。
ということで、Movable Type 4.25 以降では、MTEntriesWithSubCategories タグを利用することで、ブログ記事のない親カテゴリーのアーカイブページでも、自然体で子カテゴリーのブログ記事を表示できるようになりました。
2.ブログ記事リストの変更
デフォルトテンプレートの場合、ブログ管理画面の「デザイン」→「テンプレート」→「カテゴリ別ブログ記事リスト」をクリックし、テンプレートにある MTEntries タグを MTEntriesWithSubCategories タグに書き換えます。
変更前
...前略...
<mt:Entries limit="$limit">
<mt:Ignore><!-- Use the Entry Summary module for each entry published on this page --></mt:Ignore>
<$mt:Include module="ブログ記事の概要"$>
</mt:Entries>
...後略...
変更後
...前略...
<mt:EntriesWithSubCategories limit="$limit">
<mt:Ignore><!-- Use the Entry Summary module for each entry published on this page --></mt:Ignore>
<$mt:Include module="ブログ記事の概要"$>
</mt:EntriesWithSubCategories>
...後略...
当ブログの配布テンプレートをご利用の場合は、ブログ管理画面の「デザイン」→「テンプレート」→「ブログ記事リスト」をクリックし、テンプレートにある MTEntries タグを MTEntriesWithSubCategories タグに書き換えます。
変更前
...前略...
<mt:if name="datebased_archive">
<mt:entries>
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
<mt:else>
<mt:entries limit="auto">
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
</mt:if>
...後略...
変更後
...前略...
<mt:if name="datebased_archive">
<mt:entries>
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
<mt:else>
<mt:entriesWithSubCategories limit="auto">
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entriesWithSubCategories>
</mt:if>
...後略...
3.カテゴリアーカイブウィジェットの変更
2項の変更だけではカテゴリーリストに親カテゴリアーカイブページへのリンクが表示されません。理由は、デフォルトのサブテンプレートは MTCategoryCount タグを判定し、処理中のカテゴリーにブログ記事がない場合はリンクを表示しない制御を行なっているためです。
ここでは、制御タグを利用して、子カテゴリーのブログ記事がある場合はリンクを表示するようにします。また、カテゴリ名の横に子カテゴリのブログ記事も含めたブログ記事数を表示する変更も行います。
デフォルトテンプレートの場合、ブログ記事の「デザイン」→「ウィジェット」→「カテゴリアーカイブ」をクリックし、テンプレートの内容を次のように変更します(青色部分は追加、赤色部分は変更)。
<mt:IfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
<h3 class="widget-header">カテゴリ</h3>
<div class="widget-content">
<mt:TopLevelCategories>
<mt:SubCatIsFirst>
<ul>
</mt:SubCatIsFirst>
<mt:EntriesWithSubCategories>
<mt:EntriesFooter>
<mt:GetVar name="__counter__" setvar="entry_count" />
</mt:EntriesFooter>
</mt:EntriesWithSubCategories>
<mt:If name="entry_count">
<li><a href="<$mt:CategoryArchiveLink$>"<mt:If tag="CategoryDescription"> title="<$mt:CategoryDescription remove_html="1" encode_html="1"$>"</mt:If>><$mt:CategoryLabel$> (<mt:If tag="CategoryCount"><$mt:CategoryCount$><mt:Else><mt:GetVar name="entry_count" /></mt:If>)</a>
<mt:Else>
<li><$mt:CategoryLabel$>
</mt:If>
<$mt:SubCatsRecurse$>
</li>
<mt:SubCatIsLast>
</ul>
</mt:SubCatIsLast>
</mt:TopLevelCategories>
</div>
</div>
</mt:IfArchiveTypeEnabled>
当ブログの配布テンプレートをご利用の場合は、ブログ記事の「デザイン」→「ウィジェット」→「カテゴリアーカイブ」をクリックし、テンプレートの内容を次のように変更します(青色部分は追加、赤色部分は変更)。
<mt:ifArchiveTypeEnabled archive_type="Category">
<dt class="sidetitle">
Categories
</dt>
<dd class="side" id="categories">
<mt:topLevelCategories>
<mt:subCatIsFirst>
<ul>
</mt:subCatIsFirst>
<mt:entriesWithSubCategories>
<mt:entriesFooter>
<mt:getVar name="__counter__" setvar="entry_count" />
</mt:entriesFooter>
</mt:entriesWithSubCategories>
<mt:if name="entry_count">
<li><a href="<mt:categoryArchiveLink />" title="<mt:categoryDescription />"><mt:categoryLabel /></a> [<mt:if tag="CategoryCount"><mt:categoryCount /><mt:else><mt:getVar name="entry_count" /></mt:If>]
<mt:else>
<li><mt:categoryLabel />
</mt:if>
<mt:subCatsRecurse />
</li>
<mt:subCatIsLast>
</ul>
</mt:subCatIsLast>
</mt:topLevelCategories>
</dd>
</mt:ifArchiveTypeEnabled>
4.子カテゴリーのブログ記事投稿時に親カテゴリーアーカイブを再構築する
バージョン 4.261 で確認したところ、子カテゴリーのブログ記事投稿時に親カテゴリーアーカイブは再構築されません。したがって、下記のプラグインを併用されることをおすすめします。
カテゴリーアーカイブページの最後に「続きを読む」のリンクを表示する
カテゴリーアーカイブページで表示するブログ記事数を制限している場合、ページの最後に「続きを読む」のリンクを表示し、そのリンクをクリックすれば、月別カテゴリーアーカイブページにジャンプするカスタマイズです。
例えば、カテゴリーアーカイブページで新着5件のブログ記事を表示している場合、「続きを読む」のリンクをクリックすれば、新着6件目のブログ記事のある月別カテゴリーアーカイブページの該当記事の位置までジャンプします。
図にすると次のような感じです。

1.カスタマイズ
当サイトの配布テンプレートの場合、「ブログ記事リスト」を次のように変更します。他のテンプレートでも構造はそれほど大きく変わらないので利用できると思います。
変更前
...前略...
<mt:if name="datebased_archive">
<mt:entries>
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
<mt:else>
<mt:entries limit="auto">
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
</mt:if>
</div>
</div>
...後略...
変更後
...前略...
<mt:if name="datebased_archive">
<mt:entries>
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
<mt:else>
<mt:entries lastn="6">
<mt:unless name="__last__">
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
<mt:else>
<mt:entryDate format="/%Y/%m/" setvar="year_month" />
<mt:entryID setvar="entry_id" pad="1" />
</mt:unless>
</mt:entries>
</mt:if>
<mt:if name="archive_class" eq="category-archive">
<mt:ifArchiveTypeEnabled archive_type="Category-Monthly">
<div class="content-nav">
<a href="<mt:blogURL /><mt:subCategoryPath separator="-" /><mt:getVar name="year_month" />#a<mt:getVar name="entry_id" />">続きを読む</a>
</div>
</mt:ifArchiveTypeEnabled>
</mt:if>
</div>
</div>
limit モディファイアを lastn モディファイアに変更し、lastn モディファイアの値に、「カテゴリーアーカイブページに表示したい件数+1」を設定します(ここでは「6」)。
最後の1件はカテゴリーアーカイブページに表示せず、ブログ記事情報(投稿月日とブログ記事ID)だけを取得し、変数に保持します。
そのあと、カテゴリーアーカイブで、月別カテゴリーアーカイブのアーカイブマッピングがある場合
のみ、ブログURL・サブカテゴリーパスと変数の情報を使って、月別カテゴリーページの該当記事へのアンカーを生成します。
2.注意事項
余談です。
元テンプレートが limit モディファイア「auto」を使っているので、当初は次のように、limit モディファイアと unique モディファイアを組み合わせ、新着1件のブログ記事情報を取得しようと思いましたが、正常に動作しません(情報が取得できず)でした。
...前略...
<mt:if name="datebased_archive">
<mt:entries>
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
<mt:else>
<mt:entries limit="auto">
<mt:entryTrackbackData />
<mt:include module="ブログ記事の概要" />
</mt:entries>
</mt:if>
<mt:if name="archive_class" eq="category-archive">
<mt:ifArchiveTypeEnabled archive_type="Category-Monthly">
<mt:entries unique="1" limit="1">
<mt:entryDate format="/%Y/%m/" setvar="year_month" />
<mt:entryID setvar="entry_id" pad="1" />
</mt:entries>
<div class="content-nav">
<a href="<mt:blogURL /><mt:subCategoryPath separator="-" /><mt:getVar name="year_month" />#a<mt:getVar name="entry_id" />">続きを読む</a>
</div>
</mt:ifArchiveTypeEnabled>
</mt:if>
</div>
</div>
...後略...
3.関連記事
Movable Type のカテゴリーリストで特定のカテゴリーを非表示にする
Movable Type でカテゴリー一覧を表示するときに、特定のカテゴリーを非表示にするカスタマイズです。
1.基本
特定のカテゴリーを非表示にするには、次のように MTUnless タグと like モディファイアを組合わせて使用します。この例では、「cat1」「cat2」「cat3」のカテゴリーを、カテゴリー一覧に表示しません。
<mt:categories>
<mt:unless tag="CategoryLabel" like="cat1|cat2|cat3">
カテゴリーの処理
</mt:unless>
</mt:categories>
カテゴリーのフィルタリングでは、FilterCategories プラグインが有名で、上記のような書式でフィルタリングすることができますが、カテゴリー名が重複している場合は適正にフィルタリングできないという問題があります。
2.同名のカテゴリーが存在する場合
同名のカテゴリーが存在する場合は、tagモディファイア・like モディファイアとカテゴリーIDを組合わせてフィルタリングします。
<mt:categories>
<mt:unless tag="CategoryID" like="^3$||^5$|^7$">
カテゴリーの処理
</mt:unless>
</mt:categories>
likeモディファイアを使用する場合の注意点ですが、前述のサブテンプレートを、
<mt:categories>
<mt:unless tag="CategoryID" like="3|5|7">
カテゴリーの処理
</mt:unless>
</mt:categories>
と書くと、カテゴリーIDの番号が「3」「5」「7」を含むものすべてのID(「13」とか)が対象になってしまうため、正規表現の「^」と「$」を付与しています。
3.似たようなカテゴリー名が存在する場合
1項のようにカテゴリー名で判定するときも、冒頭の例では「cat1-1」なども含まれてしまうので、正規表現の「$」を付与して、
<mt:categories>
<mt:unless tag="CategoryLabel" like="cat1$|cat2$|cat3$">
カテゴリーの処理
</mt:unless>
</mt:categories>
とすると良いでしょう。
dTree カテゴリーリストにブログ記事数を表示する
Movable Type に表示する dTree カテゴリーリストに、ブログ記事数を表示するカスタマイズです。このカスタマイズを行なえば、dTree のカテゴリーリストにブログ記事が公開されているカテゴリーにブログ記事数を表示します。

ご要望を頂きましたので、本エントリーにて紹介致します。なお、このカスタマイズは「dTree サブカテゴリーリスト + 新着表示 for Movable Type」のカスタマイズを元にしています。
以下、サブテンプレートのみ示します。
「dTree サブカテゴリーリスト + 新着表示 for Movable Type」のひとつめのリストは、次の内容に変更してください。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<mt:setVar name="cat_number" value="1" />
<mt:setVar name="level" value="1" />
<mt:topLevelCategories>
<mt:setVar name="cat_number" op="++" />
<mt:setVar name="tree[$level]" value="$cat_number" />
<mt:if name="level" eq="1">
d.add(<mt:getVar name="cat_number" op="--" />, 0,'<mt:categoryLabel escape="html" /><mt:if tag="CategoryCount"> [<$mt:CategoryCount$>]</mt:if> <span class="new"><mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries></span>','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>');
<mt:else>
d.add(<mt:getVar name="cat_number" op="--" />, <mt:setVar name="tmp" value="$level" /><mt:setVar name="tmp" op="--" /><mt:getVar name="tree[$tmp]" op="--" />,'<mt:categoryLabel escape="html" /><mt:if tag="CategoryCount"> [<$mt:CategoryCount$>]</mt:if> <span class="new"><mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries></span>','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>');
</mt:if>
<mt:setVar name="level" op="++" />
<mt:subCatsRecurse />
<mt:setVar name="level" op="--" />
</mt:topLevelCategories>
document.write(d);
</script>
</div>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
<script type="text/javascript">
<!--
// passage time
var pass = 24;
// display content
var content = 'New!!';
var currentDate = new Date();
var spans = document.getElementsByTagName('span');
for (i = 0; i < spans.length; i++) {
if (spans[i].getAttribute('class') == 'new' ||
spans[i].getAttribute('className') == 'new') {
if (spans[i].childNodes[0]) {
time = spans[i].childNodes[0].nodeValue.split(":");
var entryDate = new Date(time[0], time[1]-1, time[2], time[3], time[4], time[5]);
var now = (entryDate.getTime() - currentDate.getTime())/(60*60*1000);
now = Math.ceil(now);
if(-now <= pass){
spans[i].innerHTML = content;
spans[i].style.display = 'inline';
}
}
}
}
//-->
</script>
「dTree サブカテゴリーリスト + 新着表示 for Movable Type」のふたつめのリストは、次の内容に変更してください。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<mt:setVar name="cat_number" value="1" />
<mt:setVar name="level" value="1" />
<mt:topLevelCategories>
<mt:setVar name="cat_number" op="++" />
<mt:setVar name="tree[$level]" value="$cat_number" />
<mt:if name="level" eq="1">
d.add(<mt:getVar name="cat_number" op="--" />, 0,'<mt:categoryLabel escape="html" /><mt:if tag="CategoryCount"> [<$mt:CategoryCount$>]</mt:if>','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>','<mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries>');
<mt:else>
d.add(<mt:getVar name="cat_number" op="--" />, <mt:setVar name="tmp" value="$level" /><mt:setVar name="tmp" op="--" /><mt:getVar name="tree[$tmp]" op="--" />,'<mt:categoryLabel escape="html" /><mt:if tag="CategoryCount"> [<$mt:CategoryCount$>]</mt:if> ','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>','<mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries>');
</mt:if>
<mt:setVar name="level" op="++" />
<mt:subCatsRecurse />
<mt:setVar name="level" op="--" />
</mt:topLevelCategories>
document.write(d);
</script>
</div>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
<script type="text/javascript">
<!--
// passage time
var pass = 24;
// display content
var content = 'New!!';
var currentDate = new Date();
var spans = document.getElementsByTagName('span');
for (i = 0; i < spans.length; i++) {
if (spans[i].getAttribute('class') == 'new' ||
spans[i].getAttribute('className') == 'new') {
if (spans[i].childNodes[0]) {
time = spans[i].childNodes[0].nodeValue.split(":");
var entryDate = new Date(time[0], time[1]-1, time[2], time[3], time[4], time[5]);
var now = (entryDate.getTime() - currentDate.getTime())/(60*60*1000);
now = Math.ceil(now);
if(-now <= pass){
spans[i].innerHTML = content;
spans[i].style.display = 'inline';
}
}
}
}
//-->
</script>
dTree サブカテゴリーリスト + 新着表示 for Movable Type
「dTree」というエクスプローラー風のツリー表示スクリプトを利用した、Movable Type のサブカテゴリーリストのツリー化カスタマイズを、下記のエントリーで以前紹介しました。
今回は、ご要望を頂き、dTree サブカテゴリーリストに新着表示を組み合わせてみました。このカスタマイズを行なえば、次のように新着ブログ記事のあるカテゴリーに対し「New!」マークを表示します。

なお、このカスタマイズでは、dTree の処理上、新着マークにアンカーがついてしまいます。

そこで、JavaScript を改変して、新着マークにアンカーを表示しない方法も併せて紹介します。

なお、以下のカスタマイズを行なう前に「dTree によるサブカテゴリーリスト for Movable Type」の4項までの作業を事前に行なってください。
また、新着表示についての詳細は「新着エントリーのあるカテゴリーに New マークをつける」を参照してください(リンク先のカスタマイズを行なう必要はありません)。
1.新着マークにアンカーをついたままにする
サブカテゴリーリストに次の内容を適用してください。これで再構築すれば新着マークが表示されます。デフォルトの設定では24時間以内の投稿に新着マークを表示します。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<mt:setVar name="cat_number" value="1" />
<mt:setVar name="level" value="1" />
<mt:topLevelCategories>
<mt:setVar name="cat_number" op="++" />
<mt:setVar name="tree[$level]" value="$cat_number" />
<mt:if name="level" eq="1">
d.add(<mt:getVar name="cat_number" op="--" />, 0,'<mt:categoryLabel escape="html" /> <span class="new"><mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries></span>','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>');
<mt:else>
d.add(<mt:getVar name="cat_number" op="--" />, <mt:setVar name="tmp" value="$level" /><mt:setVar name="tmp" op="--" /><mt:getVar name="tree[$tmp]" op="--" />,'<mt:categoryLabel escape="html" /> <span class="new"><mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries></span>','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>');
</mt:if>
<mt:setVar name="level" op="++" />
<mt:subCatsRecurse />
<mt:setVar name="level" op="--" />
</mt:topLevelCategories>
document.write(d);
</script>
</div>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
<script type="text/javascript">
<!--
// passage time
var pass = 24;
// display content
var content = 'New!!';
var currentDate = new Date();
var spans = document.getElementsByTagName('span');
for (i = 0; i < spans.length; i++) {
if (spans[i].getAttribute('class') == 'new' ||
spans[i].getAttribute('className') == 'new') {
if (spans[i].childNodes[0]) {
time = spans[i].childNodes[0].nodeValue.split(":");
var entryDate = new Date(time[0], time[1]-1, time[2], time[3], time[4], time[5]);
var now = (entryDate.getTime() - currentDate.getTime())/(60*60*1000);
now = Math.ceil(now);
if(-now <= pass){
spans[i].innerHTML = content;
spans[i].style.display = 'inline';
}
}
}
}
//-->
</script>
2.新着マークにアンカーをつけずに表示する
まず、dtree.js に下記のパッチをあてます。「パッチが分からない」とか、うまくいかない場合はこの先を読んでください。
--- dtree.js.bak Tue Jan 06 00:00:25 2009
+++ dtree.js Tue Jan 06 00:00:40 2009
@@ -22,7 +22,7 @@
// Node object
-function Node(id, pid, name, url, title, target, icon, iconOpen, open) {
+function Node(id, pid, name, url, mark, title, target, icon, iconOpen, open) {
this.id = id;
@@ -32,6 +32,8 @@
this.url = url;
+ this.mark = mark;
+
this.title = title;
this.target = target;
@@ -134,9 +136,9 @@
// Adds a new node to the node array
-dTree.prototype.add = function(id, pid, name, url, title, target, icon, iconOpen, open) {
+dTree.prototype.add = function(id, pid, name, url, mark, title, target, icon, iconOpen, open) {
- this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target, icon, iconOpen, open);
+ this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, mark, title, target, icon, iconOpen, open);
};
@@ -285,6 +287,8 @@
str += node.name;
if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';
+
+ if (node.mark) str += '<span class="new">' + node.mark + '</span>';
str += '</div>';
直接 dtree.js をエディタ上で編集する場合は、下記の青色部分を追加してください。
...前略...
// Node object
function Node(id, pid, name, url, mark, title, target, icon, iconOpen, open) {
this.id = id;
this.pid = pid;
this.name = name;
this.url = url;
this.mark = mark;
this.title = title;
...中略...
// Adds a new node to the node array
dTree.prototype.add = function(id, pid, name, url, mark, title, target, icon, iconOpen, open) {
this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, mark, title, target, icon, iconOpen, open);
};
...中略...
// Creates the node icon, url and text
dTree.prototype.node = function(node, nodeId) {
...中略...
str += node.name;
if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';
if (node.mark) str += '<span class="new">' + node.mark + '</span>';
str += '</div>';
if (node._hc) {
...中略...
そして、サブカテゴリーリストに次の内容を適用してください。これで再構築すれば新着マークが表示されます。デフォルトの設定では24時間以内の投稿に新着マークを表示します。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<mt:setVar name="cat_number" value="1" />
<mt:setVar name="level" value="1" />
<mt:topLevelCategories>
<mt:setVar name="cat_number" op="++" />
<mt:setVar name="tree[$level]" value="$cat_number" />
<mt:if name="level" eq="1">
d.add(<mt:getVar name="cat_number" op="--" />, 0,'<mt:categoryLabel escape="html" />','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>','<mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries>');
<mt:else>
d.add(<mt:getVar name="cat_number" op="--" />, <mt:setVar name="tmp" value="$level" /><mt:setVar name="tmp" op="--" /><mt:getVar name="tree[$tmp]" op="--" />,'<mt:categoryLabel escape="html" />','<mt:if tag="CategoryCount"><mt:categoryArchiveLink /><mt:else>javascript: void(0);</mt:if>','<mt:entries lastn="1"><mt:entryDate format="%Y:%m:%d:%H:%M:%S" /></mt:entries>');
</mt:if>
<mt:setVar name="level" op="++" />
<mt:subCatsRecurse />
<mt:setVar name="level" op="--" />
</mt:topLevelCategories>
document.write(d);
</script>
</div>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
<script type="text/javascript">
<!--
// passage time
var pass = 24;
// display content
var content = 'New!!';
var currentDate = new Date();
var spans = document.getElementsByTagName('span');
for (i = 0; i < spans.length; i++) {
if (spans[i].getAttribute('class') == 'new' ||
spans[i].getAttribute('className') == 'new') {
if (spans[i].childNodes[0]) {
time = spans[i].childNodes[0].nodeValue.split(":");
var entryDate = new Date(time[0], time[1]-1, time[2], time[3], time[4], time[5]);
var now = (entryDate.getTime() - currentDate.getTime())/(60*60*1000);
now = Math.ceil(now);
if(-now <= pass){
spans[i].innerHTML = content;
spans[i].style.display = 'inline';
}
}
}
}
//-->
</script>
特定のカテゴリーに属するブログ記事一覧を表示する(改)
Movable Type で、特定のカテゴリーに属するブログ記事一覧を表示するカスタマイズです。
MTEntries タグに category モディファイアを適用するだけでは適正に取得できないケースを、テンプレートタグのカスタマイズによって実現します。
1.MTEntries タグの category/categories モディファイアについて
MTEntries タグには category/categories モディファイアがあり、モディファイアに指定したカテゴリーのブログ記事を取得できます。
ただし、次のようなカテゴリーで、トップカテゴリーの「お知らせ」カテゴリーだけに属するブログ記事を抽出したいと仮定します。
・お知らせ
・イベントA
└ お知らせ
・イベントB
└ お知らせ
この場合、次のテンプレートタグでは、イベントAやイベントBの「お知らせ」カテゴリーに属するブログ記事も対象になってしまいます。
<mt:entries category="お知らせ">
...中略...
</mt:entries>
具体例として、前述の各「お知らせ」カテゴリーに次のブログ記事が属しているとします(●印)。
・お知らせ
●モバイルサイトオープン
●業務提携に関するお知らせ
・イベントA
└ お知らせ
●ソリューションセミナー
●Movable Type 入門セミナー
・イベントB
└ お知らせ
●オフィシャルサイトオープン
●シンポジウム2008
●ホームページリニューアル
サイドバーに表示する「最近のブログ記事」の MTEntries タグに category モディファイアを適用して「お知らせ」を設定すると、次のように表示されます。

余談ですが、イベントAの「お知らせ」カテゴリーに属するブログ記事を抽出したい場合、次のように指定しても、適正に取得できないようです。
<mt:entries category="イベントA/お知らせ">
...中略...
</mt:entries>
2.動作確認バージョン
このカスタマイズは次のバージョンで確認しています。
- Movable Type 4.2x(~4.23)
3.カスタマイズ
サイドバーに設置する場合、次のサブテンプレートを利用してください。
デフォルトテンプレート用
<mt:setVar name="category" value="取得したいブログ記事のカテゴリ名" />
<mt:if tag="blogEntryCount">
<div class="widget-recent-entries widget-archives widget">
<h3 class="widget-header">最近のブログ記事</h3>
<div class="widget-content">
<ul>
</mt:if>
<mt:entries category="$category">
<mt:setVar name="undef(list)" />
<mt:setVar name="count" value="0" />
<mt:entryCategories>
<mt:setVarBlock name="list" index="$count"><mt:parentCategories glue="/"><mt:categoryLabel /></mt:parentCategories></mt:setVarBlock>
<mt:setVar name="count" op="++" />
</mt:entryCategories>
<mt:setVar name="category_flag" value="0" />
<mt:loop name="list">
<mt:if name="__value__" eq="$category">
<mt:setVar name="category_flag" value="1" />
</mt:if>
</mt:loop>
<mt:if name="category_flag">
<li><a href="<mt:entryPermalink escape="html" valid_html="1">"><mt:entryTitle /></a></li>
</mt:if>
</mt:entries>
<mt:if tag="blogEntryCount">
</ul>
</div>
</div>
</mt:if>
小粋空間テンプレート用
<mt:setVar name="category" value="取得したいブログ記事のカテゴリ名" />
<mt:if tag="blogEntryCount">
<dt class="sidetitle">最近のブログ記事</dt>
<dd class="side">
<ul>
</mt:if>
<mt:entries category="$category">
<mt:setVar name="undef(list)" />
<mt:setVar name="count" value="0" />
<mt:entryCategories>
<mt:setVarBlock name="list" index="$count"><mt:parentCategories glue="/"><mt:categoryLabel /></mt:parentCategories></mt:setVarBlock>
<mt:setVar name="count" op="++" />
</mt:entryCategories>
<mt:setVar name="category_flag" value="0" />
<mt:loop name="list">
<mt:if name="__value__" eq="$category">
<mt:setVar name="category_flag" value="1" />
</mt:if>
</mt:loop>
<mt:if name="category_flag">
<li><a href="<mt:entryPermalink escape="html" valid_html="1">"><mt:entryTitle /></a></li>
</mt:if>
</mt:entries>
<mt:if tag="blogEntryCount">
</ul>
</dd>
</mt:if>
このサブテンプレートを利用することで、先のサンプルを次のように表示させることができます。

4.サブテンプレートの解説
上記のサブテンプレートについて、必要な部分のみ抜粋して解説します。
01:<mt:setVar name="category" value="取得したいブログ記事のカテゴリ名" />
02:<mt:if tag="blogEntryCount">
03:<ul>
04:</mt:if>
05:<mt:entries category="$category">
06: <mt:setVar name="undef(list)" />
07: <mt:setVar name="count" value="0" />
08: <mt:entryCategories>
09: <mt:setVarBlock name="list" index="$count"><mt:parentCategories glue="/"><mt:categoryLabel /></mt:parentCategories></mt:setVarBlock>
10: <mt:setVar name="count" op="++" />
11: </mt:entryCategories>
12: <mt:setVar name="category_flag" value="0" />
13: <mt:loop name="list">
14: <mt:if name="__value__" eq="$category">
15: <mt:setVar name="category_flag" value="1" />
16: </mt:if>
17: </mt:loop>
18: <mt:if name="category_flag">
19: <li><a href="<mt:entryPermalink escape="html" valid_html="1">"><mt:entryTitle /></a></li>
20: </mt:if>
21:</mt:entries>
22:<mt:if tag="blogEntryCount">
23:</ul>
24:</mt:if>
1行目の value モディファイアの値(赤色部分)に抽出したいカテゴリー名を設定します。冒頭のカテゴリー一覧から「お知らせ」を抽出したい場合は次のように記述します。
<mt:setVar name="category" value="お知らせ" />
サブカテゴリーを指定したい場合は、カテゴリーの区切り文字を "/" にします。例えば冒頭のカテゴリー一覧からイベントAの「お知らせ」を抽出したい場合は、次のように設定します。
<mt:setVar name="category" value="イベントA/お知らせ" />
2~4行目の MTIf タグで ul 要素の開始タグを出力します。また、22~24行目の MTIf タグで ul 要素の終了タグを出力します。
<mt:if tag="blogEntryCount">
<ul>
</mt:if>
...中略...
<mt:if tag="blogEntryCount">
</ul>
</mt:if>
本来は MTEntries タグ内に MTEntriesHeader タグ・MTEntriesFooter タグを使用して、初回の繰り返しで ul 要素の開始タグ、繰り返しの最後で ul 要素の終了タグを出力するのですが、このサブテンプレートでは MTEntriesFooter タグが正常に動作せず、初回のブログ記事の処理で実行されてしまいます。原因は MTEntries タグの中で色々なテンプレートタグを使っていて、 MTEntriesFooter タグを判定するデータが上書きされてしまっていると推測します。したがってMTEntriesFooter タグは使用せず、MTEntries タグの外側でMTIf タグで ul 要素の終了タグを出力します。それに併せて、MTEntriesHeader タグも使用していない、ということです。
5行目~21行目で MTEntries タグのループがあります。category モディファイアには、1行目で設定した変数 category を設定します。
<mt:entries category="$category">
...中略...
</mt:entries>
6~7行目で利用する変数の初期化を行います。
<mt:setVar name="undef(list)" />
<mt:setVar name="count" value="0" />
配列変数 list は、ブログ記事に属するすべてのカテゴリ名を保持するもので、count は配列変数 list のインデックス用カウンタです。いずれも処理対象のブログ記事が切り替わった時点で初期化します。配列変数 list は初期化しないと、例えば前回の処理でインデックス値 3 まで設定され、今回の処理でインデックス値 2 までしか使われなかったら、前回のインデックス値 3 が処理対象となってしまいます。
なお、undef 関数の場合、MTSetVar タグでも value モディファイアの設定は不要です。
8~11行目で、あるブログ記事が属するすべてのカテゴリーを変数 list に保持します。
<mt:entryCategories>
<mt:setVarBlock name="list" index="$count"><mt:parentCategories glue="/"><mt:categoryLabel /></mt:parentCategories></mt:setVarBlock>
<mt:setVar name="count" op="++" />
</mt:entryCategories>
8行目の MTEntryCategories タグで、ブログ記事が属するすべてのカテゴリー分、繰り返し処理を行います。ブロック内でカテゴリー名を取得しますが、その時、さらに MTParentCategories タグを用いて、処理対象のカテゴリーについて、親カテゴリーからのすべてのカテゴリ名を取得します。親カテゴリーから現在のカテゴリーまでの区切り文字は glue モディファイアを使って "/" を与えます。10行目の MTSetVar タグでは、変数 count の値をインクリメントし、次のカテゴリーの処理のためにインデックス値を更新します。
12~17行目は、設定した配列変数 list に、1行目で設定したカテゴリー名と同じカテゴリー名があることをチェックします。
<mt:setVar name="category_flag" value="0" />
<mt:loop name="list">
<mt:if name="__value__" eq="$category">
<mt:setVar name="category_flag" value="1" />
</mt:if>
</mt:loop>
12行目はチェック処理で利用する変数 flag を初期化します。13~17行目の MTLoop タグで配列変数 list を指定し、14行目で配列変数の値 __value__ と変数 category を比較します。等しければ、変数 flag に 1 を設定します。
18~20行目で変数 flag を判定し、1であれば(=1行目の変数 category に設定したカテゴリーがブログ記事に設定されていれば)ブログ記事タイトルを出力します。
<mt:if name="category_flag">
<li><a href="<mt:entryPermalink escape="html" valid_html="1">"><mt:entryTitle /></a></li>
</mt:if>
ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する(Movable Type 4.2/Movable Type 5対応)
「ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する」の Movable Type 4.2 版のプラグインを公開します。
元記事の内容は Movable Type 4.1 の内容であり、Movable Type 4.2 では前後リンクが正常に表示されない場合があります。
2009.01.05 追記:Movable Type 5.0 で動作することを確認しました。
1.プラグインの概要
下の画面(元記事の再掲)のブログ記事タイトル上にある前後リンクは、分かりにくいですが、同一カテゴリーのブログ記事です。


「ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する」では、元のプラグイン「Previous and next in category」を修正する形で書いてましたが、修正箇所が多いため、プラグインファイルで公開します(ファイル内に元プラグインの著者を掲載しています)。
このプラグインは Movable Type 4.1 / 4.2 / 5.0 で動作することを確認しています。
2.PreviousNextInCategory プラグインのダウンロード
下記の PreviousNextInCategory.zip をクリックして、プラグインアーカイブをダウンロード。
プラグイン開発やサポート等にご支援・ご賛同くださる方からの寄付をお待ち申し上げます。下記の「寄付」のリンクをクリックすると Paypal によるお支払いページにジャンプします。
3.PreviousNextInCategory プラグインのアップロード・インストール
プラグインアーカイブを展開し、中にある PreviousNextInCategory フォルダごと、Movable Type のアプリケーションディレクトリの plugins ディレクトリにアップロード。
システム管理画面のプラグイン一覧で、「PreviousNextInCategory ~」が表示されればインストール完了です。

4.プライマリカテゴリーに属するブログ記事のみを表示する場合
ブログ記事アーカイブの任意の位置に下記のサブテンプレートを設定してください。
<MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink$>">« <$MTEntryTitle$></a> |
</MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink archive_type="Category"$>"><$MTEntryCategory$></a>
<MTEntryNextInCategory>
| <a href="<$MTEntryPermalink$>"><$MTEntryTitle$> »</a>
</MTEntryNextInCategory>
ブログ記事アーカイブを再構築すれば、冒頭のように、同一カテゴリーの前後記事リンクが表示されます。
5.ブログ記事に登録されているすべてのカテゴリーに属するブログ記事を表示する場合
ブログ記事アーカイブの任意の位置に、下記のサブテンプレートを設定してください。
<MTEntryCategories>
<p>
<MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink$>">« <$MTEntryTitle$></a> |
</MTEntryPreviousInCategory>
<a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
<MTEntryNextInCategory>
| <a href="<$MTEntryPermalink$>"><$MTEntryTitle$> »</a>
</MTEntryNextInCategory>
</p>
</MTEntryCategories>
ブログ記事アーカイブを再構築すれば、ブログ記事が属する全カテゴリーの前後記事リンクが表示されます。
6.元プラグインの変更点
一応、元プラグイン PreviousNextInCategory.pl の変更点を掲載しておきます。実際にはこの修正に加えて、ブログ記事が再構築されたときに同一カテゴリーの前後記事を再構築する処理も追加しています。
「ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する」での変更(青色部分を追加)
sub _hdlr_entry_previous_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryPrevious');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $prev = $e->previous(1);
my $res = '';
while ($prev && !$prev->is_in_category($cat)){
$prev = $prev->previous(1);
}
if ($prev) {
my $builder = $ctx->stash('builder');
local $ctx->{__stash}->{entry} = $prev;
local $ctx->{current_timestamp} = $prev->created_on;
my %cond = %$cond;
$cond{EntryIfAllowComments} = $prev->allow_comments;
$cond{EntryIfCommentsOpen} = $prev->allow_comments eq '1';
$cond{EntryIfAllowPings} = $prev->allow_pings;
$cond{EntryIfExtended} = $prev->text_more ? 1 : 0;
my $out = $builder->build($ctx, $ctx->stash('tokens'), \%cond);
return $ctx->error( $builder->errstr ) unless defined $out;
$res .= $out;
}
$res;
}
sub _hdlr_entry_next_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryNext');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $next = $e->next(1);
my $res = '';
while ($next && !$next->is_in_category($cat)){
$next = $next->next(1);
}
if ($next) {
my $builder = $ctx->stash('builder');
local $ctx->{__stash}->{entry} = $next;
local $ctx->{current_timestamp} = $next->created_on;
my %cond = %$cond;
$cond{EntryIfAllowComments} = $next->allow_comments;
$cond{EntryIfCommentsOpen} = $next->allow_comments eq '1';
$cond{EntryIfAllowPings} = $next->allow_pings;
$cond{EntryIfExtended} = $next->text_more ? 1 : 0;
my $out = $builder->build($ctx, $ctx->stash('tokens'), \%cond);
return $ctx->error( $builder->errstr ) unless defined $out;
$res .= $out;
}
$res;
}
4.2 対応の変更(赤色が 4.1 までの追加部分で、青色部分をさらに追加)
sub _hdlr_entry_previous_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryPrevious');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $terms;
$terms->{category_id} = $cat->id;
my $prev = $e->previous(1, $terms);
my $res = '';
while ($prev && !$prev->is_in_category($cat)){
$terms->{category_id} = $cat->id;
$prev = $prev->previous(1, $terms);
}
if ($prev) {
my $builder = $ctx->stash('builder');
local $ctx->{__stash}->{entry} = $prev;
local $ctx->{current_timestamp} = $prev->created_on;
my %cond = %$cond;
$cond{EntryIfAllowComments} = $prev->allow_comments;
$cond{EntryIfCommentsOpen} = $prev->allow_comments eq '1';
$cond{EntryIfAllowPings} = $prev->allow_pings;
$cond{EntryIfExtended} = $prev->text_more ? 1 : 0;
my $out = $builder->build($ctx, $ctx->stash('tokens'), \%cond);
return $ctx->error( $builder->errstr ) unless defined $out;
$res .= $out;
}
$res;
}
sub _hdlr_entry_next_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryNext');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $terms;
$terms->{category_id} = $cat->id;
my $next = $e->next(1, $terms);
my $res = '';
while ($next && !$next->is_in_category($cat)){
$terms->{category_id} = $cat->id;
$next = $next->next(1, $terms);
}
if ($next) {
my $builder = $ctx->stash('builder');
local $ctx->{__stash}->{entry} = $next;
local $ctx->{current_timestamp} = $next->created_on;
my %cond = %$cond;
$cond{EntryIfAllowComments} = $next->allow_comments;
$cond{EntryIfCommentsOpen} = $next->allow_comments eq '1';
$cond{EntryIfAllowPings} = $next->allow_pings;
$cond{EntryIfExtended} = $next->text_more ? 1 : 0;
my $out = $builder->build($ctx, $ctx->stash('tokens'), \%cond);
return $ctx->error( $builder->errstr ) unless defined $out;
$res .= $out;
}
$res;
}
カテゴリークラウド for Movable Type
Movable Type のカテゴリーをタグクラウドっぽく表示するカスタマイズです。カテゴリーに属するブログ記事数に応じて、カテゴリ名のフォントサイズなどを変化させます。
このカスタマイズは Ogawa::Memoranda さんの下記の記事に掲載されているスクリプトを利用しています。
カスタマイズ方法は、上記のエントリーに掲載されているタグ表示用のサブテンプレート(下)
...前略...
<MTTags>
<li title="<$MTTag$>:<$MTTagCount$>:<$MTTagDate format="%Y-%m-%d"$>"><a
title="Tag: <$MTTag$>"
href="<$MTBlogURL$>tag/<$MTTag encode_url="1"$>"><$MTTag$></a></li>
</MTTags>
...後略...
を、次の内容に入れ替えて、テンプレートの任意の位置に貼り付けてください。
...前略...
<mt:Categories>
<li title="<mt:CategoryLabel />:<mt:CategoryCount />:<mt:Entries lastn="1"><mt:EntryModifiedDate format="%Y-%m-%d" />"></mt:Entries><a
title="Category: <mt:ParentCategories glue="/"><mt:CategoryLabel /></mt:ParentCategories>"
href="<mt:CategoryArchiveLink />"><mt:CategoryLabel /></a></li>
</mt:Categories>
...後略...
バージョン3 をお使いであれば、次のサブテンプレートをお使いください。
...前略...
<MTCategories>
<li title="<$MTCategoryLabel$>:<$MTCategoryCount$>:<MTEntries lastn="1"><$MTEntryModifiedDate format="%Y-%m-%d"$>"></MTEntries><a
title="Category: <MTParentCategories glue="/"><$MTCategoryLabel$></MTParentCategories>"
href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a></li>
</MTCategories>
...後略...
サブカテゴリーに同じ名称のカテゴリーがあると、同名のカテゴリーが連続して表示されるのが欠点です。その場合、リンクのツールチップに親カテゴリーを含めて表示するようにしています。
サンプルとして、このブログのカテゴリークラウドは次のようになりました。
カテゴリーの階層別にデザインを切り替える for Movable Type 4
カテゴリーの階層別にデザインを切り替えるカスタマイズです。ポイントは「MTElseタグを使わない(使えない)」ということです。
参考記事は下記です。ありがとうございました。
以下に示すサブテンプレートは、ブログ記事リストへの設定を前提にしています。各サブテンプレートの一番外側のifタグは、ブログ記事リストでカテゴリーアーカイブと他のアーカイブを併用している場合を考慮したものです。
2階層の場合(パターン1)
<mt:if name="category_archive">
<MTHasParentCategory>
子カテゴリーのサブテンプレート
</MTHasParentCategory>
<MTHasNoParentCategory>
親カテゴリーのサブテンプレート
</MTHasNoParentCategory>
</mt:if>
2階層の場合(パターン2)
<mt:if name="category_archive">
<MTHasSubCategories>
親カテゴリーのサブテンプレート
</MTHasSubCategories>
<MTHasNoSubCategories>
子カテゴリーのサブテンプレート
</MTHasNoSubCategories>
</mt:if>
3階層の場合(パターン1)
<mt:if name="category_archive">
<MTHasSubCategories>
<MTHasNoParentCategory>
親カテゴリーのサブテンプレート
</MTHasNoParentCategory>
<MTHasParentCategory>
子カテゴリーのサブテンプレート
</MTHasParentCategory>
</MTHasSubCategories>
<MTHasNoSubCategories>
孫カテゴリーのサブテンプレート
</MTHasNoSubCategories>
</mt:if>
3階層の場合(パターン2)
<mt:if name="category_archive">
<MTHasParentCategory>
<MTHasSubCategories>
子カテゴリーのサブテンプレート
</MTHasSubCategories>
<MTHasNoSubCategories>
孫カテゴリーのサブテンプレート
</MTHasNoSubCategories>
</MTHasParentCategory>
<MTHasNoParentCategory>
親カテゴリーのサブテンプレート
</MTHasNoParentCategory>
</mt:if>
4階層の場合
<mt:if name="category_archive">
<MTHasSubCategories>
<MTHasNoParentCategory>
階層1カテゴリーのサブテンプレート
</MTHasNoParentCategory>
<MTHasParentCategory>
<MTParentCategory>
<MTHasParentCategory>
階層3カテゴリーのサブテンプレート
</MTHasParentCategory>
<MTHasNoParentCategory>
階層2カテゴリーのサブテンプレート
</MTHasNoParentCategory>
</MTParentCategory>
</MTHasParentCategory>
</MTHasSubCategories>
<MTHasNoSubCategories>
階層4カテゴリーのサブテンプレート
</MTHasNoSubCategories>
</mt:if>
次回はプラグインもしくは制御タグによる階層判定を行います。
カテゴリーリストの中に月別カテゴリーリストを表示する
カテゴリーリストと、そのカテゴリーがもつ月別カテゴリーリストを同時に表示するカスタマイズです。

カテゴリーリストはサブカテゴリーリストでも可能です。

カテゴリーリストの表示件数を絞り、かつ表示月が少ない場合に有効です。また、月別カテゴリーが有効になっていない場合は月別カテゴリーリストを表示しません。
デフォルトテンプレート(ウィジェット)+カテゴリーリスト
<MTIfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
<h3 class="widget-header">カテゴリ</h3>
<div class="widget-content"><ul class="widget-list">
<MTCategories>
<MTIfNonZero tag="MTCategoryCount">
<li class="widget-list-item"><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><$MTCategoryLabel$></a>
<MTIfArchiveTypeEnabled archive_type="Category-Monthly">
<MTArchiveList archive_type="Category-Monthly">
<MTArchiveListHeader>
<ul class="widget-list">
</MTArchiveListHeader>
<li class="widget-list-item"><a href="<$MTArchiveLink$>"><$MTArchiveTitle regex_replace="/.*: /",""$></a> [<$MTArchiveCount$>]</li>
<MTArchiveListFooter>
</ul>
</MTArchiveListFooter>
</MTArchiveList>
</MTIfArchiveTypeEnabled>
<MTElse>
<li class="widget-list-item"><$MTCategoryLabel$>
</MTIfNonZero>
</li>
</MTCategories>
</div>
</div>
</MTIfArchiveTypeEnabled>
デフォルトテンプレート(ウィジェット)+サブカテゴリーリスト
<MTIfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
<h2 class="widget-header">カテゴリ</h2>
<div class="widget-content">
<MTTopLevelCategories>
<MTSubCatIsFirst>
<ul class="widget-list">
</MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li class="widget-list-item"><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><$MTCategoryLabel$></a>
<MTIfArchiveTypeEnabled archive_type="Category-Monthly">
<MTArchiveList archive_type="Category-Monthly">
<MTArchiveListHeader>
<ul class="widget-list">
</MTArchiveListHeader>
<li class="widget-list-item"><a href="<$MTArchiveLink$>"><$MTArchiveTitle$></a> [<$MTArchiveCount$>]</li>
<MTArchiveListFooter>
</ul>
</MTArchiveListFooter>
</MTArchiveList>
</MTIfArchiveTypeEnabled>
<MTElse>
<li class="widget-list-item"><$MTCategoryLabel$>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast>
</ul>
</MTSubCatIsLast>
</MTTopLevelCategories>
</div>
</div>
</MTIfArchiveTypeEnabled>
そのうち折りたためるようにします。
サブカテゴリーリストを定義型リストでマークアップする
Movable Type の、2階層のサブカテゴリーリストで、定義型リスト(dl/dt/dd:または定義リスト)によるマークアップを実現する方法です。ここでは Movable Type によるカスタマイズを記していますが、定義型リストの使い方の参考にもなると思います。
以前、ご質問を頂いたもので、本エントリーで情報展開しておきます。
1.完成例
親カテゴリーに dt 要素、子カテゴリーは全体を dd 要素で括った後、順不同リスト(ul/li)でリスト表示します。
<dl>
<dt>親カテゴリーA</dt>
<dd>
<ul>
<li>子カテゴリーA-1</li>
<li>子カテゴリーA-2</li>
<li>子カテゴリーA-3</li>
</ul>
</dd>
<dt>親カテゴリーB</dt>
<dd>
<ul>
<li>子カテゴリーB-1</li>
<li>子カテゴリーB-2</li>
<li>子カテゴリーB-3</li>
</ul>
</dd>
</dl>
ちなみに、上のリストを順不同リストで表現すると、次のようになります。
<ul>
<li>親カテゴリーA
<ul>
<li>子カテゴリーA-1</li>
<li>子カテゴリーA-2</li>
<li>子カテゴリーA-3</li>
</ul>
</li>
</ul>
<ul>
<li>親カテゴリーB
<ul>
<li>子カテゴリーB-1</li>
<li>子カテゴリーB-2</li>
<li>子カテゴリーB-3</li>
</ul>
</li>
</ul>
2.サブテンプレート
上記を実現するサブテンプレートは次のようになります。
<dl>
<MTTopLevelCategories>
<MTSubCatIsFirst><MTHasNoParentCategory><MTElse><dd><ul></MTHasNoParentCategory></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<MTHasNoParentCategory>
<dt><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]</dt>
<MTElse>
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
</MTHasNoParentCategory>
<MTElse>
<MTHasNoParentCategory>
<dt><MTCategoryLabel></dt>
<MTElse>
<li><MTCategoryLabel>
</MTHasNoParentCategory>
</MTIfNonZero>
<MTSubCatsRecurse>
<MTHasNoParentCategory>
<MTElse>
</li>
</MTHasNoParentCategory>
<MTSubCatIsLast><MTHasNoParentCategory><MTElse></ul></dd></MTHasNoParentCategory></MTSubCatIsLast>
</MTTopLevelCategories>
</dl>
余談ですが、定義型リストによるマークアップは、以前行われた「コーディングコンテストVol.1」で最優秀賞を獲得された、「TOTOCO.ORG」さんのマークアップで利用されていて、審査員の方から「dl要素の使い方が良い」と、高い評価を受けています。
下の画面がコンテストで最優秀賞を得たサイトです。ブラウザから[表示]-[ページのソース]でマークアップをみることができます。
例えば、グローバルナビゲーションは次のようなマークアップです(一部省略しています)。
<dl id="globalNav">
<dt>主なカテゴリー</dt>
<dd>
<ul>
<li><a href="index.html"><img src="nav_home_cr.gif" alt="ホーム" width="98" height="54" /></a></li>
<li><a href="service/index.html"><img src="nav_biz.gif" alt="事業内容" width="98" height="54" /></a></li>
<li><a href="products/index.html"><img src="nav_products.gif" alt="製品情報" width="98" height="54" /></a></li>
<li><a href="recruit/index.html"><img src="nav_recruit.gif" alt="採用情報" width="98" height="54" /></a></li>
<li><a href="about/index.html"><img src="nav_about.gif" alt="会社概要" width="98" height="54" /></a></li>
<li><a href="contact/index.html"><img src="nav_contact.gif" alt="お問い合わせ" width="99" height="54" /></a></li>
</ul>
</dd>
</dl>
dt 要素は、次のCSSで非表示になっています(セレクタ名は一部省略)。
dl#globalNav dt{
position:absolute;
overflow:hidden;
width:0;
height:0;
}
丁度この時執筆していた、「Movable Type WEBデザインの新しいルール」のグローバルナビゲーションのカスタマイズにも、この定義型リストによるマークアップを利用させていただきました。
カテゴリーリストにカスタムフィールドの画像を表示する
Movable Type のカテゴリーリストに、カスタムフィールドの画像を表示するカスタマイズです。
次のように、カテゴリー別の画像を簡単に与えることができます。

1.カスタムフィールドの作成
カテゴリーにカスタムフィールドを作成します。ここでは CategoryImage という名前のテンプレートタグにします。

2.カテゴリーに画像の追加
各カテゴリーに表示されている「Imageを選択」をクリックして、画像を追加します。

画像を選択した後、必ず保存をクリックしてください。何回か試して正常に表示されないことがあったのですが、どうも保存をクリックするのを忘れていたようです。

3.サブテンプレートの追加
冒頭のサンプルは、デフォルトテンプレートのサイドバーに下記のサブテンプレートを追加しました。階層表示でない、MTCategories タグを久しぶりに使ってみました。
青色部分がカスタムフィールド用タグです。
<mt:IfArchiveTypeEnabled archive_type="Category">
<div class="widget-archive widget-archive-category widget">
<h3 class="widget-header">カテゴリ</h3>
<div class="widget-content">
<ul class="widget-list">
<mt:Categories>
<mt:ifNonZero tag="mt:CategoryCount">
<li class="widget-list-item"><MTCategoryImageAsset><img src="<$MTAssetURL$>" style="vertical-align:middle" /> </MTCategoryImageAsset><a href="<$mt:CategoryArchiveLink$>"<mt:IfNonEmpty tag="mt:CategoryDescription"> title="<$mt:CategoryDescription$>"</mt:IfNonEmpty>><$mt:CategoryLabel$> (<$mt:CategoryCount$>)</a>
<mt:else>
<li class="widget-list-item"><MTCategoryImageAsset><img src="<$MTAssetURL$>" style="vertical-align:middle" /> </MTCategoryImageAsset><$mt:CategoryLabel$>
</mt:ifNonZero>
</li>
</mt:Categories>
</ul>
</div>
</div>
</mt:IfArchiveTypeEnabled>
赤色部分は、画像の垂直方向の位置揃えのための style 属性です。サンプルでは img 要素に直接与えてしまっているので、適宜スタイルシートで設定するようにしてください。
ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する
Movable Type で、ブログ記事の前後のブログ記事へのリンクを、直近のブログ記事ではなく、同一カテゴリーのブログ記事を表示するカスタマイズです。
2008.11.18 Movable Type 4.2 対応の記事を公開しました。
下の画面の、ブログ記事タイトル上にある前後リンクは、分かりにくいですが、同一カテゴリーのブログ記事です。

また、ブログ記事に複数カテゴリーを設定している場合は、すべてのカテゴリーの前後リンクも表示します(こんなに表示するのもどうかと思いますが...)。

以下、カスタマイズ方法です。
1.プラグインのダウンロード
Previous and next in category のサイトに進み、「PreviousNextInCategory」のリンクをクリック。
![]()
2.プラグインのインストール
ダウンロードした PreviousNextInCategory.zip を解凍して、PreviousNextInCategory.pl をpluginsディレクトリにアップロードします。
ブログ管理画面より、「システムメニュー」→「プラグイン」で「PreviousNextInCategory.pl」が表示されればインストール完了です。

3.プライマリカテゴリーに属するブログ記事のみを表示する場合
ブログ記事アーカイブの任意の位置に下記のサブテンプレートを設定してください。
<MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink$>">« <$MTEntryTitle$></a> |
</MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink archive_type="Category"$>"><$MTEntryCategory$></a>
<MTEntryNextInCategory>
| <a href="<$MTEntryPermalink$>"><$MTEntryTitle$> »</a>
</MTEntryNextInCategory>
ブログ記事アーカイブを再構築すれば、冒頭のように、同一カテゴリーの前後記事リンクが表示されます。
4.ブログ記事に登録されているすべてのカテゴリーに属するブログ記事を表示する場合
PreviousNextInCategory.plを任意のエディタで開き、
:
sub _hdlr_entry_previous_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryPrevious');
my $cat = $e->category
or return '';
my $prev = $e->previous(1);
:
sub _hdlr_entry_next_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryNext');
my $cat = $e->category
or return '';
my $next = $e->next(1);
:
の部分に下記の青色の行を追加します。
:
sub _hdlr_entry_previous_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryPrevious');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $prev = $e->previous(1);
:
sub _hdlr_entry_next_in_category {
my($ctx, $args, $cond) = @_;
my $e = $ctx->stash('entry')
or return $ctx->_no_entry_error('MTEntryNext');
my $cat = $e->category
or return '';
if($ctx->stash('category') ne '') {
$cat = $ctx->stash('category');
}
my $next = $e->next(1);
:
ブログ記事アーカイブの任意の位置に下記のサブテンプレートを設定してください。
<MTEntryCategories>
<p>
<MTEntryPreviousInCategory>
<a href="<$MTEntryPermalink$>">« <$MTEntryTitle$></a> |
</MTEntryPreviousInCategory>
<a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a>
<MTEntryNextInCategory>
| <a href="<$MTEntryPermalink$>"><$MTEntryTitle$> »</a>
</MTEntryNextInCategory>
</p>
</MTEntryCategories>
ブログ記事アーカイブを再構築すれば、ブログ記事が属する全カテゴリーの前後記事リンクが表示されます。
5.前後記事の再構築をする
上記の設定だけでは、ブログ記事投稿時に同一カテゴリーの前後記事が再構築されないという問題があります。
ということで、一応、MT4対応のプラグインを作ってみました。
元プラグインをかなり改変してしまったので、上記のファイルをダウンロードしたら、元プラグインにある、
_hdlr_entry_previous_in_category
_hdlr_entry_next_in_category
を埋め込んでください(複数カテゴリーに対応させる場合は4項のカスタマイズも行ってください)。
具体的な作業は、ダウンロードしたファイルの最後の方に簡単な説明を入れてますので、それを読んでください。
複数のカテゴリーを設定したブログ記事でも、前後リンクのブログ記事はすべて再構築されます。
なお、再構築は同じカテゴリーのブログ記事を検索するという、元記事のロジックをそのまま使わせてもらってますが、パフォーマンスの問題を解消する改善策がありましたらご教示ください。
6.参考記事
このエントリーは下記の記事を参考にさせていただきました。ありがとうございました。
カテゴリーアーカイブのサブカテゴリーリストに、親カテゴリーとその子カテゴリーを表示する
Movable Type のカテゴリーアーカイブに表示しているサブカテゴリーリストにおいて、自カテゴリーと、その親カテゴリーに属するカテゴリーを表示するカスタマイズです。
具体例を説明します。例えば、ブログのカテゴリーが、
cat1
├ cat1-1
├ cat1-2
└ cat1-3
cat2
├ cat2-1
├ cat2-2
└ cat2-3
cat3
├ cat3-1
├ cat3-2
└ cat3-3
となっていると仮定します。
cat1-1 のカテゴリーアーカイブを表示した時、サブカテゴリーリストには、
cat1
├ cat1-1
├ cat1-2
└ cat1-3
のみを表示します。また、cat2-2 のカテゴリーアーカイブを表示した時、サブカテゴリーリストには、
cat2
├ cat2-1
├ cat2-2
└ cat2-3
のみを表示します。
1.サブカテゴリーのアーカイブで親カテゴリーとそのサブカテゴリーを表示する
次のサブテンプレートを任意の位置に設定して、再構築してください。
<MTParentCategory>
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</MTParentCategory>
このサブテンプレートは、親カテゴリーでは何も表示されません。親カテゴリーは、一番外側の MTParentCategory タグの実行条件にマッチしない(親カテゴリーに親カテゴリーが存在しない)ためです。
2.親カテゴリーでも同じように表示する
親カテゴリーである cat1 のカテゴリーアーカイブを表示した時、サブカテゴリーリストに
cat1
├ cat1-1
├ cat1-2
└ cat1-3
とする場合は、先のサブテンプレートに下記の青色部分を追加します。
<MTParentCategory>
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</MTParentCategory>
<MTHasNoParentCategory>
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</MTHasNoParentCategory>
ちなみに上記のリストでは、MTSubCategories が2ヶ所出現し、その内容は全く同じです(赤色部分)。
<MTParentCategory>
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</MTParentCategory>
<MTHasNoParentCategory>
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</MTHasNoParentCategory>
次のように MTSetVarTemplate タグを使って丸めておけば、サブテンプレートの重複したマークアップを解消できます。
<mt:setvartemplate name="subcategorylist">
<MTSubCategories include_current="1">
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</mt:setvartemplate>
<MTParentCategory>
<mt:getvar name="subcategorylist">
</MTParentCategory>
<MTHasNoParentCategory>
<mt:getvar name="subcategorylist">
</MTHasNoParentCategory>
3.カテゴリーアーカイブ以外でこのサブテンプレートを表示させない対処
いずれの方法も、リストの一番外側は、
<MTIf name="category_archive">
:
</MTIf>
で括っておけば、他のアーカイブで表示されずに済みます。
ブログ記事に同一カテゴリーのブログ記事リストを表示(MT4版・改)
「ブログ記事に同一カテゴリーのブログ記事リストを表示(MT4版)」や、これまでの似たようなカスタマイズでは、次の問題あることが判明しました。
1.問題点
異なる親カテゴリーに同名のサブカテゴリーがある場合、対応できない。
具体的には、次のようなカテゴリー構成を想定します。
cat-A
├ cat-1
└ cat-2
cat-B
├ cat-1
└ cat-2
この構成で「ブログ記事に同一カテゴリーのブログ記事リストを表示(MT4版)」を行うと、cat-A/cat-1 に属するブログ記事と、cat-B/cat-1 に属するブログ記事は「同一カテゴリーのブログ記事リスト」とみなされてしまいます。
2010.10.31追記:MT5では、MTEntriesタグにcategoryモディファイアを与え、モディファイアの値に親カテゴリーから子カテゴリまでを階層的に指定することで、この問題は解消されます。
2.原因
「同一カテゴリーのブログ記事リスト」のキー情報として、MTEntryCategory という、ブログ記事に属するメインカテゴリー名のみ使っており、カテゴリーの親カテゴリーまで含めた情報やID番号でサーチしていないためです。
こうなった経緯は、そもそも、Movable Type 3 の途中まで「サブカテゴリー」という概念が存在しませんでした。つまり、親カテゴリーしか作れなかったため、同名のカテゴリーの存在が許されず、これまでのサブテンプレートを使えば「同一カテゴリーのブログ記事リスト」を実現できた、という訳です。
3.対処
3.1 EntryCategoryID プラグインを使う
「EntryCategoryID プラグイン」を使い、ブログ記事のメインカテゴリーのID番号と、ブログ記事リストのカテゴリーIDを比較し、同一カテゴリーID のブログ記事のみリスティングします。
<mt:setvarblock name="entrycategoryid"><$MTEntryCategoryID$></mt:setvarblock>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTCategories>
<mt:setvarblock name="currentcategoryid"><$MTEntryCategoryID$></mt:setvarblock>
<mt:if name="currentcategoryid" eq="$entrycategoryid">
<MTEntries>
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTEntries>
</mt:if>
</MTCategories>
</ul>
</dd>
3.2 MTParentCategories タグを使う(その1)
これは後から気がついたのですが、MTParentCategories タグを使い、ブログ記事のメインカテゴリーの親カテゴリーを取得すれば、3.1項と同じことができます。
<MTParentCategories glue="/" setvar="entrycategories"><$MTCategoryLabel$></MTParentCategories>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTCategories>
<MTParentCategories glue="/" setvar="currententrycategories"><$MTCategoryLabel$></MTParentCategories>
<mt:if name="currententrycategories" eq="$entrycategories">
<MTEntries>
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTEntries>
</mt:if>
</MTCategories>
</ul>
</dd>
MTParentCategories のカテゴリーのセパレータには "/"、また MTSetvarBlock タグの代わりに setvar モディファイアを利用しています。
3.3 MTParentCategories タグを使う(その2)
こちらは、MTEntries タグに category モディファイアを与えて、とりあえず自カテゴリーで絞り込んでから親カテゴリーと比較します。
<mt:setvarblock name="entrycategory"><$MTEntryCategory$></mt:setvarblock>
<MTParentCategories glue="/" setvar="entrycategories"><$MTCategoryLabel$></MTParentCategories>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTEntries category="$entrycategory">
<MTParentCategories glue="/" setvar="currententrycategories"><$MTCategoryLabel$></MTParentCategories>
<mt:if name="currententrycategories" eq="$entrycategories">
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</mt:if>
</MTEntries>
</ul>
</dd>
2008.02.25
3.3項を追加しました。
2010.10.31
1項に注記を追加しました。
Movable Type 4 でカテゴリー別にデザインを切り替える方法(その3)
Movable Type 4 でカテゴリー別にデザインを切り替える方法を、何回かに分けて紹介します。
1.MTIfCategory タグブロック内のサブテンプレートをモジュール化する
カテゴリーアーカイブのデザインを変更する2つめの方法で、MTIfCategory タグブロック内にサブテンプレートをベタ書きするのではなく、MTInclude タグを使います。
カテゴリー1~3
<MTIfCategory name="カテゴリー1">
<$MTInclude module="カテゴリー1"$>
</MTIfCategory>
<MTIfCategory name="カテゴリー2">
<$MTInclude module="カテゴリー2"$>
</MTIfCategory>
<MTIfCategory name="カテゴリー3">
<$MTInclude module="カテゴリー3"$>
</MTIfCategory>
こうすることにより、カテゴリーアーカイブ本体では「どのカテゴリーにどのテンプレートを割り当てるか」という制御に徹することができ、テンプレート全体の見通しがよくなります。
汎用的なデザインを与えたいカテゴリー4~6を新たに追加する場合は、次のようにします。
<MTIfCategory name="カテゴリー1">
<$MTInclude module="カテゴリー1"$>
<MTElse>
<MTIfCategory name="カテゴリー2">
<$MTInclude module="カテゴリー2"$>
<MTElse>
<MTIfCategory name="カテゴリー3">
<$MTInclude module="カテゴリー3"$>
<MTElse>
<$MTInclude module="カテゴリーその他"$>
</MTIfCategory>
</MTIfCategory>
</MTIfCategory>
最初の MTIfCategory タグでカテゴリー1であるかの判定をし、そうでなければ MTElse を実行して、次の MTIfCategory タグでカテゴリー2であるかの判定をします。その繰り返しで、最後のカテゴリー判定にマッチしなかったカテゴリーには一番最後の MTElse タグの内容、つまりデフォルトとなるデザインのテンプレートモジュールを呼び出します。
2.MTIfCategory タグを除去して、モジュール化をさらに簡素化する
さて、すでにお気づきの方もいらっしゃると思いますが、最初のリストは、カテゴリーを識別するキーさえ取得できれば、実は以下の1行で済みます。
<$MTInclude module="カテゴリーを識別するキー"$>
「カテゴリーを識別するためのキー」として、次のようにカテゴリー名を使ってみます。カテゴリー名は、MTInclude タグを実行する前に、MTSetVarBlock タグを使って変数に設定し、変数名をmoduleモディファイアに与えれば、ダイナミックにカテゴリー名を設定することができます。
<mt:setvarblock name="category_name"><$MTCategoryLabel$></mt:setvarblock>
<$MTInclude module="$category_name"$>
これで、このアーカイブが「カテゴリー1」の再構築を行うときには変数 category_name には「カテゴリー1」が、「カテゴリー2」の再構築を行うときには変数 category_name には「カテゴリー2」...という具合に設定され、それぞれ「カテゴリー1」「カテゴリー2」...という名前のテンプレートモジュールを呼び出します。
注意するのは、変数category_nameをmoduleモディファイア(というか、nameモディファイア以外)で使う場合は、変数名の前に大抵「$」をつけておく、ということです。
3.MTIf タグを使ってデフォルトデザインの条件分岐をつける
2つめのリストのように、デフォルトのデザインと振り分けたい場合は、さらに MTIf タグと MTCategoryDescription タグで制御します。この方法は SYSTEM STUDIO さんよりアイデア頂きました。ありがとうございました。
<mt:setvarblock name="category_description"><$MTCategoryDescription$></mt:setvarblock>
<mt:if name="category_description">
<$MTInclude module="$category_description"$>
<mt:else>
<$MTInclude module="デフォルト"$>
<mt:if>
このリストを使う前準備として、各カテゴリーの「カテゴリーの説明」欄に、呼び出したいモジュール名を設定しておきます。デフォルトデザインのモジュールを呼び出したいときには、「カテゴリーの説明」欄には何も設定しません。
そうすれば、MTIf タグの判定で「カテゴリーの説明」欄に記入されている場合に、「カテゴリーの説明」欄に設定された名前のテンプレートモジュールを呼び出します。「カテゴリーの説明」欄に記入していない場合は、「デフォルト」という名前のテンプレートモジュールを呼び出します。
なお、前回もお伝えしたとおり、「カテゴリーの説明」欄を使うよりも、カスタムフィールドを利用した方が妥当に思われます。
Movable Type 4 でカテゴリー別にデザインを切り替える方法(その2)
Movable Type 4 でカテゴリー別にデザインを切り替える方法を、何回かに分けて紹介します。
1.ひとつのアーカイブテンプレートでカテゴリーを分割する
カテゴリーアーカイブのデザインを変更する2つめの方法は、アーカイブテンプレートの中で MTIfCategory タグを使います。MTIfCategory タグの name モディファイアには、カテゴリー名が重複しないように設定します。
カテゴリー1~3
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
</MTIfCategory>
<MTIfCategory name="カテゴリー2">
:
(カテゴリー2用のテンプレート)
:
</MTIfCategory>
<MTIfCategory name="カテゴリー3">
:
(カテゴリー3用のテンプレート)
:
</MTIfCategory>
この方法には、次のような特徴があります。
- カテゴリーの振り分け処理が可能
- 基本的にパスは一意に決まる
- 優先の制約がない
ひとつのアーカイブテンプレートにまとめる一番のメリットは、あるいくつかのカテゴリーには特殊なデザインを与え、そうでないものについては汎用的なデザインを適用できることです。
「その1」の方法では、アーカイブテンプレートをカテゴリーごとに与えているため、そのような制御ができなくなります。
例えば、冒頭のサブテンプレートに、汎用的なデザインを使いたいカテゴリー4~6を新たに追加する場合、最初に示したサブテンプレートでは、カテゴリー4~6を個別に指定する必要がありますが、次のように変更すれば、一括した指定が可能です。
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
<MTElse>
<MTIfCategory name="カテゴリー2">
:
(カテゴリー2用のテンプレート)
:
<MTElse>
<MTIfCategory name="カテゴリー3">
:
(カテゴリー3用のテンプレート)
:
<MTElse>
:
(カテゴリー4~6用のテンプレート)
:
</MTIfCategory>
</MTIfCategory>
</MTIfCategory>
最初の MTIfCategory タグでカテゴリー1であるかの判定をし、そうでなければ MTElse を実行して、次の MTIfCategory タグでカテゴリー2であるかの判定をします。その繰り返しで、最後のカテゴリー判定にマッチしなかったカテゴリーには一番最後の MTElse タグの内容、つまりデフォルトとなるデザインを適用します。
次の設定は誤りです。
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
</MTIfCategory>
<MTIfCategory name="カテゴリー2">
:
(カテゴリー2用のテンプレート)
:
</MTIfCategory>
<MTIfCategory name="カテゴリー3">
:
(カテゴリー3用のテンプレート)
:
<MTElse>
:
(カテゴリー4~6用のテンプレート)
:
</MTIfCategory>
理由は、「カテゴリー4~6用のテンプレート」と書かれた部分にはカテゴリー1とカテゴリー2が含まれるからです。
また、この方法では基本的に全てのカテゴリーに共通のパスを与えますが、テンプレートタグを用いることでカテゴリー別に異なるパスを与えることもできます(これについては別の機会に)。またカテゴリー用アーカイブがひとつであるため、「優先」の問題も回避できます。
2.スタイルシートについて
ここでは次の方法が考えられます。
まず、head 要素が、各カテゴリーのサブテンプレートに含まれているのであれば、head 要素内にカテゴリー用のスタイルシートを呼び出す link 要素をそのまま記述します。
すべてのカテゴリーが共通で head 要素をテンプレートモジュールとして呼び出している場合は、MTIfCategory タグブロック内に次のような MTSetVar タグを記述します。
<MTIfCategory name="cat1">
<mt:setvar name="style" value="[カテゴリー1用スタイルシートのファイル名]">
</MTIfCategory>
<MTIfCategory name="cat2">
<mt:setvar name="style" value="[カテゴリー2用スタイルシートのファイル名]">
</MTIfCategory>
<MTIfCategory name="cat3">
<mt:setvar name="style" value="[カテゴリー3用スタイルシートのファイル名]">
</MTIfCategory>
<$MTInclude module="ヘッダー"$>
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
汎用的なカテゴリー用のスタイルシートを作りたい場合は、次のようにします。
<MTIfCategory name="cat1">
<mt:setvar name="style" value="[カテゴリー1用スタイルシートのファイル名]">
<MTElse>
<MTIfCategory name="cat2">
<mt:setvar name="style" value="[カテゴリー2用スタイルシートのファイル名]">
<MTElse>
<MTIfCategory name="cat3">
<mt:setvar name="style" value="[カテゴリー3用スタイルシートのファイル名]">
<MTElse>
<mt:setvar name="style" value="[カテゴリー4~6用スタイルシートのファイル名]">
</MTIfCategory>
</MTIfCategory>
</MTIfCategory>
<$MTInclude module="ヘッダー"$>
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
そして、「ヘッダー」モジュールには次のように記述しておきます。
<mt:if name="category_archive">
<link rel="stylesheet" href="<$MTBlogURL$><$mt:getvar name="style"$>" type="text/css" title="<$MTCategoryLabel encode_html="1"$>" media="screen,tv" />
</mt:if>
または、MTCategoryDescription タグにスタイルシートのファイル名(下のサンプルでは拡張子なし)を設定しておき、「ヘッダー」モジュールだけで呼び出せる方法もあります。
<mt:if name="category_archive">
<link rel="stylesheet" href="<$MTBlogURL$><$MTCategoryDescription$>.css" type="text/css" title="<$MTCategoryLabel encode_html="1"$>" media="screen,tv" />
</mt:if>
異なるカテゴリーで同じデザインを適用したい場合は、MTCategoryDescription タグに該当する「カテゴリーの説明」欄に同じ名称を記述しておきます。
なお、「カテゴリーの説明」よりもカスタムフィールドを使う方が、用途が明確になってよりいいでしょう。
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その1)
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その2)
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その3)
Movable Type 4 でカテゴリー別にデザインを切り替える方法(その1)
Movable Type 4 でカテゴリー別にデザインを切り替える方法を、何回かに分けて紹介します。
1.カテゴリー別にアーカイブテンプレートを独立させる
2009.08.21 注:カテゴリー別にアーカイブテンプレートを独立させる方法ではカテゴリーを適正に制御することができません。カテゴリー別にデザインを切り替えるには、「Movable Type 4 でカテゴリー別にデザインを切り替える方法(その2)」「Movable Type 4 でカテゴリー別にデザインを切り替える方法(その3)」を参照願います。
カテゴリーアーカイブのデザインを変更するために、カテゴリー別に複数のアーカイブテンプレートを作る方法があります。その際、カテゴリーアーカイブテンプレート全体を MTIfCategory タグで括ります。MTIfCategory タグの name モディファイアには、カテゴリー名が重複しないように設定します。
カテゴリー1
<MTIfCategory name="カテゴリー1">
:
(カテゴリー1用のテンプレート)
:
</MTIfCategory>
カテゴリー2
<MTIfCategory name="カテゴリー2">
:
(カテゴリー2用のテンプレート)
:
</MTIfCategory>
カテゴリー3
<MTIfCategory name="カテゴリー3">
:
(カテゴリー3用のテンプレート)
:
</MTIfCategory>
この方法には、次のような特徴があります。
- カテゴリーアーカイブテンプレートの独立性
- カテゴリー別にパスを変更できる
- カテゴリー別に異なるパスを設定すると「優先」の制約が発生する
まず、カテゴリーアーカイブテンプレートを独立させ、テンプレートとカテゴリーを1:1の対応にするので、下のように編集対象のカテゴリーが視覚的に分かりやすくなるというメリットがあります。また、テンプレートの内容にもよりますが、この方法であれば、Movable Type 4 の制御系タグをほとんど使わずにすむかもしれません。

また、カテゴリー別に異なるパスを与えたい場合、この方法以外に選択の余地はありません。テンプレートタグをパス欄に設定すれば個別に設定することも可能です。
最後の「カテゴリー別に異なるパスを設定すると「優先」の制約が発生する」の意味は、まず、同一アーカイブ種別のテンプレートを複数作成すると、「優先」の問題が発生します。「優先」とは、他のページからあるアーカイブ種別のアーカイブにリンクする場合のリンク先を決めるためのもので、優先にするテンプレートにはチェックをつけます。

例えば、カテゴリー1・カテゴリー2・カテゴリー3用のアーカイブテンプレートを、それぞれ別のアーカイブテンプレートで作成した場合、どれかひとつのアーカイブテンプレートが「優先」に、残りが「非優先」になります。
もし、カテゴリー別にパスを変更した場合、メインページなどでカテゴリーリストを、MTTopLevelCategories タグで表示すると、「優先」が設定されたカテゴリーのパスで表示されるので、非優先のカテゴリーアーカイブページはデッドリンクになります。
ただし、全てのカテゴリーアーカイブが同じパスであれば、非優先カテゴリーアーカイブへのリンクも、優先カテゴリーアーカイブで生成されたリンクが利用できます(たまたまそうなるだけであり、手法としては適切ではないかもしれません)。
2.スタイルシートについて
ここでは2つの方法が考えられます。
まず、head 要素が、独立させたカテゴリーアーカイブにそれぞれ含まれているのであれば、head 要素内にカテゴリー用のスタイルシートを呼び出す link 要素をそのまま記述します。これが一番シンプルな方法です。
もうひとつは、head 要素をテンプレートモジュールとして呼び出している場合は、MTIfCategory タグブロック内に次のような MTSetVar タグを記述します。
<MTIfCategory name="cat1">
<mt:setvar name="style" value="[カテゴリー用スタイルシートのファイル名]">
<$MTInclude module="ヘッダー"$>
:
</MTIfCategory>
そして、「ヘッダー」モジュールには次のように記述します。
<mt:if name="category_archive">
<link rel="stylesheet" href="<$MTBlogURL$><$mt:getvar name="style"$>" type="text/css" title="<$MTCategoryLabel encode_html="1"$>" media="screen,tv" />
</mt:if>
または、MTCategoryDescription タグにスタイルシートのファイル名(下のサンプルでは拡張子なし)を設定しておき、「ヘッダー」モジュールだけで呼び出せる方法もあります。
<mt:if name="category_archive">
<link rel="stylesheet" href="<$MTBlogURL$><$MTCategoryDescription$>.css" type="text/css" title="<$MTCategoryLabel encode_html="1"$>" media="screen,tv" />
</mt:if>
異なるカテゴリーで同じデザインを適用したい場合は、MTCategoryDescription タグに同じ名称を記述しておきます。
後者の方法は、他のカテゴリー分割方法でも共通に使えます。
2008.02.20
カテゴリーパスの記述を一部修正しました。
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その1)
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その2)
- Movable Type 4 でカテゴリー別にデザインを切り替える方法(その3)
Movable Type 4 のカテゴリーアーカイブで全てのブログ記事を表示する
Movable Type 4 デフォルトテンプレートでのカテゴリーアーカイブでは、そのカテゴリーのブログ記事が全て表示されない仕組みになっています。
これは、カテゴリーアーカイブの表示記事数を絞る代わりに、「月別カテゴリーアーカイブ」を併用して、カテゴリーアーカイブの分割ページとして賄うようにしているためです。
こうすることで、カテゴリーアーカイブの記事数が増大しても、カテゴリーアーカイブをページ分割等で表示記事数を絞る必要がなくなります。
本エントリーでは、カテゴリーアーカイブで表示記事数がメインページと同じになる仕組みと、それを解除する方法等について解説します。
1.カテゴリーアーカイブで表示記事数が絞られる仕組み
仕組みは簡単で、デフォルトテンプレートであれば、「デザイン」→「テンプレート」→「アーカイブテンプレート」→「ブログ記事リスト」の MTEntries タグに limit モディファイアを適用されていると思います。このモディファイアの値に "auto" が設定されていれば、アーカイブでの表示記事数が「設定」→「ブログの設定」→「ブログ記事」→「ブログ記事の表示数」の設定が適用されます。つまりメインページと同じ表示になります。
:
<MTIf name="datebased_archive">
<MTEntries>
<$MTEntryTrackbackData$>
<$MTInclude module="ブログ記事の概要"$>
</MTEntries>
<MTElse>
<MTEntries limit="auto">
<$MTEntryTrackbackData$>
<$MTInclude module="ブログ記事の概要"$>
</MTEntries>
</MTIf>
:
上のリストは、次のように表示するアーカイブを振り分けています。
<MTIf name="datebased_archive">
:
(日付アーカイブ)
:
<MTElse>
:
(カテゴリーアーカイブ)
:
</MTIf>
limit モディファイアは lastn モディファイアと似たような動作を行ないます。
2.カテゴリーアーカイブで記事をすべて表示する
「デザイン」→「テンプレート」→「アーカイブテンプレート」→「ブログ記事リスト」で、limit モディファイアを削除すれば、カテゴリーアーカイブで記事をすべて表示できます(下)。
:
<MTIf name="datebased_archive">
<MTEntries>
<$MTEntryTrackbackData$>
<$MTInclude module="ブログ記事の概要"$>
</MTEntries>
<MTElse>
<MTEntries>
<$MTEntryTrackbackData$>
<$MTInclude module="ブログ記事の概要"$>
</MTEntries>
</MTIf>
:
ただし、この方法では、記事数が増えるにしたがってファイルサイズも増大するので、日付カテゴリアーカイブとの併用が望ましいです。
3.月別カテゴリーアーカイブリストを表示する
当ブログの配布テンプレートではサイドバーに月別カテゴリーアーカイブのリストが表示されないので(過去のバージョンで一部表示されるものもあります)、下記のリストを「サイドバー」テンプレートに貼り付けておけば、月別カテゴリーアーカイブにリンクさせることができます(この点についてはいずれ修正します)。
<MTIf name="module_category-monthly_archives">
<MTIfArchiveTypeEnabled archive_type="Category-Monthly">
<dt class="sidetitle">
Monthly <$MTCategoryLabel$>
</dt>
<dd class="side">
<ul>
<MTArchiveList archive_type="Category-Monthly">
<li><a href="<$MTArchiveLink$>"><$MTArchiveTitle$></a> [<$MTArchiveCount$>]</li>
</MTArchiveList>
</ul>
</dd>
</MTIfArchiveTypeEnabled>
</MTIf>
4.関連記事
dtree のサブカテゴリーリストにブログ記事タイトルを表示する for Movable Type
以前ご紹介した、「dTree によるサブカテゴリーリスト for Movable Type」で、ブログ記事タイトルを表示するカスタマイズをご紹介します。
dTree とは、エクスプローラー風のツリー表示用スクリプトです。下記のサンプルで動作をご確認ください。
本エントリーのカスタマイズを行うことで、下のスクリーンショットのように、各カテゴリー配下に属するブログ記事タイトルを表示させることができます。

以下、サブカテゴリーリストにブログ記事タイトルを表示するカスタマイズです。なお、この記事の5項の設定を行う前に、「dTree によるサブカテゴリーリスト for Movable Type」の4項までを設定しておいてください。
5.dTree サブカテゴリーリスト表示用タグ設定
テンプレートで、サブカテゴリーリストを表示したい位置に下記のタグを設定してください。
表示用タグは PHP 版と JavaScript 版、MTタグ版を用意しました。表示される結果はどれも同じです。
5.1 PHP版
このタグを設定する場合、PHP化を行っていることが前提です。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'SubCategories','javascript: void(0);');
<?php $cat_number = 0; $level = 0; $tree = array(); ?>
<MTTopLevelCategories>
<?php $tree[$level] = ++$cat_number; if(!$level) { ?>
d.add(<?php echo $cat_number ?>, 0,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } else { if(!$tree[$level - 1]) { ?>
d.add(<?php echo $cat_number ?>, 1,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } else { ?>
d.add(<?php echo $cat_number ?>, <?php echo $tree[$level - 1] ?>,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php }} ?>
<MTEntries>
<MTEntriesHeader>
<?php $level++; ?>
</MTEntriesHeader>
<?php $cat_number++; ?>
d.add(<?php echo $cat_number ?>, <?php echo $tree[$level - 1] ?>,'<$MTEntryTitle encode_php="1"$>','<$MTEntryPermalink$>');
<MTEntriesFooter>
<?php $level--; ?>
</MTEntriesFooter>
</MTEntries>
<?php $level++; ?>
<MTSubCatsRecurse>
<?php $level--; ?>
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
5.2 JavaScript 版
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1, 'SubCategories','javascript: void(0);');
var cat_number = 0;
var level = 0;
var link = new Array();
<MTTopLevelCategories>
link[level] = ++cat_number;
if(!level) {
d.add(cat_number, 0,'<$MTCategoryLabel encode_js="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
} else {
if(!link[level - 1]) {
d.add(cat_number, 1,'<$MTCategoryLabel encode_js="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
} else {
d.add(cat_number, link[level - 1],'<$MTCategoryLabel encode_js="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
}
}
<MTEntries>
<MTEntriesHeader>
level++;
</MTEntriesHeader>
cat_number++;
d.add(cat_number, link[level - 1],'<$MTEntryTitle encode_js="1"$>','<$MTEntryPermalink$>');
<MTEntriesFooter>
level--;
</MTEntriesFooter>
</MTEntries>
level++;
<MTSubCatsRecurse>
level--;
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
5.3 テンプレートタグ版(MT4.1 以上のみ対応)
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<$mt:setvar name="cat_number" value="1"$>
<$mt:setvar name="level" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
<$mt:setvar name="tree[$level]" value="$cat_number"$>
<mt:if name="level" eq="1">
d.add(<$mt:getvar name="cat_number" op="--"$>, 0,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<mt:else>
d.add(<$mt:getvar name="cat_number" op="--"$>, <$mt:setvar name="tmp" value="$level"$><$mt:setvar name="tmp" op="--"$><$mt:getvar name="tree[$tmp]" op="--"$>,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
</mt:if>
<MTEntries>
<MTEntriesHeader>
<$mt:setvar name="level" op="++"$>
</MTEntriesHeader>
<$mt:setvar name="cat_number" op="++"$>
d.add(<$mt:getvar name="cat_number" op="--"$>, <$mt:setvar name="tmp" value="$level"$><$mt:setvar name="tmp" op="--"$><$mt:getvar name="tree[$tmp]" op="--"$>,'<$MTEntryTitle escape="html"$>','<$MTEntryPermalink$>');
<MTEntriesFooter>
<$mt:setvar name="level" op="--"$>
</MTEntriesFooter>
</MTEntries>
<$mt:setvar name="level" op="++"$>
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="--"$>
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
以上です。
2007.12.28
MT3.x でパーマリンクが正常に生成されない不具合を修正しました(MTEntryPermaLink を MTEntryPermalink に修正)。
dTree を Movable Type 4.1/MTOS のネイティブタグで実装する
Movable Type 4.1/MTOS で変数の算術演算子と配列およびハッシュが実装されたことで、PHPあるいはJavaScriptとの組み合わせが必要だった処理が、ネイティブなタグのみで実装可能になりました。
全てのコードについて移植が可能であるかどうかは不明ですが、どの程度の威力があるか検証してみたかったので、サンプルとして、以前紹介した dTree のカスタマイズについてテンプレートタグで実装してみました。
1.dTree について
機能や設定方法は下記の記事を参照願います(実際にご利用になる場合、この記事の4項までの設定が必要です)。
で、元記事で紹介したPHP版のスクリプトは下記の通りです(若干直しました)。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<?php $cat_number = 0; $level = 0; $tree = array(); ?>
<MTTopLevelCategories>
<?php $tree[$level] = ++$cat_number; if(!$level) { ?>
d.add(<?php echo $cat_number ?>, 0,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } else { ?>
d.add(<?php echo $cat_number ?>, <?php echo $tree[$level - 1] ?>,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } $level++; ?>
<MTSubCatsRecurse max_depth="3">
<?php $level--; ?>
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
再掲になりますが、dTree によるサブカテゴリーリストの完成イメージは次の通りです。

この表示を行うための JavaScript は次の内容になっています(上記のPHPスクリプトから生成されたものです)。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
d.add(1, 0,'test1','http://.../test/');
d.add(2, 1,'test1-1','http://.../test/test11/');
d.add(3, 2,'test1-1-1','http://.../test/test11/test111/');
d.add(4, 2,'test1-1-2','http://.../test/test11/test112/');
d.add(5, 1,'test1-2','http://.../test/test12/');
d.add(6, 5,'test1-2-1','http://.../test/test12/test121/');
d.add(7, 5,'test1-2-2','http://.../test/test12/test122/');
d.add(8, 0,'test2','http://.../test2/');
d.add(9, 8,'test2-1','http://.../test2/test21/');
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
スクリーンショットと JavaScript(のカテゴリー)の対応はなんとなくお分かりになると思いますが、
d.add(...)
の行で、カテゴリー部分を表示させています。
本エントリーでは、Movable Type のネイティブタグのみで、このカテゴリーを表示する部分の JavaScript を生成します。
2.dTree のカテゴリー表示部分のフォーマット
先程も簡単に紹介しましたが、JavaScript でカテゴリーを表示する部分は add 関数がキモとなっており、関数のパラメータは、
d.add([*1],[*2],[カテゴリー名],[カテゴリーのURL *3]);
- *1:カテゴリーに一意に割り当てられたdTree用のカテゴリー番号
- *2:そのカテゴリーが属する親カテゴリーの番号
"0"はdTreeのルートに属する場合(=最上位のカテゴリー) - *3:dTreeの生成するa要素のhref属性になります。
となっています。
上記の add 関数部分を、サブカテゴリーリストを出力するサブテンプレートを応用して作成します。以下、add 関数の各パラメータをどのようなロジックで作成するかという解説を交えながら、ネイティブなテンプレートを組み立てていきます。
3.各パラメータ用のデータ生成方法
3.1 第1パラメータ用のデータ生成
第1パラメータはカテゴリーに番号を順に付与していけば良いだけので、リスト1のように、
リスト1
<$mt:setvar name="cat_number" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
d.add(<$mt:getvar name="cat_number"$>,~略~);
<$MTSubCatsRecurse$>
</MTTopLevelCategories>
とすれば良いことが分かります。
1行目でカテゴリー番号保持用の変数(cat_number)を1で初期化し、MTTopLevelCategories タグのループ内でインクリメントしていきます。
そしてインクリメント後に add 関数の第1パラメータに表示させればOKです。
3.2 第2パラメータ用のデータ生成
第2パラメータの、自カテゴリーの属する親カテゴリー番号を算出する方法は色々なアプローチがあると思いますが、ここでの方法は、まず算出に必要なデータとして、現在処理されているカテゴリーの階層をインデックスとした自カテゴリー番号を、配列の変数として保持します。
「カテゴリーの階層」は、親カテゴリーの階層は0、子カテゴリーの階層は1、孫カテゴリーの階層は2...、という具合に、数値で表すこととします。
「カテゴリーの階層をインデックスとした自カテゴリー番号を、配列の変数として保持」とは、例えば一番最初の「カテゴリー1」を処理している時、このカテゴリーはルート階層(数値で表すと0)に属するので、
tree[0]=1
という変数を作成することを指しています。左辺の変数 tree のインデックス0が階層の番号を示し、右辺の1がカテゴリー番号を示します。
「カテゴリー2」を処理している時、このカテゴリーは親カテゴリー(数値で表すと1)に属するカテゴリーなので、
tree[1]=2
という変数を作成します。
この規則によって、各カテゴリーを処理する時には、刻々と内容が書き換わる、次のような配列が作成されます。
- カテゴリー1の処理中:tree[0]=1
- カテゴリー2の処理中:tree[1]=2
- カテゴリー3の処理中:tree[2]=3
- カテゴリー4の処理中:tree[2]=4
- カテゴリー5の処理中:tree[1]=5
- カテゴリー6の処理中:tree[2]=6
- カテゴリー7の処理中:tree[2]=7
- カテゴリー8の処理中:tree[0]=8
- カテゴリー9の処理中:tree[1]=9
少し話が難しくなりますが、このデータは次回の繰り返し処理で利用するためのものです。つまり、カテゴリー1の処理中に作成された、一番最初の、
tree[0]=1
は(MTTopLevelCategories の)繰り返し処理の中でそのまま保持されており、次のカテゴリー2の処理の時に利用される、ということだけをとりあえず覚えていてください。
前置きが長くなりましたが、上記のデータを作成するサブテンプレートは、リスト2のようになります(青色はリスト1からの追加部分)。
リスト2
<$mt:setvar name="cat_number" value="1"$>
<$mt:setvar name="level" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
<$mt:setvar name="tree[$level]" value="$cat_number"$>
d.add(<$mt:getvar name="cat_number"$>,~略~);
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="++"$>
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="--"$>
</MTTopLevelCategories>
2行目で配列インデックス用の変数levelを初期化し、5行目で、処理中のカテゴリー番号を、現在の階層をインデックスとした配列データに保持します。
階層の数値の増減は、MTSubCatsRecurse の直前と直後で操作しています。
プログラミングに不慣れな方には分かりにくいのですが、MTSubCatsRecurseはいわゆる再帰処理を行うためのタグで、現在処理しているカテゴリーに子カテゴリーが存在する場合、MTSubCatsRecurse の内容を取り出し、 MTTopLevelCategories の中で処理します。
つまり MTSubCatsRecurse は次の階層を処理するための再帰データとなるので、その直前で変数 level をインクリメントすることで、階層用のデータがインクリメントされます。
また、MTSubCatsRecurse の直後でデクリメントすれば、階層の数値を親カテゴリーの階層に戻せます。
さらに MTSubCatsRecurse の中に孫カテゴリーデータが存在すれば、変数 level はさらにインクリメントされることになります。
これでdTreeに必要なデータが揃いましたので、あとは子カテゴリーが属する親カテゴリーのカテゴリー番号を求めるだけです。
これは、現在処理されているデータの階層からデクリメントした配列の値、つまり自カテゴリーの上位の階層のカテゴリー番号を取得すればいい訳です。
言い換えると、例えば2行目の、
tree[1]=2
の親カテゴリー番号を求める場合、上位の階層は
tree[0]
であり、その中に親のカテゴリー番号が設定されているので、配列のインデックスをデクリメント(-1)、つまり、
tree[1-1]
とすれば、tree[0] が求まります。あとはそこに設定されているカテゴリー番号1を取得すれば良い訳です。
また、4行目の
tree[2]=4
の親カテゴリーを求める場合、上位の階層は
tree[1]
となり、その中にカテゴリー番号が設定されているので、インデックスをデクリメント(-1)、つまり
tree[2-1]
とすれば、tree[1] が求まるので、あとはそこに設定されているカテゴリー番号2を取得すれば良い訳です。
話をまとめると、リスト3のようになります(青色はリスト2からの追加部分)。
リスト3
<$mt:setvar name="cat_number" value="1"$>
<$mt:setvar name="level" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
<$mt:setvar name="tree[$level]" value="$cat_number"$>
<mt:if name="level" eq="1">
d.add(<$mt:getvar name="cat_number"$>, 0,'<$MTCategoryLabel escape="js"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<mt:else>
d.add(<$mt:getvar name="cat_number"$>, <$mt:setvar name="tmp" value="$level"$><$mt:setvar name="tmp" op="--"$><$mt:getvar name="tree[$tmp]"$>,'<$MTCategoryLabel escape="js"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
</mt:if>
<$mt:setvar name="level" op="++"$>
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="--"$>
</MTTopLevelCategories>
追加した6~10行目のうち、9行目が該当します。
第2パラメータの値に配列変数treeのデータを表示しています。
6行目の MTIf で処理を振り分けている理由ですが、親カテゴリーを処理している場合、さらに上位の階層(つまり dTree のルート階層)データを取得しようとしますが、これまでの処理では設定されていないデータなので、エラーを避けるため、その場合のみ、7行目で第2パラメータに固定で0を設定するようにしています。
3.3 第3パラメータ用のデータ生成
第3パラメータのカテゴリー名には、<$MTCategoryLabel escape="js"$> を記述するだけです。なお、JavaScript として正常に動作するよう、escape モディファイアに "js" を指定します。
3.4 第4パラメータ用のデータ生成
第4パラメータには、リスト4のようにカテゴリーのリンク、
リスト4
<MTIfNonZero tag="MTCategoryCount">
<$MTCategoryArchiveLink$>
<MTElse>
javascript: void(0);
</MTElse>
</MTIfNonZero>
を設定します。
カテゴリーにブログ記事が1件以上投稿されている場合は、カテゴリーアーカイブへのリンクを設定し、投稿されていなければリンクの代わりに "javascript: void(0);" を設定し、リンクをクリックしてもページ遷移が発生しないようにしています。
最後に、第1パラメータと第2パラメータに表示される値をデクリメントします(青色はリスト3からの追加部分)。
リスト5
<$mt:setvar name="cat_number" value="1"$>
<$mt:setvar name="level" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
<$mt:setvar name="tree[$level]" value="$cat_number"$>
<mt:if name="level" eq="1">
d.add(<$mt:getvar name="cat_number" op="--"$>, 0,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<mt:else>
d.add(<$mt:getvar name="cat_number" op="--"$>, <$mt:setvar name="tmp" value="$level"$><$mt:setvar name="tmp" op="--"$><$mt:getvar name="tree[$tmp]" op="--"$>,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
</mt:if>
<$mt:setvar name="level" op="++"$>
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="--"$>
</MTTopLevelCategories>
これは変数cat_numberと変数levelの初期値を1にしているため、デクリメントしないと下のように、カテゴリー番号が2から開始されるためです。
d.add(2, 0,'test1','http://.../test/');
d.add(3, 2,'test1-1','http://.../test/test11/');
d.add(4, 3,'test1-1-1','http://.../test/test11/test111/');
d.add(5, 3,'test1-1-2','http://.../test/test11/test112/');
d.add(6, 2,'test1-2','http://.../test/test12/');
d.add(7, 6,'test1-2-1','http://.../test/test12/test121/');
d.add(8, 6,'test1-2-2','http://.../test/test12/test122/');
d.add(9, 0,'test2','http://.../test2/');
d.add(10, 9,'test2-1','http://.../test2/test21/');
変数cat_numberと変数levelの初期値を1にしているのは、初期値0の場合にリスト系のテンプレートタグで正常にインクリメントされない不具合を避けるためです。
これにdTree用の前後のスクリプトを加えれば完成です(青色はリスト5からの追加部分)。
リスト6
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'Categories','javascript: void(0);');
<$mt:setvar name="cat_number" value="1"$>
<$mt:setvar name="level" value="1"$>
<MTTopLevelCategories>
<$mt:setvar name="cat_number" op="++"$>
<$mt:setvar name="tree[$level]" value="$cat_number"$>
<mt:if name="level" eq="1">
d.add(<$mt:getvar name="cat_number" op="--"$>, 0,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<mt:else>
d.add(<$mt:getvar name="cat_number" op="--"$>, <$mt:setvar name="tmp" value="$level"$><$mt:setvar name="tmp" op="--"$><$mt:getvar name="tree[$tmp]" op="--"$>,'<$MTCategoryLabel escape="html"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
</mt:if>
<$mt:setvar name="level" op="++"$>
<$MTSubCatsRecurse$>
<$mt:setvar name="level" op="--"$>
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
よりエレガントな実装があると思いますが、その点はご容赦ください。
Movable Type 3 からのアップグレードによる「月別カテゴリーアーカイブ」の追加方法
2日ほど前に、このブログに「月別カテゴリーアーカイブ」を追加しました。カテゴリー・アーカイブの右下に表示されている「Category Monthly Archives」から辿れます。

追加した目的は2つあり、ひとつはカテゴリーアーカイブのナビゲーションを増やしたかったこと、もうひとつは Google 検索の「小粋空間」の検索で、どの程度のページ増加があるのかを確認したかったためです。
ページ増加の結果については最後に記すことにして、ここでは、Movable Type 3 からのアップグレードによる「月別カテゴリーアーカイブ」の追加方法を紹介します。
1.日付+カテゴリー(ユーザ)アーカイブについて
カテゴリーアーカイブやユーザアーカイブは、日付アーカイブ(年別・月別等)と異なり、記事数が増加することで1ページのファイルサイズが無限に増えていきます。
Movable Type 3 まではページ分割のカスタマイズでこの問題を回避していましたが、Movable Type 4 では、カテゴリーアーカイブとユーザアーカイブをさらに日付と組み合わせたアーカイブを作成することができるようになったので、例えば、あるカテゴリーアーカイブのトップには一定の記事数を表示し、過去の記事については「日付+アーカイブ」のページへリンクすれば、ページ分割として利用することができ、カテゴリーアーカイブ/ユーザアーカイブのトップページのファイルサイズを抑えることができます。
2.月別カテゴリーアーカイブの作成
Movable Type 4 の新規インストールでは「月別カテゴリーアーカイブ」がデフォルトで用意されているので、ここでは Movable Type 3 のアップグレードで Movable Type 4 運用のケースで「月別カテゴリーアーカイブ」を追加する場合について簡単に説明します。
2.1 アーカイブテンプレートの追加
既存のカテゴリー・アーカイブを利用する場合と、アーカイブを新規作成する場合で若干手順が異なります。
2.1.1 既存のカテゴリー・アーカイブを利用する場合
「デザイン」→「テンプレート」→「アーカイブテンプレート」→「カテゴリー・アーカイブ」を選択。

2.1.2 新規で作成する場合
「デザイン」→「テンプレート」→「アーカイブテンプレート」で、「アーカイブテンプレートを作成」の右にある「ブログ記事リスト」をクリック。

タイトルに「月別カテゴリー」を入力し(名前は何でもいいです)、編集画面の内容にカテゴリー・アーカイブと同じ内容を設定。
2.2 アーカイブマッピングを追加
ページ下にある「アーカイブマッピング」の「新しいアーカイブマッピングを作成」をクリック。

セレクトボックスで「カテゴリー - 月別」を選択し、「追加」をクリック。

これで、再構築をすれば「月別カテゴリーアーカイブ」が生成されます。
3.月別カテゴリーアーカイブリストへのリンクを追加
カテゴリーアーカイブのサイドバーに、月別カテゴリーアーカイブリストへのリンクを追加します。下は MT3 のデフォルトテンプレートに合わせたスタイルにしています。
<MTIf name="module_category-monthly_archives">
<MTIfArchiveTypeEnabled archive_type="Category-Monthly">
<div class="module-archives module">
<h2 class="module-header"><$MTArchiveTitle$>:月別アーカイブ</h2>
<div class="module-content">
<MTArchiveList archive_type="Category-Monthly">
<MTArchiveListHeader><ul class="module-list"></MTArchiveListHeader>
<li class="module-list-item"><a href="<$MTArchiveLink$>"><$MTArchiveTitle$></a></li>
<MTArchiveListFooter></ul></MTArchiveListFooter>
</MTArchiveList>
</div>
</div>
</MTIfArchiveTypeEnabled>
</MTIf>
4.完成例
トップページにある「趣味」というカテゴリーページへのリンクをクリックすると、

「趣味」カテゴリーのサイドバーに「趣味:月別アーカイブ」というリンクが表示されます。

5.検索結果ページ数増加について
「月別カテゴリーアーカイブ」追加による増加ページ数は、約800ページです。
で、「小粋空間」というキーワードで Google 検索すると、ここ最近は160 万件位で頭打ち状態だったのですが、今日調べてみると、260 万件まで増加していました(もう少し日が経つと減少するかもしれません)。

ちなみに、著名なブログでも検索結果ページ数は当ブログより少ないケースが少なくないのですが、ここまで検索結果ページ数が稼げているのは、テンプレート利用者のサイトに設定しているクレジットバナーのおかげだと感謝しています。
ブログ記事に同一カテゴリーのブログ記事リストを表示(MT4版)
Movable Type 4 で、ブログ記事アーカイブ(エントリーアーカイブ)に同一カテゴリーのブログ記事リスト(エントリーリスト)を表示するためのカスタマイズです。
質問を頂きましたので本エントリーにて解説致します。
Movable Type 3 までは、MTTagInvoke を使ったカスタマイズ「個別エントリーアーカイブに同一カテゴリーのエントリーを表示」が可能でしたが、Movable Type 4 ではこのプラグインが利用できなくなっています。
MT3 と同等のカスタマイズを行うには MTEntryCategoryEntries というプラグインがお勧めですが、ここでは、MTIf タグを使った方法を、順を追ってカスタマイズする形で紹介したいと思います。
読むのが面倒な方は、2項~4項のいずれかのサンプルを、そのままサイドバーに貼り付けてお使いください。
1.基本設定
ブログ記事に同一カテゴリーのブログ記事リストを表示する場合の基本形です。
<MTSetVarBlock name="entrycategory"><$MTEntryCategory$></MTSetVarBlock>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTEntries category="$entrycategory">
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTEntries>
</ul>
</dd>
1行目にある、
<MTSetVarBlock name="entrycategory"><$MTEntryCategory$></MTSetVarBlock>
で、<$MTEntryCategory$> の評価内容を取得し、entrycategory という MT の変数に設定します。
そして、
<MTEntries category="$entrycategory">
で、先に設定した変数 entrycategory の値を用いてブログ記事リストを特定のカテゴリーでフィルタリングしています。MTGetVar の name 属性で変数を使用する場合は $ を付与しませんが(下)、
<MTGetVar name="entrycategory">
MTEntries タグの category 属性に用いる場合は、$ を付与して、MT の変数であることを明示します。
2.特定のアーカイブのみで表示させる
1項の状態では、サイドバーをインクルードする全てのページで表示されてしまうため、ブログ記事アーカイブのみにも適用されてしまいます。
このリストをブログ記事アーカイブだけに表示させるには、リスト全体 MTIf タグで括ります。
<MTIf name="entry_template">
<MTSetVarBlock name="entrycategory"><$MTEntryCategory$></MTSetVarBlock>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTEntries category="$entrycategory">
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTEntries>
</ul>
</dd>
</MTIf>
1行目の MTIf タグの name 属性には、ブログ記事のみで有効になる "entry_template" という値を設定します。
<MTIf name="entry_template">
これでブログ記事アーカイブ以外では、このリストは表示されなくなります。
アーカイブで使える変数値については、「予約変数一覧 for Movable Type 4(その1)」にまとめてありますので、参考になれば幸いです。
3.現在のブログ記事タイトルをリストから除外する
2項までの設定では、現在表示されているブログ記事のタイトルも表示されてしまうので、次にこれを非表示にする制御を行います。
非表示にするには、現在表示されているブログ記事ページのID番号と、リスティングされているブログ記事のID番号を比較・判定する処理(青色部分)を追加します。
<MTIf name="entry_template">
<MTSetVarBlock name="entryid"><$MTEntryID$></MTSetVarBlock>
<MTSetVarBlock name="entrycategory"><$MTEntryCategory$></MTSetVarBlock>
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTEntries category="$entrycategory">
<MTSetVarBlock name="currententryid"><$MTEntryID$></MTSetVarBlock>
<MTIf name="currententryid" ne="$entryid">
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTIf>
</MTEntries>
</ul>
</dd>
</MTIf>
現在表示されているブログ記事ページのID番号は、2行目の
<MTSetVarBlock name="entryid"><$MTEntryID$></MTSetVarBlock>
で取得し、リスティングされているブログ記事ページのID番号は、MTEntries タグブロック内の
<MTSetVarBlock name="currententryid"><$MTEntryID$></MTSetVarBlock>
で取得しています。これで、
entryid:現在表示されているブログ記事ページのID番号
currententryid:リスティングされているブログ記事ページのID番号
となり、あとはこれを MTIf タグで判定します。
<MTIf name="currententryid" ne="$entryid">
ne 属性で判定しているので、判定結果が「真」、つまりお互いのブログ記事IDが等しくなければ、MTIf ブロック内の行を実行します。
4.リストが1件の場合はリストを非表示にする
前項の設定を行った場合、あるカテゴリーに属するブログ記事が1件の場合、リストに何も表示されなくなってしまいます。
これを回避するため、カテゴリーに属するブログ記事が1件の場合は、リスト全体を非表示にする制御を行います。
<MTIf name="entry_template">
<MTSetVarBlock name="entryid"><$MTEntryID$></MTSetVarBlock>
<MTSetVarBlock name="entrycategory"><$MTEntryCategory$></MTSetVarBlock>
<MTEntries category="$entrycategory">
<MTSetVarBlock name="entrycount"><$MTGetVar name="__counter__"$></MTSetVarBlock>
</MTEntries>
<MTUnless name="entrycount" eq="1">
<dt class="sidetitle">
Entries of this Category
</dt>
<dd class="side">
<ul>
<MTEntries category="$entrycategory">
<MTSetVarBlock name="currententryid"><$MTEntryID$></MTSetVarBlock>
<MTIf name="currententryid" ne="$entryid">
<li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li>
</MTIf>
</MTEntries>
</ul>
</dd>
</MTUnless>
</MTIf>
該当カテゴリーのブログ記事数のカウントには、MTEntries タグ内で __counter__ を利用することで取得しています。
ところが、__counter__ という変数は、
<$MTGetVar name="entrycount" value="__counter__"$>
では正常に値を取得できない(変数値がそのまま変数名に設定されてしまう)ので、MTSetVarBlock と MTGetVar を組み合わせて、
<MTSetVarBlock name="entrycount"><$MTGetVar name="__counter__"$></MTSetVarBlock>
としています。
そして、MTUnless タグを用いて、カウント値が "1" でない場合にブロック内を実行するように制御します。
<MTUnless name="entrycount" eq="1">
カテゴリー・アーカイブのカテゴリーリストで該当カテゴリーのエントリーのみを表示する
カテゴリー・アーカイブに表示されたカテゴリーリストで、該当カテゴリーのエントリーのみを表示するカスタマイズです。
ご質問を頂きましたので本エントリーにて紹介致します。
以下のサンプルの(X)HTMLは、当サイトの「XHTML 1.0 Strict 版テンプレート」をもとにしたマークアップですので、それ以外の配布テンプレートをご利用の場合は、dt / dd をそれぞれ div に直してください。
また、本カスタマイズは MT4 でも利用可能ですが、MT4 版は別エントリーで投稿したいと思います。
1.PHP 版
カテゴリー・アーカイブテンプレートの任意の位置に、下記のカテゴリーリストを設定してください。
ブログがPHP化されていることが前提です。
<MTIfArchiveTypeEnabled archive_type="Category">
<dt class="sidetitle">
Categories
</dt>
<dd class="side">
<?php $category = '<$MTCategoryLabel encode_php="1"$>'; ?>
<div id="categories">
<MTSubCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><$MTCategoryLabel$></a> [<$MTCategoryCount$>]
<?php if ($category == '<$MTCategoryLabel encode_php="1"$>') { ?>
<ul><MTEntries><li><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></li></MTEntries></ul>
<?php } ?>
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse max_depth="3">
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</div>
</dd>
</MTIfArchiveTypeEnabled>
2.JavaScript 版
1項と同様、カテゴリー・アーカイブテンプレートの任意の位置に、下記のカテゴリーリストを設定してください。
<MTIfArchiveTypeEnabled archive_type="Category">
<dt class="sidetitle">
Categories
</dt>
<dd class="side">
<script type="text/javascript">
//<![CDATA[
var category = '<$MTCategoryLabel encode_js="1"$>';
//]]>
</script>
<div id="categories">
<MTSubCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><$MTCategoryLabel$></a> [<$MTCategoryCount$>]
<script type="text/javascript">
//<![CDATA[
if (category == '<$MTCategoryLabel encode_js="1"$>') {
document.write('<ul><MTEntries><li><a href="<$MTEntryPermalink$>"><$MTEntryTitle encode_js="1"$></a></li></MTEntries></ul>');
}
//]]>
</script>
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse max_depth="3">
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</div>
</dd>
</MTIfArchiveTypeEnabled>
カテゴリーリストにエントリータイトルを表示する
Movable Type のカテゴリーリストにエントリータイトルを表示するカスタマイズです。
オーソドックスなカスタマイズですが、MT をブログとして用いるのではなく、投稿するエントリー数がある程度決まっていて、それらを更新するというスタイルで使う場合、カテゴリーリストをメニューリストとして代用することができ、非常に有効な方法です。
1.デフォルトテンプレートの場合
カテゴリーリストに青色の部分を追加してください。
<MTIfArchiveTypeEnabled archive_type="Category"><div class="module-categories module">
<h2 class="module-header">カテゴリー</h2>
<div class="module-content">
<MTTopLevelCategories>
<MTSubCatIsFirst><ul class="module-list"></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li class="module-list-item"><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a>
<ul class="module-list"><MTEntries><li class="module-list-item"><a href="<$MTEntryPermalink$>"><$MTEntryTitle encode_html="1"$></a></li></MTEntries></ul>
<MTElse>
<li class="module-list-item"><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTTopLevelCategories>
</div>
</div>
</MTIfArchiveTypeEnabled>
2.公開テンプレートの場合
カテゴリーリストに青色の部分を追加してください。サンプルは XHTML 1.0 Strict 版を使っていますが、それ以外のものでも追加位置と追加内容は同じです。
<MTIfArchiveTypeEnabled archive_type="Category">
<dt class="sidetitle">
Categories
</dt>
<dd class="side">
<div id="categories">
<MTSubCategories>
<MTSubCatIsFirst><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>]
<ul><MTEntries><li><a href="<$MTEntryPermalink$>"><$MTEntryTitle encode_html="1"$></a></li></MTEntries></ul>
<MTElse>
<li><MTCategoryLabel>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse max_depth="3">
</li>
<MTSubCatIsLast></ul></MTSubCatIsLast>
</MTSubCategories>
</div>
</dd>
</MTIfArchiveTypeEnabled>
dTree によるサブカテゴリーリスト for Movable Type
dTree というエクスプローラー風のツリー表示スクリプトを利用した、Movable Type のサブカテゴリーリストのツリー化カスタマイズをご紹介します。
表示は左のスクリーンショットのようになり、「+」「-」をクリックするとツリーを開閉することができます。また、カテゴリー名をクリックすると該当のカテゴリーページにジャンプします。一番下の「open all」「close all」をクリックすると全ツリーの一括開閉もできます。
動作についてはサンプルをご利用ください。
後で気がつきましたが、「MovableType備忘録」さんでも同じようなカスタマイズを公開されています。
以下、カスタマイズ方法です。
1.スクリプトのダウンロード
Destroydrop » Javascripts » Tree の右上にある、Download の dtree.zip のリンクをクリックしてダウンロード。

2.スクリプトのアップロード
アーカイブを解凍した中にある下記のファイルまたはディレクトリを index.html と同じディレクトリにアップロード(他は使いません)。
/img
dtree.css
dtree.js
3.画像ファイルパスの修正
dtree.js を任意のエディタで開き、下記の
this.icon = {
root : 'img/base.gif',
folder : 'img/folder.gif',
folderOpen : 'img/folderopen.gif',
node : 'img/page.gif',
empty : 'img/empty.gif',
line : 'img/line.gif',
join : 'img/join.gif',
joinBottom : 'img/joinbottom.gif',
plus : 'img/plus.gif',
plusBottom : 'img/plusbottom.gif',
minus : 'img/minus.gif',
minusBottom : 'img/minusbottom.gif',
nlPlus : 'img/nolines_plus.gif',
nlMinus : 'img/nolines_minus.gif'
};
を下のようにご自身のドメイン(ブログのURL)を追加します。
this.icon = {
root : 'http://user-domain/img/base.gif',
folder : 'http://user-domain/img/folder.gif',
folderOpen : 'http://user-domain/img/folderopen.gif',
node : 'http://user-domain/img/page.gif',
empty : 'http://user-domain/img/empty.gif',
line : 'http://user-domain/img/line.gif',
join : 'http://user-domain/img/join.gif',
joinBottom : 'http://user-domain/img/joinbottom.gif',
plus : 'http://user-domain/img/plus.gif',
plusBottom : 'http://user-domain/img/plusbottom.gif',
minus : 'http://user-domain/img/minus.gif',
minusBottom : 'http://user-domain/img/minusbottom.gif',
nlPlus : 'http://user-domain/img/nolines_plus.gif',
nlMinus : 'http://user-domain/img/nolines_minus.gif'
};
4.script 要素追加
dTree を表示したいテンプレートに、下記の link 要素と script 要素を追加します。
<link rel="stylesheet" href="<$MTBlogURL$>dtree.css" type="text/css" />
<script type="text/javascript" src="<$MTBlogURL$>dtree.js"></script>
5.dTree サブカテゴリーリスト表示用タグ設定
テンプレートで、サブカテゴリーリストを表示したい位置に下記のタグを設定してください。
表示用タグは PHP 版と JavaScript 版を用意しました。表示される結果はどちらも同じですが、PHP 版の方がページのファイルサイズを抑えることができます。
5.1 PHP版
このタグを設定する場合、PHP化を行っていることが前提です。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1,'SubCategories','javascript: void(0);');
<?php $a = 0; $b = 0; $link = array(); ?>
<MTTopLevelCategories>
<?php $link[$b] = ++$a; if(!$b) { ?>
d.add(<?php echo $a ?>, 0,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } else { if(!$link[$b - 1]) { ?>
d.add(<?php echo $a ?>, 1,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php } else { ?>
d.add(<?php echo $a ?>, <?php echo $link[$b - 1] ?>,'<$MTCategoryLabel encode_php="1"$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
<?php }} $b++; ?>
<MTSubCatsRecurse max_depth="3">
<?php $b--; ?>
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
5.2 JavaScript 版
こちらは JavaScript 版です。
<script type="text/javascript">
d = new dTree('d');
d.config.useCookies=false;
d.add(0, -1, 'SubCategories','javascript: void(0);');
var a = 0;
var b = 0;
var link = new Array();
<MTTopLevelCategories>
link[b] = ++a;
if(!b) {
d.add(a, 0,'<$MTCategoryLabel$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
} else {
if(!link[b - 1]) {
d.add(a, 1,'<$MTCategoryLabel$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
} else {
d.add(a, link[b - 1],'<$MTCategoryLabel$>','<MTIfNonZero tag="MTCategoryCount"><$MTCategoryArchiveLink$><MTElse>javascript: void(0);</MTElse></MTIfNonZero>');
}
}
b++;
<MTSubCatsRecurse max_depth="3">
b--;
</MTTopLevelCategories>
document.write(d);
</script>
<p style="text-align:center"><a href="javascript: d.openAll();">open all</a> | <a href="javascript: d.closeAll();">close all</a></p>
以上です。
関連記事:
2007.06.26
3項を追加しました。
2007.12.01
PHP版タグの MTCategoryLabel タグに encode_php="1" を追加しました。
2007.12.18
MTSubCategories タグを MTTopLevelCategories タグに変更しました。
サブカテゴリーリストのエクスプローラ風折りたたみ
当サイトでこれまで紹介してきた「サブカテゴリーリストの折りたたみ」カスタマイズは、「折りたたみマーク(+ツリー化)」という形式が主体でしたが、新たに Windows のエクスプローラのツリー表示と同じように、タイトルの左側に折りたたみ画像を表示し、折りたたみ状態によって画像を切り替えられるカスタマイズを紹介致します。
ここでは、Movable Type のデフォルトテンプレート(スクリーンショット)および公開テンプレートでのカスタマイズ方法について説明します。
1.スクリプトのダウンロード
下記のリンクをクリックし、リンク先のページにある menufolder.js のリンクをクリックしてダウンロードしてください。
2.menufolder.js の設定変更
ダウンロードした menufolder.js を任意のエディタで開き、下記のように該当部分を青色の内容に変更してください。
// サブカテゴリー用折りたたみマーク
// 上:閉じている状態で表示されるマーク
// 下:開いている状態で表示されるマーク
var openMarkForSubCategories = '<img src="close.png" style="border:none;vertical-align:middle;" />';
var closeMarkForSubCategories = '<img src="open.png" style="border:none;vertical-align:middle;" />';
// サブカテゴリー用折りたたみマーク挿入位置
// カテゴリー前に折りたたみマークを配置:true
// カテゴリー後に折りたたみマークを配置:false
var preMarkForSubCategory = true;
// サブカテゴリーのタイトルとマークのスペース
var offsetForTitleAndMarkOfSubcategory = 1;
3.スクリプトのアップロード
menufolder.js の修正が終わったら保存し、メインページと同じディレクトリにアップロードしてください。
4.テンプレートに script 要素追加
サブカテゴリーリストの折りたたみを利用する各テンプレートの </head> の直前に下記のタグを追加してください。charset 属性は menufolder.js の文字コードを指定してください(分からなければとりあえずサンプルのまま貼り付けてください)。
<script type="text/javascript" src="<$MTBlogURL$>menufolder.js" charset="utf-8"></script>
5.テンプレートにサブカテゴリーリスト表示用タグを追加
デフォルトテンプレートの場合は5.1項、公開テンプレートの場合は5.2項のサブカテゴリーリスト表示用タグを、表示したいテンプレートの任意の位置に追加します。
5.1 公開テンプレート
<div class="sidetitle">
Categories
</div>
<div class="side">
<div id="categories">
<MTTopLevelCategories>
<MTSubCatIsFirst><MTHasParentCategory><div id="subcategories<MTParentCategory><$MTCategoryID$></MTParentCategory>list"></MTHasParentCategory><ul></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li><MTHasSubCategories><div class="subcategories" id="subcategories<$MTCategoryID$>name"></MTHasSubCategories><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>] <MTHasSubCategories></div></MTHasSubCategories>
<MTElse>
<li><MTHasSubCategories><div class="subcategories" id="subcategories<$MTCategoryID$>name"></MTHasSubCategories><MTCategoryLabel> <MTHasSubCategories></div></MTHasSubCategories>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul><MTHasParentCategory></div></MTHasParentCategory></MTSubCatIsLast>
</MTTopLevelCategories>
</div>
</div>
<script type="text/javascript">
<!--
<MTTopLevelCategories>
<MTHasSubCategories>FoldNavigation('subcategories<$MTCategoryID$>','off',false);</MTHasSubCategories>
<MTSubCatsRecurse>
</MTTopLevelCategories>
//-->
</script>
5.2 デフォルトテンプレート
<div class="module-categories module">
<h2 class="module-header">カテゴリー</h2>
<div class="module-content" id="categories">
<MTTopLevelCategories>
<MTSubCatIsFirst><MTHasParentCategory><div id="subcategories<MTParentCategory><$MTCategoryID$></MTParentCategory>list"></MTHasParentCategory><ul class="module-list"></MTSubCatIsFirst>
<MTIfNonZero tag="MTCategoryCount">
<li class="module-list-item"><MTHasSubCategories><div class="subcategories" id="subcategories<$MTCategoryID$>name"></MTHasSubCategories><a href="<$MTCategoryArchiveLink$>" title="<$MTCategoryDescription$>"><MTCategoryLabel></a> [<$MTCategoryCount$>] <MTHasSubCategories></div></MTHasSubCategories>
<MTElse>
<li class="module-list-item"><MTHasSubCategories><div class="subcategories" id="subcategories<$MTCategoryID$>name"></MTHasSubCategories><MTCategoryLabel> <MTHasSubCategories></div></MTHasSubCategories>
</MTElse>
</MTIfNonZero>
<MTSubCatsRecurse>
</li>
<MTSubCatIsLast></ul><MTHasParentCategory></div></MTHasParentCategory></MTSubCatIsLast>
</MTTopLevelCategories>
</div>
</div>
<script type="text/javascript">
<!--
<MTTopLevelCategories>
<MTHasSubCategories>FoldNavigation('subcategories<$MTCategoryID$>','initState',false);</MTHasSubCategories>
<MTSubCatsRecurse>
</MTTopLevelCategories>
//-->
</script>
6.スタイルシート変更
デフォルトテンプレートの場合は6.1項、公開テンプレートの場合は6.2項の CSS をスタイルシートに追加してください。
6.1 デフォルトテンプレート
#categories ul {
margin-left: 0;
padding-left: 0;
list-style: none;
}
#categories ul li {
padding-left: 15px;
}
div .subcategories {
margin-left: -15px;
}
6.2 公開テンプレート
#categories ul {
margin: 0 0 0 2px;
padding: 0;
list-style: none;
}
#categories ul li {
margin: 2px 0 2px 5px;
padding-left: 10px;
list-style: none;
}
#categories li li {
margin: 2px 0 2px 5px;
padding-left: 10px;
list-style: none;
}
div .subcategories {
margin-left: -15px;
}
公開テンプレートの場合は、すでに設定されている下記の CSS を削除してください。
.side #categories ul {
padding-left: 16px;
}
.side #categories ul ul {
padding-left: 10px;
}
.side #categories li {
list-style-type: circle;
}
7.画像のアップロード
下記の折りたたみマーク画像をダウンロード(Windows であれば右クリックして「名前を付けて画像を保存」を選択)し、メインページと同じディレクトリにアップロードしてください。
画像はお好みのものをご利用ください。
サブカテゴリーリストのツリー画像で親カテゴリーのみ異なる画像を表示する
先日エントリーした「CSS 変更(2007.02.11)」でお知らせした通り、サブカテゴリーリストの親カテゴリーだけ異なる画像を表示させるカスタマイズをご紹介致します。

この変更を行なえば、ツリー画像が各親カテゴリー内に閉じた形で表示されるようになります。またカテゴリー表示が長大になる場合、従来の表示では親カテゴリーのツリー画像が途切れる可能性が高かったのですが、この方法であればある程度問題なく表示されると思います。
変更方法は、CSS の修正と親カテゴリー用の画像の用意です。
元のサンプルは「サブカテゴリーリストの折りたたみ+ツリー化 for Movable Type」を利用していますが、CSS についてはブログツール・ブログサービスに依存しませんので、変更箇所を確認しながら修正してください。
スクリーンショットの完成例で使用している親カテゴリーのリストマークは、下記から頂きました。
全く同じマークは下から 30 番目あたりにあります。
下記にスクリーンショットと同じ変更をした CSS を示します。変更箇所は赤、追加は青で示していますが、お好みに応じて適宜修正してください。
変更前
ul.tree {
margin: 0 0 0 5px;
padding: 0;
font-size: 9px;
list-style: none;
}
ul.tree ul {
margin: 0;
padding: 0;
}
ul.tree li {
margin: 0;
padding: 0 0 0 13px;
background: url(tree_lst.gif) no-repeat 2px 0;
list-style: none;
}
ul.tree li.tree_end {
background: url(tree_end.gif) no-repeat 2px 0;
list-style: none;
}
変更後
ul.tree {
margin: 0 0 0 3px;
padding: 0;
font-size: 9px;
list-style: none;
}
ul.tree ul {
margin: 0;
padding: 0;
}
ul.tree li {
margin: 0px;
padding: 0 0 0 17px;
background: url([親カテゴリー用画像ファイル]) no-repeat 1px 0.15em;
list-style: none;
}
ul.tree li li {
margin: 0;
padding: 0 0 0 15px;
background: url(tree_lst.gif) no-repeat 4px 0;
list-style: none;
}
ul.tree li li.tree_end {
background: url(tree_end.gif) no-repeat 4px 0;
list-style: none;
}
ご覧の通り、親カテゴリー用の li 要素セレクタと、子カテゴリー用の li 要素セレクタを分割しています。子カテゴリーは、li 要素セレクタを重ねて指定し、li 要素が再帰的に出現する場合のみ、ツリー画像を表示するようにしています。
参考までにサンプルのHTMLマークアップも掲載しておきます。折りたたみ用の div 要素が含まれてやや複雑になってますが予めご了承ください。
<ul class="tree">
<li class="tree">
<div class="subcategories" id="subcategories9name"><a href="..." title="9">ブログ</a> [1]</div>
<div id="subcategories9list">
<ul class="tree">
<li class="tree_end">
<div class="subcategories" id="subcategories10name"><a href="..." title="10">Movable Type</a> [1]</div>
<div id="subcategories10list">
<ul class="tree">
<li class="tree"><a href="..." title="11">カスタマイズ</a> [1]</li>
<li class="tree_end"><a href="..." title="12">テンプレート</a> [2]</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="tree">
<div class="subcategories" id="subcategories1name"><a href="..." title="1">日記</a> [1]</div>
<div id="subcategories1list">
<ul class="tree">
<li class="tree_end"><a href="..." title="2">食事</a> [1]</li>
</ul>
</div>
</li>
<li class="tree_end">
<div class="subcategories" id="subcategories3name"><a href="..." title="3">趣味</a> [1]</div>
<div id="subcategories3list">
<ul class="tree">
<li class="tree">
<div class="subcategories" id="subcategories5name"><a href="..." title="5">パソコン</a> [1]</div>
<div id="subcategories5list">
<ul class="tree">
<li class="tree"><a href="..." title="7">Linux</a> [1]</li>
<li class="tree_end"><a href="..." title="8">Windows</a> [1]</li>
</ul>
</div>
</li>
<li class="tree_end">
<div class="subcategories" id="subcategories4name"><a href="..." title="4">車</a> [1]</div>
<div id="subcategories4list">
<ul class="tree">
<li class="tree_end"><a href="..." title="6">VW</a> [1]</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>


