Movable Typeでタグのインクリメンタルサーチを実現する
Movable Typeの検索フォームを使ったタグ検索で、インクリメンタルサーチが行えるようにするカスタマイズです。
このカスタマイズを行えば、次のようにタグ文字列を1文字入力するたびに、候補を表示してくれます。ご覧のとおり、途中の文字の検索もできます。

日本語の検索も可能です。

タグのインクリメンタルサーチを導入すれば、タグクラウドのようにページを占有する必要がなくなります。タグ数が多いほど有効です。頻度の高いタグだけを表示するタグ一覧と併用するという手もあります。
ここでは「クラシックブログ」テーマに適用する方法を紹介します。
検索フォームを使ったタグ検索の動作については「Movable Typeの検索フォームでタグ検索をする」をご覧ください。
1.ライブラリのダウンロード・アップロード
「suggest.js - 入力補完ライブラリ」のページにアクセスして、「suggest.js」をダウンロードします。このライブラリはMITライセンスです(Ver2.1以降)。
ダウンロードしたsuggest.jsをブログのサイトパスにアップロードします。
2.タグリストの作成
タグのインクリメンタルサーチ用のリストを作成します。
「デザイン」→「テンプレート」→「インデックステンプレートの作成」をクリック。

次の内容を入力して「保存」をクリックし、保存後再構築を行ってください。
- タイトル:タグリスト(何でもいいです)
- 出力ファイル名:list.js
- テンプレートの内容:以下
var list = [<mt:Tags>
"<mt:TagName />"<mt:unless name="__last__">,</mt:unless></mt:Tags>
];
3.script要素の追加
「HTMLヘッダー」テンプレートモジュールの「<$mt:CCLicenseRDF$>」の直前に下記の内容を追加します。
<script type="text/javascript" src="<$mt:BlogURL$>suggest.js"></script>
<script type="text/javascript" src="<$mt:BlogURL$>list.js"></script>
<script type="text/javascript">
var start = function(){
new Suggest.Local("search",
"suggest",
list,
{ dispMax: 100, highlight: true});
};
window.addEventListener ?
window.addEventListener('load', start, false) :
window.attachEvent('onload', start);
</script>
「Suggest.Local」のパラメータの意味は次の通りです。
- 第1パラメータ:入力テキストフィールドのid属性値
- 第2パラメータ:結果表示フィールドのid属性値
- 第3パラメータ:インクリメンタルサーチの検索対象となる配列変数名
- 第4パラメータ(オプション):dispMaxは最大表示数、highlightはマッチした文字の強調表示
第4パラメータのオプションは他にもいろいろあるので、「suggest.js - 入力補完ライブラリ」のページを参照してください。
4.CSSの追加
インクリメンタルサーチの結果表示エリアのスタイルを、「スタイルシート」インデックステンプレートに追加します。赤色は「クラシックブログ」のために追加した部分です。
/* インクリメンタルサーチ結果表示エリア全体 */
#suggest {
position: absolute;
background-color: #FFFFFF;
border: 1px solid #CCCCFF;
width: 111px;
font: 13px arial,helvetica,hirakakupro-w3,osaka,"ms pgothic",sans-serif;
z-index:100;
margin-top: -3px;
}
/* 選択部分 */
#suggest div {
display: block;
width: 107px;
padding: 2px;
overflow: hidden;
white-space: nowrap;
}
/* カーソル選択時 */
#suggest div.select{
color: #FFFFFF;
background-color: #3366FF;
}
/* マウスオーバー時 */
#suggest div.over{
background-color: #99CCFF;
}
/* 強調文字 */
#suggest strong{
font-weight: bold;
color: #e50003;
}
/* 強調文字選択時 */
#suggest div.select strong{
font-weight: bold;
color: pink;
}
.widget-search {
overflow: hidden;
width: 100%;
}
.widget-search-content {
font-size: 11px;
margin: 5px 15px 20px;
}
5.検索フォームの追加
インクリメンタルサーチ用のタグ検索フォームをウィジェットに追加します。
「デザイン」→「ウィジェット」→「ウィジェットの作成」をクリック。

次の内容を入力して「保存」をクリック。
- タイトル:タグ検索(何でもいいです)
- テンプレートの内容:以下
<div class="widget-search">
<h3 class="widget-header">検索</h3>
<div class="widget-search-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input autocomplete="off" type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
</form>
<div id="suggest" style="display:none;"></div>
</div>
</div>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
赤色がインクリメンタル検索のための追加部分です。「autocomplete="off"」はブラウザの補完機能をオフにするためのもの、form要素直後のdiv要素はインクリメンタルサーチ結果を表示するエリアです。
このサブテンプレートは「検索」ウィジェットテンプレートとほぼ同じ内容ですが、input要素の青色部分を「search」から「tag」に変更しています。
また、class属性値「widget」「widget-content」をはずしています。理由はそれらのclass属性値に設定されているpositionプロパティがインクリメンタルサーチの表示に干渉するためです。
class属性値「widget」「widget-content」をはずすとpositionプロパティ以外のプロパティもはずれてしまうので、widget-searchセレクタ、widget-search-contentセレクタで補っています。
6.検索フォームをウィジェットセットに追加
5項で作成した「タグ検索」ウィジェットを、表示したいウィジェットセットの「インストール済み」にドラッグして「保存」をクリックします。

