チャレンジ! Movable TypeをCMSとして使ってみよう!

第14回検索結果が多いときにページを分割する

前回途中まで作った「検索結果」テンプレートにJavaScriptを追加して、20件ごとにページ分割する方法を紹介します。

ほげ山くん:先輩!また今回もアップデート情報が出てるらしいじゃないですか!

くれま先輩:だね。2009年3月18日に、前回も触れた4.25が出荷されたのよ!

ほげ山くん:今回はあっという間でしたねぇ。前にも話題に出たMotionが使えるようになったんですよね?

くれま先輩:そうそう!TwitterなどのWebサービスでの活動を集めるアクションストリーム機能も使えるようになってるから、触ってみたらどうでしょう?蒲生さんのサイトで「アクションストリーム」の活用方法が記事にされていたので、興味のある方は、ぜひチェックしてみてくださいね。

【参考ページ】
【Movable Type 4.25公開】Action Streamをブログに追加して楽しもう: 世界中の1%の人々へ
http://www.dakiny.com/archives/mt42/movable_type_425action_stream/
Movable Type 4.25 出荷開始 | MovableType.jp
http://www.movabletype.jp/blog/movable_type_425.html

ページを分割するために必要な手順を確認

くれま先輩:っじゃ、前回の続きをやっていきましょ。今日はいつもと違って、ちょっと複雑なことをするので、よーく説明を聞いてね。まず、今日やることは大まかに分けて次の4ステップになるよ。

  1. 「検索結果」テンプレート内に、必要な記述を追加する
  2. デフォルトのテンプレートセットからmt.jsを持ってくる
  3. デフォルトの「検索結果」テンプレートから、必要なJavaScriptをとってくる
  4. ヘッダ領域の検索フォームにCGIに渡す引数を足す

ほげ山くん:了解です!

「検索結果」テンプレート内に、必要な記述を追加する

ほげ山くん:では、最初に、⁠検索結果」テンプレートの編集画面を開きますね。上部メニューの[デザイン→テンプレート]を選択して、⁠ステムテンプレート」のセクションにある「検索結果」をクリックしましたー。

くれま先輩:足す部分が多いので、一ヶ所づつ説明していくね。最初はhead要素内の<mt:Include module="head要素" />のすぐ後ろに、こういう風に足してね。

 <mt:Include module="head要素" />直後に追加する記述
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript" src="<mt:BlogURL />mt.js"></script>
<mt:Include module="ページ分割用Javascript" />

ほげ山くん:あれ?「mt.js」って第4回で削除したんじゃなかったでしたっけ?

くれま先輩:ごめんね…。あの時は、⁠検索結果」テンプレートにAjaxを使う説明をする計画がなかったの…。だけどそれをするには、必要な関数が記述されている「mt.js」が必要だから、あとでデフォルトのテンプレートセットから持ってくるようにさせてね。

ほげ山くん:ふーん。分りました。あと、⁠ページ分割用JavaScript」っていうテンプレートモジュールも作ってないですよね?

くれま先輩:うん。それはこれから作るからね。次は、<mt:SearchResults>~</mt:SearchResults>までを、次のようにまるっと書き換えてね。

<mt:SearchResults>~</mt:SearchResults>だった部分に置き換えるサブテンプレート
<div id="search-results">
	<mt:SetVarTemplate id="search_results" name="search_results">
		<mt:SearchResults>
			<mt:BlogResultHeader>
				<span id="current-page" class="hidden"><mt:CurrentPage /></span>
				<h1>「<mt:SearchString />」での検索結果</h1>
			</mt:BlogResultHeader>
			<div class="serchResult">
			<h3><a href="<mt:EntryLink />"><mt:EntryTitle /></a></h3>
			<mt:SetVarBlock name="entry_category"><mt:EntryCategory></mt:SetVarBlock>
			<mt:If name="entry_category" eq="最新情報">
				<p><mt:EntryBody words="50" /></p>
			<mt:Else>
				<dl>
				<dt>著者名</dt>
				<dd><mt:author_name /></dd>
				<dt>発売日</dt>
				<dd><mt:release_date /></dd>
				<dt>対象年齢</dt>
				<dd><mt:readers_age /></dd>
				<dt>版型</dt>
				<dd><mt:book_size /></dd>
				<dt>説明</dt>
				<dd><mt:EntryBody words="50" /></dd>
				</dl>
				<p><mt:coverAsset><a href="<mt:EntryLink />"><img src="<mt:AssetThumbnailURL width="100" />"alt="<mt:EntryTitle />" title="<mt:EntryTitle />" /></a></mt:coverAsset></p>
			</mt:If>
			<!-- end div.serchResult --></div>
			<mt:SearchResultsFooter>
				<div class="content-nav">
				<mt:IfPreviousResults><a href="<mt:PreviousLink />" rel="prev" onclick="return swapContent(-1);">< 前</a>&nbsp;&nbsp;</mt:IfPreviousResults><mt:PagerBlock><mt:IfCurrentPage><mt:Var name="__value__" /><mt:Else><a href="<mt:PagerLink />"><mt:Var name="__value__" /></a></mt:IfCurrentPage><mt:Unless name="__last__">&nbsp;</mt:Unless></mt:PagerBlock><mt:IfMoreResults>&nbsp;&nbsp;<a href="<mt:NextLink />" rel="next" onclick="return swapContent();">次 ></a></mt:IfMoreResults>
				<!-- end div.content-nav --></div>
				</mt:SearchResultsFooter>
		</mt:SearchResults>
	</mt:SetVarTemplate>
	<mt:Var name="search_results" />
