Movable Type 4.2 の Ajax 検索機能

Movable Type 4.2 の Ajax 検索機能

Posted at June 20,2008 12:55 PM
Tag:[Ajax, MovableType, Search]

Movable Type 4.2 の検索機能ではページ分割が導入されました。

検索結果のページ分割

検索結果が複数のページに跨る場合(=ページ分割された場合)は、Google マップのスクロールのように、次の検索結果ページを Ajax で事前に取得します。
その結果、分割ページに移動するときは、ストレスのないページ送りができるようになっています。瞬時に前後ページに移動できるので、かなり快適です。
ただし、初回の検索は Ajax ではありません。

本エントリーでは、検索結果ページで使われている JavaScript をかなり簡単に紹介します。

1.getResults

MTIfMoreResultsタグで、検索結果がページ分割されている場合にこのコードがページに展開され、現在の検索結果の表示中にバックグラウンドで Ajax を起動し、次のページの検索結果を取得・保持します。

<MTIgnore>Below Javascript adds ajax search capability</MTIgnore>
<script type="text/javascript">
/* <![CDATA[ */
<MTIfMoreResults>
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);
}
...中略...
</MTIfMoreResults>
/* ]]> */
</script>

この関数は、検索結果ページに埋め込まれた次のスクリプトで実行されます。

<MTIgnore><!-- Used with the ajax search capability of the new search class --></MTIgnore>
<MTIfMoreResults>
<script type="text/javascript">
<!--
var div = document.getElementById('search-results');
var results = {
    '<MTCurrentPage>': {
        'content': div.innerHTML,
        'next_url': '<MTNextLink>'
    }
};
var timer = window.setTimeout("getResults(" + <MTCurrentPage> + ")", 1*1000);
//-->
</script>
</MTIfMoreResults>

次のページのURLは、getResults の内部処理で JSON 型の変数 results の next_url にアクセスし、MTNextLinkタグで展開された URL を取得します。

getResults は、周期処理を行うための window.setTimeout で起動され、getResults の内部処理の window.clearTimeout で周期処理を停止します。つまり1回しか起動されません。また、1秒周期で実行するため、検索結果が表示されてからすぐにリンクをクリックすると、Ajax による次のページ取得が完了していない場合があります。

2.swapContent

検索結果本文を、保持している前後の検索結果と置き換えます。

<script type="text/javascript">
/* <![CDATA[ */
<MTIfMoreResults>
...中略...
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;
}
<MTElse><MTIfPreviousResults>
function swapContent(direction) {
    return true;
}</MTIfPreviousResults>
</MTIfMoreResults>
/* ]]> */
</script>

この関数は、検索結果ページに埋め込まれたページ移動用のナビゲーションの「前」「次」のリンクから実行されます。

<MTIgnore><!-- Used with the ajax search capability of the new search class --></MTIgnore>
<div class="content-nav">
<MTIfPreviousResults>
  <a href="<MTPreviousLink>" rel="prev" onclick="return swapContent(-1);">&lt; 前</a>&nbsp;&nbsp;
</MTIfPreviousResults>
<MTPagerBlock>
  <MTIfCurrentPage>
    <MTVar name="__value__">
  <MTElse>
    <a href="<MTPagerLink>"><MTVar name="__value__"></a>
  </MTIfCurrentPage>
  <mt:unless name="__last__">&nbsp;</mt:unless>
</MTPagerBlock>
<MTIfMoreResults>&nbsp;&nbsp;<a href="<MTNextLink>" rel="next" onclick="return swapContent();">次 &gt;</a>
</MTIfMoreResults>

なお、Ajax によるページ移動は「前」「次」のリンクを使った場合のみ有効で、ページ番号のリンクをクリックしたときは通常のCGI起動になります。

3.注意事項

ページ分割時の Ajax を有効に活用するには、次の青色の1行が必要です。

...前略...
<MTSearchResults>
  <MTSearchResultsHeader>
    <div id="search-results">
      <span id="current-page" class="hidden"><MTCurrentPage></span>
      <h1 id="page-title" class="search-results-header">
...後略...

関数 swapContent の内部処理で、現在のページ番号をここから取得しています。

関連記事
zenback
人気エントリー
トラックバックURL


コメント

お忙しいところ、度々のサポート要請で申し訳ありません。
この記事を見て、小粋空間さんのテンプレート(4.2Styleタイプ)に4.21デフォルトの検索関連テンプレートを移植する形で作ってみました。

1.私の移植のやり方が悪いのか、4.21元々の問題なのか私には分りませんが、
分割されたページの「前、分割ページの番号、次」のリンクで&(アンパサンド)が実体参照文字になっておらずW3CのValidation Checkでエラーとなります。考えられる対処方法があればご指摘いただけないでしょうか。
2.分割されたページの2ページ目以降はテンプレートを経由しないで編集されているようですが、これが仕様なのでしょうか。ページ・カテゴリの場合にテンプレートでメタデータ内のカテゴリがリンク付きのフォルダー名になるのを持ち替える等しているのですが、これが反映されません。

よろしくお願いします。

[1] Posted by オーク : October 6, 2008 5:32 PM

>オークさん
こんにちは。
ご質問の件ですが、

1.mt:PreviousLink タグ・mt:PagerLink タグ・mt:NextLink タグに escape="html" というモディファイアを設定してみてはいかがでしょうか。

2.2ページ目以降は Ajax または ページ指定した検索用CGIを起動しているという認識です。文章の後半はご要望の内容が理解できませんでした。すいません。

それではよろしくお願い致します。

[2] Posted by yujiro logo : October 7, 2008 4:54 PM

荒木さん、おはようございます。

1項につきましては、お蔭様で解決いたしました。アドバイスありがとうございます。

2項につきましては、2ページ目以降も1ページ目同様の記事の編集が出来ればと思った次第です。Ajaxと言うものを理解できていませんので、もう少し勉強してからにします。

度々のサポート、ありがとうございました。

[3] Posted by オーク : October 9, 2008 9:05 AM

>オークさん
こんにちは。
ご連絡ありがとうございました。
Ajax ではページの一部を入れ替えるだけなので、おそらく、カスタマイズしたい部分が2ページ目以降の入れ替え対象に含まれていない、と理解致しました。
つまり、2ページ目以降に何かを反映させるには、検索結果テンプレートの MTSearchResults タグのブロック内に書き込まないといけないと思います。
それではよろしくお願い致します。

[4] Posted by yujiro logo : October 9, 2008 2:10 PM
コメントする
greeting

*必須

*必須(非表示)


ご質問のコメントの回答については、内容あるいは多忙の場合、1週間以上かかる場合があります。また、すべてのご質問にはお答えできない可能性があります。予めご了承ください。

太字イタリックアンダーラインハイパーリンク引用
[サインインしない場合はここにCAPTCHAを表示します]

コメント投稿後にScript Errorや500エラーが表示された場合は、すぐに再送信せず、ブラウザの「戻る」ボタンで一旦エントリーのページに戻り(プレビュー画面で投稿した場合は、投稿内容をマウスコピーしてからエントリーのページに戻り)、ブラウザをリロードして投稿コメントが反映されていることを確認してください。

コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。例えば「<$MTBlogURL$>」は「&lt;$MTBlogURL$&gt;」となります(全て半角文字)