これですべての設定が完了しましたので、全体を再構築して、タグ検索フォームでインクリメンタルサーチが動作することを確認してください。
Movable Typeの検索フォームでタグ検索をする
Movable Typeに限らず、ブログツールやCMSにおけるタグ検索はタグクラウドや記事中のタグリンクをクリックして、同じタグの記事を表示する仕組みになっていますが、検索フォームを使ってタグ検索するカスタマイズを紹介します。
この内容は、MTQにあった質問に対する回答の一部です。以前、このブログか書籍で同じ記事を書いた記憶があるのですが、見当たらないため本エントリーで展開します。
1.カスタマイズのイメージ
タグ検索フォームを新たに作り、フォームにタグ文字列を入力して検索します。

次のようにタグ検索結果が表示され、右サイドバーにはタグの一覧も表示されます。
2.タグ検索フォーム
次のコードをMTのウィジェットとして登録します。
<div class="widget-search widget">
<h3 class="widget-header">検索</h3>
<div class="widget-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
</form>
</div>
</div>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
通常の検索フォームと異なるのは次の赤色部分のみです。
<input type="text" id="search" class="ti" name="tag" value="<$mt:SearchString$>" />
カスタマイズするのはこのタグ検索フォームだけです。検索結果はシステムテンプレートの「検索結果」をそのまま使います。
3.記事検索とタグ検索を切り替えるラジオボタンをつける
ちょっと工夫をすれば、検索フォームに記事検索とタグ検索を切り替えるラジオボタンをつけることも可能です。

次のコードをMTのウィジェットとして登録します。赤色部分が2項のソースの差分です。jQuery本体は適宜「ヘッダー」モジュールなどに追加して読み込ませてください。
<div class="widget-search widget">
<h3 class="widget-header">検索</h3>
<div class="widget-content">
<form method="get" action="<$mt:CGIPath$><$mt:SearchScript$>">
<input type="text" id="search" class="ti" name="search" value="<$mt:SearchString$>" />
<mt:If name="search_results">
<input type="hidden" name="IncludeBlogs" value="<$mt:SearchIncludeBlogs$>" />
<mt:Else>
<input type="hidden" name="IncludeBlogs" value="<$mt:BlogID$>" />
</mt:If>
<input type="hidden" name="limit" value="<$mt:SearchMaxResults$>" />
<input type="submit" accesskey="4" value="検索" />
<input type="radio" name="search_id" value="search" checked="checked" /> 記事検索
<input type="radio" name="search_id" value="tag" /> タグ検索
</form>
</div>
</div>
<script type="text/javascript">
jQuery(function() {
jQuery('input[name="search_id"]').change(function(){
jQuery('#search').attr('name', jQuery(this).val());
});
<mt:If name="search_results">
<mt:IfTagSearch>
jQuery('input[name="search_id"]').val(['tag']);
</mt:IfTagSearch>
</mt:If>
});
</script>
<mt:If name="search_results">
<mt:IfTagSearch>
<div class="widget-tags widget">
<h3 class="widget-header">タグ</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<li><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;"><$mt:TagName$> (<$mt:TagCount$>)</a></li>
</mt:Tags>
</ul>
</div>
</div>
</mt:IfTagSearch>
</mt:If>
検索は以下のjQueryで切り替えています。
jQuery(function() {
jQuery('input[name="search_id"]').change(function(){
jQuery('#search').attr('name', jQuery(this).val());
});
<mt:If name="search_results">
<mt:IfTagSearch>
jQuery('input[name="search_id"]').val(['tag']);
</mt:IfTagSearch>
</mt:If>
});
ラジオボタンの切り替えでchangeメソッドが起動して、input要素の値を書き換えています。
MTテンプレートタグを使っているのは、タグ検索結果ページを表示したときに、ラジオボタンがデフォルトの選択状態にせず「タグ検索」を選択した状態にするためのものです。
4.インクリメンタル検索
さらに工夫をすればタグのインクリメンタル検索が可能です。これについては別途エントリーしたいと思います。
Movable Typeのテンプレートタグにおけるプライベートタグの正しい指定方法
Movable Typeでプライベートタグを使いたいときに指定する「include_privateモディファイア」が利用可能なテンプレートタグや、MTEntryIfTaggedタグでのプライベートタグの正しい判定方法について調べましたので、本エントリーで紹介します。
1.include_privateモディファイアが利用可能なテンプレートタグ
include_privateモディファイアは、プライベートタグを処理に含めたいときに指定するモディファイアです。
include_privateモディファイアが利用可能なテンプレートタグは、次の6種類です。
- MTEntryTags
- MTPageTags
- MTAssetTags
- MTEntryIfTagged
- MTPageIfTagged
- MTAssetIfTagged
MTEntryTagsタグでプライベートタグを対象にするには、次のようにinclude_privateモディファイアに「1」を設定します。
<mt:EntryTags include_private="1">
:
</mt:EntryTags>
include_privateモディファイアを指定しない場合は、「include_private="0"」と同じ意味になります。
2.MTXXXIfTaggedタグにおけるプライベートタグ判定方法
例えばMTEntryIfTaggedタグを使って、ブログ記事にプライベートタグ「@foo」が設定されていることを判定するには、前述のMTEntryTagsタグのお作法に従えば、次のようにtagモディファイアとinclude_privateモディファイアをセットで記述するように思われます。
<mt:EntryIfTagged tag="@foo" include_private="1">
:
</mt:EntryIfTagged>
ところが上記は誤りで、正解は次のようにtagモディファイアのみを記述します(正解はもうひとつありますが、話の流れ上、後述します)。
<mt:EntryIfTagged tag="@foo">
:
</mt:EntryIfTagged>
include_privateモディファイアを記述しない理由は、tagモディファイアで値を指定した場合、include_privateモディファイア自体が参照されなくなるためです。
ソースコードをトレースすると、MTEntryIfTaggedで起動される_hdlr_entry_if_taggedの処理は次のようになっています。tagモディファイアに値を設定している場合、赤色の部分が実行されます。
sub _hdlr_entry_if_tagged {
my ( $ctx, $args, $cond ) = @_;
my $entry = $ctx->stash('entry');
return 0 unless $entry;
my $tag
= defined $args->{name}
? $args->{name}
: ( defined $args->{tag} ? $args->{tag} : '' );
if ( $tag ne '' ) {
$entry->has_tag($tag);
}
else {
my @tags = $entry->tags;
@tags = grep /^[^@]/, @tags
if !$args->{include_private};
return @tags ? 1 : 0;
}
}
赤色部分で起動されているhas_tagの処理は、次のようになっています。
sub has_tag {
my $obj = shift;
my ($tag) = @_;
$tag = $tag->name if ref $tag;
foreach ( $obj->tags ) {
return 1 if $tag eq $_;
}
0;
}
このメソッドでは、引数に設定されたタグ名とオブジェクト(ブログ記事など)に設定されているタグ名をすべて比較し、一致すれば「1」を返却します。
つまり、通常のタグとプライベートタグとの区別などせず、MTEntryIfTaggedタグのtagモディファイアで指定したタグがブログ記事に設定されていれば、MTEntryIfTaggedブロックを実行します。
それでは、include_privateモディファイアはどのように使えばよいかというと、
tagモディファイアを指定せず、次のように記述します。
<mt:EntryIfTagged include_private="1">
:
</mt:EntryIfTagged>
上記のように「include_private="1"」のみを指定した場合、プライベートタグも含めて何らかのタグがブログ記事に設定されていれば、MTEntryIfTaggedブロックを実行します。先述の「『@foo』が設定されていることを判定するもうひとつの正解」がこの書き方です。ただし「@foo」以外のタグも判定に含まれます。
<mt:EntryIfTagged include_private="0">
:
</mt:EntryIfTagged>
上記のように「include_private="0"」を指定した場合、プライベートタグを除いた何らかのタグがブログ記事に設定されていれば、MTEntryIfTaggedブロックを実行します。
3.MTTagsタグでプライベートタグは出力可能か
MTTagsタグはそもそもプライベートタグを収集対象外としているので、MTTagsタグでプライベートタグを出力することはできません。プライベートタグを出力するには、MTEntryTagsなどのMTXXXTagsタグに「include_private="1"」を組み合わせます。
4.tagモディファイアで論理演算子は利用可能か
本題からそれますが、MTEntriesタグのtagモディファイアではANDやORなどの演算子が利用可能です。
MTEntryIfTaggedなどのMTXXXIfTaggedタグのtagモディファイアは、残念ながら論理演算子は利用できません。またカンマなどで区切って複数のタグを指定することもできません。
Movable Typeのタグの「あいまい検索」について
Movable Type 5.0xのタグの「あいまい検索」について、具体的にヒットする検索範囲を調査しましたので紹介します。
1.基本
タグのあいまい検索は、ブログ記事一覧・ウェブページ一覧・アイテム一覧など、タグづけができるオブジェクトについて、フィルタリングする際の項目として選択できます。