<!-- end div#search-results --></div>

ほげ山くん:長いですね!!!ちょっと解説してくださいよ!

くれま先輩:<div id="search-results">はJavaScriptのソースからDOM要素を取得するために必要なので足しているんだよ。<span id="current-page" class="hidden"><mt:CurrentPage /></span>も記述しないとAjaxによる動作ができないので、足してね。

ほげ山くん:後は、<mt:SearchResultsFooter>のところが物凄く追加されましたねぇ。

くれま先輩:mt:SearchResultsFooterの中身は、ページ分割されるときに表示されるこんなナビゲーションを作っている部分なのよ。

ページ分割をしたときに表示されるナビゲーション
ページ分割をしたときに表示されるナビゲーション

ほげ山くん:なるほど、ページ数が多いとき「ページ番号」⁠< 前」⁠次 >」などを出して、前後ページに移動させるアレですね。

くれま先輩:<mt:IfPreviousResults>は、いま見ているページよりも前のページがある場合に中身を処理するんだよ。つまり、⁠< 前」を出力してる。mt:PagerBlockの中身は、検索結果ページの総ページ分繰り返し処理されるの。

ほげ山くん:1 2 3 4…っていう数字が出されてる部分ですか?

くれま先輩:そうよ。その数字を出力するのは、<mt:Var name="__value__" />の部分だね。⁠__value__」を使って、繰り返した数を出力しているんだよ。

ほげ山くん:<mt:Unless name="__last__">の部分っていうのは、⁠~でないとき」に実行されるんですよね?

くれま先輩:そうだね。⁠__last__」は、繰り返しの最後を表しているから、繰り返しの最後で無い場合は「&nbsp;」が数字の間に挟まるってことね。

ほげ山くん:なるほど、長いけど少しづつ見ていくと、理解できそうですね。

くれま先輩:うんうん。後は「< 前」⁠次 >」を囲っているa要素の中に「onclick」があるけれど、この部分でJavaScriptを動作させているわけだ。

ほげ山くん:はーい。

くれま先輩:最後に、<!-- end div#primary --></div>の直前にこれを書いてね。

<!-- end div#primary --></div>の直前に追加する記述
<mt:Include module="ページ分割用Javascript002" />

ほげ山くん:できましたー。

くれま先輩:はい、じゃあここまで書けたら、⁠保存」をクリックしておいてね。

デフォルトのテンプレートセットからmt.jsを持ってくる

ほげ山くん:次は「mt.js」ですよね?

くれま先輩:うん、そう。さっきも話したけど、これを削除してしまったので、新規のブログを作って、そこからコピーして持ってきましょ。

ほげ山くん:新規のブログを作る…。えーっと、右上の[システムメニュー→ブログ]を選択するんですよね。で、⁠ブログを作成する」をクリック、と。

くれま先輩:ブログの名前とサイトURL+サイトパスのディレクトリ名は、は、いままでのものと被らないように何か入力してみてね。試しに「test」とかでいいよ。

ほげ山くん:はいー。テンプレートセットは「プロフェッショナルウェブサイト」にしときます。で、⁠ブログを作成する」をクリック。

くれま先輩:そうしたら、上部メニューの[デザイン→テンプレート]を選択して、⁠インデックステンプレート」のセクションの「JavaScript」をクリックしてね。

ほげ山くん:すごく長いソースが入ってますね…。

くれま先輩:ここは詳しく解説しないので、全部のソースをコピーしておいてね。で、左上のプルダウンメニューから「絵本出版のリブリート」のブログの方に戻ろう。

ほげ山くん:戻りました。

