Ajax によるモジュール化
Movable Type のサイドバーの各リストを、Ajax でモジュール化を行う方法を紹介します。
1.PHP モジュール化と Ajax モジュール化の違い
Movable Type における PHP モジュール化には次のようなメリットがあります。
- 再構築時間の削減
- アーカイブに依存しないリストの生成(今回はここに言及しません)
ただし PHP モジュール化は、ユーザがブラウザからインクルード元のページにアクセスした時、インクルード元のページはインクルード先の各モジュールを読み込んだコンテンツを生成・返却するため、サイドバーに多くの情報をインクルードしていると、PHP でページを生成する分、表示が遅延します。
本題とはそれますが、WordPress で表示までに若干のタイムラグが生じるのは、この PHP によるページ生成が行われるためです(キャッシュや条件付きGETが機能していればこの限りではありません)。
Ajax モジュール化を利用すれば、サイドバーの情報は非同期で表示させられるので、ユーザはページをストレスなく閲覧することが可能になります。
再構築時間は PHPモジュール化と同じ効果があります。
ただし内部リンク等がインクルード元のページに表れないため、SEO という観点では注意が必要かもしれません。
当サイトでは、数ヶ月前からサイドバーやメインページ上部にある多くのリストを Ajax モジュール化しており、安定して表示されることが確認できたので、本エントリーにて設定方法を説明します。
また、Ajax と JavaScript の併用や関連テクニックについても分かる範囲で解説しています。
以下、当サイトの配布テンプレートをサンプルに、「最近のエントリー」の Ajax モジュール化を例にします。
2.prototype.js のダウンロード・アップロード
上記のサイトにある Download the latest version のリンクをクリックし、アーカイブをダウンロードします。アーカイブを解凍して、dist フォルダの中にある prototype.js を使用します(他は使いません)。
prototype.js は index.html と同じディレクトリにアップロードしてください。
3.モジュールの作成
MT3.3x の場合、[テンプレート] - [テンプレートを新規作成] で、「最近のエントリー」用のテンプレートを作成。各項目には下記を設定。
- テンプレート名:最近のエントリーAjaxモジュール(名前は何でもいいです)
- 出力ファイル名:recentEntries.html
- このテンプレートにリンクするファイル:(設定不要)
- 再構築オプション:チェックする
- テンプレートの内容:下記
<div class="sidetitle"> Recent Entries </div> <div class="side"> <MTEntries lastn="10"> <a href="<$MTEntryPermalink$>" title="e<$MTEntryID$>"><$MTEntryTitle$></a><br /> </MTEntries> </div>
4.テンプレートの修正
インデックステンプレートや各アーカイブテンプレートで「最近のエントリー」を表示させているタグを、下記に置き換えます。
<div id="entries"></div>
<script type="text/javascript">
//<![CDATA[
getFile('<MTBlogURL>recentEntries.html', 'entries');
//]]>
</script>
getFile のパラメータには、Ajax で取得したいファイル名(3項のファイル名)と、その id 属性(上記リストの1行目の div の id 属性に設定した属性値)を設定してください。
5.JavaScript の追加
下記のスクリプトを外部ファイル(例えば ajaxUtil.js )として保存し、index.html と同じディレクトリにアップロードしてください。
function getFile(url, id) {
url = url + "?" + Math.random();
new Ajax.Updater({success: id},
url, {
method: 'get',
onComplete: end,
onFailure: error
});
return false;
}
getFile の中で prototype.js の Ajax.Updater を呼び出しています。
prototype.js は Ajax.Request が一般的ですが、取得したデータの表示位置をダイナミックに振り分けることができません。Ajax.Updater を用いれば関数起動時に id 属性(=取得データの表示位置)を指定できるので、複数のリストをこのスクリプトひとつで賄うことができます。
Ajax.Updater の解説は下記に詳しく書かれています。
6.script 要素の追加
3のスクリプトを読み込むため、テンプレートに script 要素を </head> の直前に追加。
<script type="text/javascript" src="<$MTBlogURL$>ajaxUtil.js"></script>
7.モジュールの内容を常に更新する
prototype.js + IE では、モジュールの内容が更新されても、インクルード元のページの更新では最新の内容が反映されない事象が発生します。
その対策として、URL にランダムなクエリーを与えることで(下記)、モジュールの内容を毎回更新するようにしています。
url = url + "?" + Math.random();
参考ページを失念してしまったので、これにつきましては分かり次第掲載します。また他のライブラリであればOKとか、エレガントな実装等、さらに良い方法がありましたらご教示ください。
8.JavaScript を利用する場合のテクニック
「サイドメニューの折りたたみ」や「ツリー化」、あるいは「新着表示」等、リストに対して JavaScript を適用させたい場合、起動用の script 要素の挿入位置に気をつける必要があります。
下は4項のリストに折りたたみのスクリプト(青色)を埋め込んだ失敗例です。
<div id="entries"></div>
<script type="text/javascript">
//<![CDATA[
getFile('recentEntries.html', 'entries');
FoldNavigation('newentry','on',false);
//]]>
</script>
このようにインクルード元にインクルード先を制御するスクリプト(この例では FoldNavigation)を記述しても、 スクリプトが実行されるタイミングでは該当のリストが存在しない(=非同期で取得される)ためエラーになります。
モジュール自体にスクリプトを埋め込んだ場合も、正常に動作しないようです。
これを解決するには、Ajax でモジュールが取得された後にスクリプトを実行するようにします。例えば5項の ajaxUtil.js に下記の関数を追加します。
function end(req) {
if(req.responseText.match(/id="newentryname"/)){
FoldNavigation('newentry','on',false);
return;
}
}
これは5項の onComplete で起動される関数です。当サイトで公開している Ajax 月送りカレンダーもこの方法で休日表示のスクリプトを起動しています。
2007.08.20
3項に再構築オプションの設定の説明を追加しました。