本題のあいまい検索でヒットする範囲ですが、、「タグに含まれる半角記号を無視して検索する」という動作になります。
例えばブログ記事Aに「a-b-c」、ブログ記事Bに「a:b:c」というタグがつけられた状態で「abc」や「a-b-c」という文字列でフィルタリングすれば、検索文字列から記号を除去した「abc」という文字列で検索し、さらに検索されるタグについても、それぞれ記号を除去した「abc」として扱い、結果的に両方の記事がヒットします。
半角英文字の大文字・小文字もあいまい検索の対象になります。
2.あいまい検索の仕組み
「a-b-c」「a:b:c」などを「abc」という文字列に変換することを、ここでは「正規化」と呼ぶことにします。実はタグを作成したときに、この正規化されたデータも同時にデータベースに登録されています。下はphpMyAdminでmt_tagテーブルを表示したものです。

tag_idが「4」「6」「8」「10」「12」などのタグはすべて小文字で設定されているのが分かると思いますが、ここに正規化されたタグが入っています。このデータは管理画面から入力したデータではなく、tag_idが「5」「7」「9」「11」「13」をもとに正規化したものです。
そして、tag_idが「5」「7」「9」「11」「13」のtag_n8d_idというフィールドには、正規化されたタグのIDが設定されています。この状態で例えば「AJAX」というタグを追加すれば、すでに正規化されたタグは登録されているので、追加したタグのtag_n8d_idに「4」が設定されます。
このデータ構造によってあいまい検索を実現しています。例は英文字だけですが、日本語が混在していても正規化されます。
ちなみに、タグを正規化するメソッドはMT::Tag::normalizeです。
sub normalize {
my $tag = shift;
my ($str) = @_;
if (!@_ && !(ref $tag)) {
$str = $tag;
} elsif (!$str && (ref $tag)) {
$str = $tag->name;
}
my $private = $str =~ m/^@/;
$str =~ s/[@!`\\<>\*&#\/~\?'"\.\,=\(\)\${}\[\];:\ \+\-\r\n]+//gs;
$str = lc $str;
$str = '@' . $str if $private;
$str;
}
あいまい検索を使ってフィルタリングする処理は、MT::CMS::Entry::listで行っています。n8d_idを利用しているのが分かります。
sub list {
my $app = shift;
…中略…
if ( $filter_col && $filter_val ) {
if ( !exists( $terms{$filter_col} ) ) {
…中略…
elsif (( $filter_col eq 'normalizedtag' )
|| ( $filter_col eq 'exacttag' ) )
{
my $normalize = ( $filter_col eq 'normalizedtag' );
require MT::Tag;
require MT::ObjectTag;
my $tag_delim = chr( $app->user->entry_prefs->{tag_delim} );
my @filter_vals = MT::Tag->split( $tag_delim, $filter_val );
my @filter_tags = @filter_vals;
if ($normalize) {
push @filter_tags, MT::Tag->normalize($_)
foreach @filter_vals;
}
my @tags = MT::Tag->load( { name => [@filter_tags] },
{ binary => { name => 1 } } );
my @tag_ids;
foreach (@tags) {
push @tag_ids, $_->id;
if ($normalize) {
my @more = MT::Tag->load(
{ n8d_id => $_->n8d_id ? $_->n8d_id : $_->id } );
push @tag_ids, $_->id foreach @more;
}
}
@tag_ids = (0) unless @tags;
$arg{'join'} = MT::ObjectTag->join_on(
'object_id',
{
tag_id => \@tag_ids,
object_datasource => $pkg->datasource
},
{ unique => 1 }
);
}
…中略…
}
…後略…
「n8d_id」は半角記号を除去して正規化したデータ。タグ作成時にDBに登録されている。
3.Movable Type 5.1について
Movable Type 5.1でのフィルタリングには「あいまい検索」という項目がありませんが、タグでフィルタリングすればデフォルトの動作であいまい検索を行うようです。

タグ別ブログ記事一覧
Movable Type で「タグ別にブログ記事一覧を表示したい」というご質問がありましたので、本エントリーで紹介致します。
タグ別にブログ記事一覧を表示するには、次のサブテンプレートをご利用ください。
<mt:Entries>
<mt:EntryIfTagged>
<mt:EntryTags>
<mt:TagName setvar="tag_name" />
<mt:SetVarBlock name="entry_title">
<li><a href="<mt:EntryPermalink />"><mt:EntryTitle /></a></li>
</mt:SetVarBlock>
<mt:SetVar name="data{$tag_name}" value="$entry_title" append="1" />
</mt:EntryTags>
</mt:EntryIfTagged>
</mt:Entries>
<mt:loop name="data">
<ul>
<li><mt:GetVar name="__key__" />
<ul>
<mt:GetVar name="__value__" />
</ul>
</li>
</ul>
</mt:loop>
簡単ですが、以上です。
2010.10.13
テンプレートに一部誤りがあったので修正しました。
Movable Type 5.0 のタグクラウドについて
Movable Type 5.0 のタグクラウドの簡単な解説です。
クラッシックウェブサイトテーマのタグクラウドは次のようになっています。
<mt:Tags top="20" include_blogs="children" include_with_website="1">
<mt:If name="__first__">
<div class="widget-tag-cloud widget">
<h3 class="widget-header">タグクラウド</h3>
<div class="widget-content">
<ul>
</mt:If>
<li class="rank-<$mt:TagRank max="10"$>"><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;" rel="tag"><$mt:TagName$></a></li>
<mt:If name="__last__">
</ul>
</div>
</div>
</mt:If>
</mt:Tags>
mt:Tags タグに include_blogs="children"(青字部分)が設定されているの、ウェブサイト配下のブログのブログ記事に付与されたタグを収集対象にするための設定です。
また、mt:Tags タグに include_with_website="1" (赤字部分)が設定されていることで、自ウェブサイトの情報も収集対象にしていますが、ウェブサイトにはブログ記事が存在しないので、この設定ではウェブサイトのタグは読み込まれません。
ウェブページのタグを読み込むには、先のサブテンプレーとの mt:Tags タグに type モディファイアを追加します。
<mt:Tags type="page" top="20" include_blogs="children" include_with_website="1">
…後略…
type="page" とすることで mt:Tags タグの収集対象をウェブページにします。
ただしこの設定では、ブログのブログ記事のタグは読み込まれず、ブログのウェブページのタグが読み込み対象となります。
また、これは前バージョンからの設定されているのですが、タグのリンクは JavaScript の location.href を使用して、href 属性から取得できないようになっており、クローラー対策と思われます。
…前略…
<a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;" rel="tag"><$mt:TagName$></a>
…後略…
ウェブページで画像の出力を制御する
Movable Type のウェブページで、特定のウェブページにだけ画像を表示したい場合のカスタマイズです。
例えば、ウェブページテンプレートに、ウェブページごとに異なる画像を出力するために次のようなマークアップを記述していると仮定します。
<img src="<mt:BlogURL />images/page<$mt:PageID$>.png" />
このマークアップでは、画像が不要なページも一律 img 要素を出力してしまうため、画像を出力したいウェブページに「@image」というプライベートタグを記述し、次のように青色部分を追加することで、画像の不要なページに img 要素を出力しないようにすることができます。
<mt:PageIfTagged tag="@image">
<img src="<mt:BlogURL />images/page<$mt:PageID$>.png" />
</mt:PageIfTagged>
逆に、「画像を出力しない」というプライベートタグをつけて、それ以外のウェブページで img 要素を出力したい場合は、次のようにします。
<mt:PageIfTagged tag="@noimage">
<mt:else>
<img src="<mt:BlogURL />images/page<$mt:PageID$>.png" />
</mt:PageIfTagged>
MTPageIfTagged タグはこのように、tag モディファイアにプライベートタグを指定することもできます。
そもそも、ウェブページへ画像を出力するにはカスタムフィールドを使う方法もありますが、ここでは img 要素を直接テンプレートに記述する方法で紹介しました。
特定のランクのタグだけを表示する
Movable Type で特定のランクのタグだけを表示するカスタマイズです。ご質問を頂きましたので、情報展開します。
1.特定のランクのタグだけを表示
デフォルトテンプレートの「タグクラウド」に対し、青色部分を追加し、赤色部分には1~10の値を設定します。なお、MTTags タグの top モディファイアは削除してください。
<mt:If tag="Tags">
<div class="widget-tag-cloud widget">
<h3 class="widget-header">タグクラウド</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<mt:TagRank max="10" setvar="tag_rank" />
<mt:If name="tag_rank" eq="値">
<li class="rank-<$mt:TagRank max="10"$>"><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;" rel="tag"><$mt:TagName$></a></li>
</mt:If>
</mt:Tags>
</ul>
</div>
</div>
</mt:If>
2.複数のランクのタグを表示
1項のサブテンプレートに追加した MTIf タグの eq モディファイアを変更します。例えば8以上のランクを取得したい場合は次のようにします。
<mt:If tag="Tags">
<div class="widget-tag-cloud widget">
<h3 class="widget-header">タグクラウド</h3>
<div class="widget-content">
<ul>
<mt:Tags>
<mt:TagRank max="10" setvar="tag_rank" />
<mt:If name="tag_rank" ge="8">
<li class="rank-<$mt:TagRank max="10"$>"><a href="javascript:void(0)" onclick="location.href='<$mt:TagSearchLink encode_js="1"$>';return false;" rel="tag"><$mt:TagName$></a></li>
</mt:If>
</mt:Tags>
</ul>
</div>
</div>
</mt:If>
プライベートタグで特定のブログ記事一覧を表示する
Movable Type のタグ機能には「プライベート・モード」が用意されています。
タグの先頭に「@」を付与することで、そのタグは「プライベートタグ」となり、MTEntryTagsタグ・MTTagsタグなどのブロックタグの収集対象から除外でき、プライベートタグ名を指定すれば、収集対象にすることができます。
このプライベート・モードを利用して、ブログ記事が属するカテゴリーやタグに依存しない特定のブログ記事を集めた、例えば「トピック」一覧を表示する方法を紹介します。
方法は簡単で、表示したいブログ記事に「@topic」というプライベートタグを付与します。ブログ記事には、カテゴリーや通常のタグも設定してかまいません。
そして、次のサブテンプレートをテンプレートの任意の位置に設定すれば、プライベートタグを付与したブログ記事の一覧を表示します。
<mt:Entries tag="@topic" days="10">
<mt:EntriesHeader>
<ul>
</mt:EntriesHeader>
<li><a href="<mt:EntryPermalink valid_html="1" />"><mt:EntryTitle encode_html="1" /></a></li>
<mt:EntriesFooter>
</ul>
</mt:EntriesFooter>
</mt:Entries>
MTEntries タグの tag モディファイアにプライベートタグ「@topic」を指定することで、このタグが設定されたブログ記事のみを収集します。また、ここでは days モディファイアで 10 を指定しているので、10日分のブログ記事を表示します。
表示件数を一定にしたい場合は、MTEntries タグの days モディファイアの代わりに、lastn モディファイアまたは limit モディファイアを指定します。
<mt:Entries tag="@topic" lastn="10">
...後略...
<mt:Entries tag="@topic" limit="10">
...後略...
カテゴリ別にトピック一覧を表示したい場合は、MTEntries タグに、さらに category モディファイアを指定します。
<mt:Entries tag="@topic" lastn="10" category="カテゴリ名">
...後略...
タグクラウドの折りたたみ for Movable Type 4
最近流行の「タグクラウド」ですが、タグの増加にしたがって表示される数が増えていきます。サイドバーにタグクラウドを表示していると膨大になる可能性があります。
そうならないよう、Movable Type のデフォルトテンプレートのサイドバーに表示するタグクラウドは、MTTags タグに limit 属性をつけることで表示数を制限していますが、全てのタグが確認できないのが難点です。
ということで、タグクラウドを途中で折りたたむことによって、表示領域を占有せず、かつ折りたたみのリンクをクリックすれば全てのタグを確認できるカスタマイズを紹介します。
このカスタマイズを行うことで、下のように、タグクラウドに折りたたみリンクが表示され、

リンクをクリックすると残りのタグが表示されます。

1.折りたたみスクリプトの追加
ブログ管理画面の「デザイン」→「テンプレート」→「テンプレートモジュール」→「ヘッダー」を開き、追記文章の折りたたみで使用しているスクリプト(下記)を head 終了タグの直前に追加します。
<script type="text/javascript">
function showHide(entryID, entryLink, htmlObj) {
extTextDivID = ('Text' + (entryID));
extLinkDivID = ('Link' + (entryID));
if( document.getElementById ) {
if( document.getElementById(extTextDivID).style.display ) {
if( entryLink != 0 ) {
document.getElementById(extTextDivID).style.display = "block";
document.getElementById(extLinkDivID).style.display = "none";
htmlObj.blur();
} else {
document.getElementById(extTextDivID).style.display = "none";
document.getElementById(extLinkDivID).style.display = "block";
}
} else {
location.href = entryLink;
return true;
}
} else {
location.href = entryLink;
return true;
}
}
</script>
上記は外部ファイルにしても構いません。
2.タグクラウドの変更
サイドバーのタグクラウドを下記の内容に変更します。
2.1 公開テンプレートの場合
<MTIf name="main_index">
<dt class="sidetitle">
Tag Clouds
</dt>
<$MTSetVar name="foldflag" value="0"$>
<dd class="side">
<ul id="tags">
<MTTags>
<MTIf name="__counter__" eq="8">
</ul>
<div class="list_more" id="LinkEntry">
<a href="javascript:void(0)" name="<$MTTagID$>" onclick="showHide('Entry','<$MTBlogURL$>',this);return false;">続きを読む ≫</a>
</div>
<div id="TextEntry" style="display: none">
<div class="list_more"><a href="javascript:void(0)" name="" onclick="showHide('Entry',0,this);return false;">≪ 続きを隠す</a></div>
<ul id="tags">
<$MTSetVar name="foldflag" value="1"$>
</MTIf>
<li class="module-list-item taglevel<$MTTagRank$>"><a href="<$MTTagSearchLink$>"><$MTTagName$></a></li>
</MTTags>
</ul>
<MTIf name="foldflag"></div></MTIf>
</dd>
</MTIf>
2.2 デフォルトテンプレートの場合
<$MTSetVar name="foldflag" value="0"$>
<MTIf name="main_index">
<div class="widget-cloud widget">
<h3 class="widget-header">タグクラウド</h3>
<div class="widget-content">
<ul class="widget-list">
<MTTags sort_by="rank">
<MTIf name="__counter__" eq="8">
</ul>
<div class="list_more" id="LinkEntry">
<a href="javascript:void(0)" name="<$MTTagID$>" onclick="showHide('Entry','<$MTBlogURL$>',this);return false;">続きを読む ≫</a>
</div>
<div id="TextEntry" style="display: none">
<div class="list_more"><a href="javascript:void(0)" name="" onclick="showHide('Entry',0,this);return false;">≪ 続きを隠す</a></div>
<ul class="widget-list">
<$MTSetVar name="foldflag" value="1"$>
</MTIf>
<li class="rank-<$MTTagRank max="10"$> widget-list-item"><a href="<$MTTagSearchLink$>"><$MTTagName$></a></li>
</MTTags>
</ul>
<MTIf name="foldflag"></div></MTIf>
</div>
</div>
</MTIf>
3.デフォルト表示数を変更する
いずれのテンプレートも、2項にある下記の数字(赤色)を変更してください。
<MTIf name="__counter__" eq="8">
デフォルトで表示されるタグ数は「設定した値-1」になります。
CSSは別途掲載します。すいません。
タグ検索でエントリーの画像を表示する
Movable Type のタグ検索機能で、エントリータイトル・概要の代わりに、エントリーに含まれる画像を検索結果画面に表示するカスタマイズです。
下のスクリーンショットは、デフォルトテンプレートで、"image" というタグを与えた3つのエントリーにそれぞれ異なる画像を表示させ、"image" タグで検索した検索結果画面のサンプルです。

デザインが大雑把で申し訳ありませんが、以前このカスタマイズについてのご質問を頂いていてからかなり時間が経ってしまいましたので、取り急ぎの公開です。
試してみたところ、Collect プラグインを利用すれば、タグ検索による画像表示が行えることが判明しました。
1.プラグインのダウンロード
下記のサイトにある「Download」のリンクをクリックして、Collect Plugin をダウンロード
staggernation.com:Collect Plugin for Movable Type
解凍した中にある Collect.pl を plugins フォルダ直下にアップロード。
2.検索結果テンプレートの修正
ここでは、デフォルトテンプレートを例にして <MTSearchResults>~</MTSearchResults> の修正箇所を示します。
リスト1 のように、赤色を削除して青色を追加します。
リスト1 検索結果テンプレート修正箇所
<MTSearchResults>
<MTBlogResultHeader>
<h3 class="search-results-header">
<MTIfStraightSearch>
ブログ: <$MTBlogName$> での検索結果
</MTIfStraightSearch>
<MTIfTagSearch>
<$MTBlogName$>でタグ <$MTSearchString$> が指定されているエントリー
</MTIfTagSearch>
</h3>
<div class="search-results-container">
<MTIfTagSearch>
<ul>
</MTIfTagSearch>
</MTBlogResultHeader>
<MTIfStraightSearch>
<h3><a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a></h3>
<p><$MTEntryExcerpt$> <$MTEntryEditLink$></p>
</MTIfStraightSearch>
<MTIfTagSearch>
<div class="entry-tags">
<h4 class="entry-tags-header">タグ:</h4>
<ul class="entry-tags-list">
<MTEntryTags>
<li class="entry-tag"><a href="<$MTTagSearchLink$>&IncludeBlogs=<$MTSearchIncludeBlogs$>" rel="tag"><$MTTagName$></a></li>
</MTEntryTags>
</ul>
</div>
<MTCollect tags="img">
<MTCollectThis show="0">
<$MTEntryBody$>
</MTCollectThis>
<MTIfCollected tags="img">
<MTCollected tags="img" lastn="1">
<li style="display:inline"><a href="<$MTEntryPermalink$>"><img src="<$MTCollectedAttr attr="src"$>" /></a></li>
</MTCollected>
</MTIfCollected>
</MTCollect>
</MTIfTagSearch>
<MTIfStraightSearch>
<p class="entry-footer">
<span class="post-footers"><MTIfNonEmpty tag="EntryAuthorDisplayName">投稿者: <$MTEntryAuthorDisplayName$> </MTIfNonEmpty>日時: <$MTEntryDate$></span>
</p>
</MTIfStraightSearch>
<MTBlogResultFooter>
<MTIfTagSearch>
</ul>
</MTIfTagSearch>
</div>
</MTBlogResultFooter>
</MTSearchResults>
ここで行っている修正は主に下記の通りです。
- タグ表示部分に Collect プラグインの MT タグを挿入
- タグ検索は順序なしリスト(ul - li)で表示
- タグ検索結果の ul 要素の開始タグは
MTBlogResultHeaderに、終了タグはMTBlogResultFooterに埋め込み(ここに埋め込まないと、検出されたエントリー数分表示されるため) - エントリータイトルおよび投稿者情報部分は通常検索時のみ表示されるよう、
<MTIfStraightSearch>~<MTIfStraightSearch>で括る
修正方法は他にも色々ありますので、お試しになってください
3.エントリーに含まれる画像の表示数を変更する
エントリーに含まれる画像の件数を設定しているリスト2 の赤色部分を変更します。
リスト2 画像表示数変更方法
<MTCollected tags="img" lastn="1">
なお、エントリー表示数を制御することはできません(検索されたエントリー数分を全て表示)。
Movable Type 3.3 エントリー・タグ詳説
Movable Type 3.3 から追加されたタグ機能の利用方法が下記のページに掲載されています。
Movable Type Beta Weblog:Everybody loves tags!
以下、元記事で紹介されているタグの機能や利用方法について超意訳で紹介します。
1.タグとは?
タグは、項目の特定の一部分を説明するための簡単な単語、あるいは語句です。例えば、私は(私自身に)
human, male, guy, sailor, product manager, san franciscan, shaved head, tall, joke-cracking, six apartisan, stressed-out, geek
というタグ付けをするかもしれません。それらのタグの全てが、私が誰であるかに関して、より良い情報を与えてくれます。
Movable Type ではエントリーにタグを与える機能を提供します。例えば、あなたはこの記事に関するエントリーを書き、エントリーに、
movable type 3.3, movable type, new release, beta, feature, tagging, entry tags
というタグを付与することができます。
そして後でこのエントリー(や他のエントリー)を見つけるのに使用することができる、特別なメタデータ(MTタグ)を提供します。
Movable Type 3.3 では「自動同義語」をサポートしています。例えば "Movable Type" は "movabletype" と同等であるとみなします。特定のタグを共有するエントリーは、自動的に関連づけられます。これで Movable Typeインタフェース、またはあなたの公開ブログから関連する内容を見つけることが簡単になります。
タグのデフォルト区切り文字はカンマですが、
メイン・メニュー > システム・メニュー > 投稿者 > [投稿者名]
の「タグ区切り」でスペース文字に変更することもできます。
エントリー編集画面のタグ・フィールドでは、使用済みのタグを利用した自動補完機能があります。
2.キーワードとの違い
キーワードはエントリーに括りつけられた、MTEntryKeywords によって出力される文字列で、検索することも可能ですが、エントリー・タグは強力かつ洗練されたタグのセットで、「タグサーチ」という機能で特定のタグが与えられたエントリーを検索します。
将来は XML-RPC API でエントリー・タグがサポートされる予定です。
3.カテゴリーとの違い
タグは関連するエントリーを分類・組織化し、検索を助けるという点においてはカテゴリーと同様ですが、下記の点に相違があります。
- Model:
- カテゴリは目次のようにトップダウン的な設定ですが、タグは本のインデックスのようにボトムアップで設定されます。
- Specificity:
- カテゴリは汎用的で、エントリーを副カテゴリに分配することで特性を獲得する場合に適しています。タグは限定的で、タグの組み合わせで(エントリーの)特性を獲得する場合に適しています。
- Planning:
- カテゴリは少ない数で計画性があり、時間の経過によって一貫性のあるものとなります。タグは計画性がなく、各項目の細部に基づいたものになります。
- Archiving vs searching:
- カテゴリーは「アーカイブ」として異なるページに各カテゴリーに関連するエントリーを静的に格納します。タグも1ページに特定のタグによるエントリーを表示しますが、それらのページはダイナミック(再構築不要)に表示されます。
4.エントリー・タグの追加と削除
タグを利用するには、エントリー編集画面の下にある「画面の表示設定を変更」をクリックして、ダイアログの「エディター・フィールド」欄の左側にあるラジオボタンが「基本」になっているので「すべて」または「カスタム」を選択します。
「すべて」を選んだ場合はそのまま右下の「保存」をクリックします。「カスタム」を選んだ場合は、「タグ」というチェックボックスにチェックをしてください。
追記:左下にある「アクション・バー」で「両方」を選択しておくと「保存」「確認」ボタンがエントリー上部にも表示されて便利です。
エントリー・タグフィールドについて
エントリー・タグフィールドにタグを設定します。タグを複数記述する場合はカンマで区切ってください。タグはカンマ以外のどのような文字列も許容しますが、
@ ! ` \ < > * & # / ~ ? ' " . , = ( ) $ { } [ ] ; : <space> + -
以外の文字列を入力することで正常に動作します。入力した英文字は最終的に小文字として扱われます。
例外的な利用方法として、タグに "@" を付加することでタグは「プライベート・モード」として機能します。プライベート・モードのタグはブログ上で表示されることはありませんが、検索インタフェースや管理インタフェースで使用することができます。
エントリー・タグの自動補完
エントリー・タグを入力フィールドにタイプした時、使用済みのエントリー・タグと一致する文字列で始まるのであれば、それらが候補としてドロップダウンリストで表示されます。リストを直接クリックするか上下キーで選択した後 Tab キーを押すと、エントリー・タグの入力が補完されます。
5.エントリー・タグの管理
エントリー・タグはブログ全体およびブログ単位のどちらでも管理可能です。それぞれの管理画面のサイドバーにある「タグ」をクリックすると管理画面に遷移します。
削除
削除したいタグの左側にあるチェックボックスをチェックして、削除ボタンをクリックします。
タグ名の変更
タグ名のリンクをクリックするとテキストボックスに切り替わるので、任意の名称を入力して「名前の変更」をクリックします。
タグのマージ
前記の「タグ名の変更」で、すでに存在するタグ名を設定すると「マージ(合体)しますか?」という旨のダイアログが表示されます。「OK」をクリックするとマージされます。
6.エントリー・タグの表示
Movable Type 3.3 ではエントリー・タグ表示のために、次のMTタグを提供します。
- MTTags
- MTTagName
- MTTagID
- MTTagCount
- MTTagRank
- MTTagSearchLink
- MTEntryTags
- MTEntryIfTagged
以下、テンプレートに対するエントリー・タグの設定方法です。関連タグを青色で示しています。
エントリーにタグを表示
<MTEntries>
The entry "<$MTEntryTitle$>" is tagged:
<MTEntryTags glue=", "><$MTTagName$></MTEntryTags>
</MTEntries>
エントリーにタグを表示(タグの有無判定あり)
<MTEntries>
The entry "<$MTEntryTitle$>"
<MTEntryIfTagged>
is tagged: <MTEntryTags glue=", "><$MTTagName$></MTEntryTags>
<MTElse>
has no entry tags.
</MTElse>
</MTEntryIfTagged>
</MTEntries>
タグ検索用リンクを表示
<MTEntryTags glue=", ">
<a href="<$MTTagSearchLink$>"><$MTTagName$></a></MTEntryTags>
tag 属性で指定したタグの有無で表示を制御
<MTEntries>
[...MTEntry data...]
<MTEntryIfTagged tag="important">
<p><img src="/movabletype/docs/3.2/images/gold_star.gif"
alt="This is important!" /></p>
</MTEntryIfTagged>
</MTEntries>
ブログで使用されるすべてのタグを表示
<ul>
<MTTags>
<li>
<a href="<$MTTagSearchLink$>"><$MTTagName$></a>
</li>
</MTTags>
</ul>
ブログで使用されるすべてのタグを表示(タグカウントつき)
<ul>
<MTTags>
<li>
<a href="<$MTTagSearchLink$>"><$MTTagName$> (<$MTTagCount$>)</a>
</li>
</MTTags>
</ul>
タグクラウド(タグを雲のように表示)
<div class="module-tagcloud module">
<h2 class="module-header">Tag cloud</h2>
<div class="module-content">
<ul class="module-list">
<MTTags>
<li class="module-list-item taglevel<$MTTagRank$>">
<a href="<$MTTagSearchLink$>"><$MTTagName$></a>
</li>
</MTTags>
</ul>
</div>
</div>
- タグクラウドは下記のCSSが必要です。
.module-tagcloud .module-content {text-align: center; }
.module-tagcloud .module-content .module-list { list-style: none; }
.module-tagcloud .module-content .module-list .module-list-item { display: inline; }
.module-tagcloud .module-content .module-list li.taglevel1 { font-size: 19px; }
.module-tagcloud .module-content .module-list li.taglevel2 { font-size: 17px; }
.module-tagcloud .module-content .module-list li.taglevel3 { font-size: 15px; }
.module-tagcloud .module-content .module-list li.taglevel4 { font-size: 13px; }
.module-tagcloud .module-content .module-list li.taglevel5 { font-size: 11px; }
.module-tagcloud .module-content .module-list li.taglevel6 { font-size: 9px; }
特定のタグが与えられたエントリーのみ表示
<MTEntries tag="TAGNAME">
[...]
</MTEntries>
特定のタグが与えられたエントリー最新1件をトップに表示
<!-- The "banner" entry -->
<MTEntries tag="Important" lastn="1">
[...]
</MTEntries>
<!-- All other recent entries -->
<MTEntries>
[...]
</MTEntries>
注目して欲しいエントリー("notable" というタグを付与)をサイドバーに表示
<div class="module-archives module">
<h2 class="module-header">Notable entries</h2>
<div class="module-content">
<ul class="module-list">
<MTEntries lastn="5" tag="notable">
<li class="module-list-item">
<a href="<$MTEntryPermalink$>"><$MTEntryTitle$></a>
</li>
</MTEntries>
</ul>
</div>
</div>
tag 属性にNOTオペレータが付与されたタグを用いてエントリーの公開を抑止する
<MTEntries tag="NOT noindex">
[...]
</MTEntries>
アーカイブページでのタグクラウドのインクルード
再構築時のパフォーマンスの問題を回避するため、タグクラウドをアーカイブページに含める場合は、PHPによるモジュール化またはSSIを用いてください。