くれま先輩:そうしたら、上部メニューの[デザイン→テンプレート]を選択して、⁠インデックステンプレートを作成」をクリックして。名前を「JavaScript⁠⁠、出力ファイル名を「mt.js」にして、他はとくに触らずに「保存」をクリックしてね。

デフォルトの「検索結果」テンプレートから、必要なJavaScriptをとってくる

ほげ山くん:デフォルトの「検索結果」テンプレートを使うということは、またさっき作った「test」ブログに移動すればいいんですね?

くれま先輩:うん。⁠test」ブログの「検索結果」テンプレート編集画面を開いてね。デフォルトのソースが記述されているけど、その中で次の2つの部分を使うので、コピーしておいてね。

ページ分割用Javascriptに使う部分
<script type="text/javascript">
/* <![CDATA[ */
var user = <$mt:UserSessionState$>;
<mt:IfMoreResults>
function getResults(page) {
    page = parseInt(page);
    if (timer) window.clearTimeout(timer);
    var xh = mtGetXmlHttp();
    if (!xh) return false;
    var res = results[page];
    if (!res) return;
    var url = res['next_url'];
    if (!url) return;

    xh.open('GET', url + '&format=js', true);
    xh.onreadystatechange = function() {
        if ( xh.readyState == 4 ) {
            if ( xh.status && ( xh.status != 200 ) ) {
                // error - ignore
            } else {
                try {
                    var page_results = eval("(" + xh.responseText + ")");
                    if ( page_results['error'] == null )
                        results[page + 1] = page_results['result'];
                } catch (e) {
                }
            }
        }
    };
    xh.send(null);
}

function swapContent(direction) {
    if ( direction == undefined ) direction = 1;
    var page_span = document.getElementById('current-page');
    if (!page_span) return true;
    var next_page = direction + parseInt(page_span.innerHTML);
    var res = results[next_page];
    if (!res) return true;
    var content = res['content'];
    if (!content) return true;
    var div = document.getElementById('search-results');
    if (!div) return true;
    div.innerHTML = content;
    timer = window.setTimeout("getResults(" + next_page + ")", 1*1000);
    window.scroll(0, 0);
    return false;
}
<mt:Else><mt:IfPreviousResults>
function swapContent(direction) {
	return true;
}</mt:IfPreviousResults>
</mt:IfMoreResults>
/* ]]> */
</script>
ページ分割用Javascript002に使う部分
<mt:Ignore>Used with the ajax search capability of the new search class</mt:Ignore>
<mt:IfMoreResults>
<script type="text/javascript">
<!--
var div = document.getElementById('search-results');
var results = {
    '<$mt:CurrentPage$>': {
        'content': div.innerHTML,
        'next_url': '<$mt:NextLink$>'
    }
};
var timer = window.setTimeout("getResults(" + <$mt:CurrentPage$> + ")", 1*1000);
//-->
</script>
</mt:IfMoreResults>

ほげ山くん:あぁ、じーっと見てたら、発見できましたw これって、テンプレートモジュールにすればいいんですよね?

くれま先輩:うん、それぞれ名前をつけて、新規テンプレートモジュールにしておいてね!

ヘッダ領域の検索フォームにCGIに渡す引数を足す

くれま先輩:最後に、検索結果1ページに表示させる結果の数をコントロールするために、ヘッダ領域に入ってる検索フォームのところに要素を追加するよ。上部メニューの[デザイン→テンプレート]を選択して、テンプレートモジュールのセクションにある「ヘッダ領域」をクリック。

ほげ山くん:しましたー。

くれま先輩:そうしたら、<input type="hidden" name="IncludeBlogs" value="<mt:BlogID />" />っていう行を書いたと思うので、その直後にこの一行を追加してね。

<input type="hidden" name="IncludeBlogs" value="<mt:BlogID />" />の直後に追加する記述
<input type="hidden" name="limit" value=":<mt:SearchMaxResults />" />

ほげ山くん:mt:SearchMaxResultsって、なんでしたっけ?

くれま先輩:検索で返される結果の最大数を出力するタグなのよ。

ほげ山くん:なるほど。その最大値って、どこかで設定するんですか?

くれま先輩:環境設定ファイル(mt-config.cgi)で設定できるんだけど、今回はデフォルトの値「20件」のままで行こうと思うので、設定はこれにて終了!今回はちょっと長くなってしまったので、この辺で。

ほげ山くん:今日の作業で、ページ分割ってできるようになったんですか?

くれま先輩:うん、なってるよ!次回は必ず、検索用テンプレートを完成させて、動作の確認をしようね!

次回予告

おすすめ記事

記事・ニュース一覧