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項に再構築オプションの設定の説明を追加しました。
- iPhoneで通信量を調べる方法
- Ajaxによるモジュール化(jQuery版)
- Movable Type 4.2 における mt.js の変更点(その1:Ajax 対応と window.onload の代替スクリプト)
- Ajax でキャッシュさせない方法
- Safari の Ajax 文字化け対処
- 複数ブログで Ajax 月送りカレンダーを利用する方法
- はてなブックマークの「人気エントリー/注目エントリー」を Ajax + Perl でブログに表示する
- BlogPeople 等のリンクリストによる表示の遅延を解消する(その2:Ajax編)
≫ SEO対策セミナー・コンサルティング・塾 from SEO対策セミナー・コンサルティング・塾
本物のSEO対策!3億2100万件中1位表示の実績!会員制SEOサポート塾が遂に開講! [続きを読む]
javascriptエラーが出たので、
5.JavaScript の追加 で、
onComplete: 'end',
onFailure: 'error'
と、シングルクォートで囲み、
6.script 要素の追加 で、prototype.js も読ませてエラーが消せたのですが、
「Recent Entries」下の表示が、<$MTEntryTitle$>とそのまま出てきてしまいます。またリンク先もMTタグがそのまま出てきます。どうすれば正常に表示できるか、ご存知でしたらお教えください。よろしく願いいたします。
お騒がせします。MTタグが表示される問題は解消されましたが、
7.モジュールの内容を常に更新する
prototype.js + IE では、モジュールの内容が更新されても…
の件に書かれてある通り、エントリを追加しても、そのあと
recentEntries.html を再構築しないと画面表示されませんでした。
解決法をお探し中と書かれておりましたので
recentEntries.html をその都度再構築する運用をしつつ、気長に待たせていただきます。
>yakitoribankさん
こんにちは。
説明不足ですいません。
recentEntries.htmlのテンプレート編集画面で「再構築オプション」にチェックをつけてください。これでエントリ追加時に自動的に再構築されるので、個別に再構築する必要はなくなります(本文にその旨追記致しました)。
ちなみに7項の対処とrecentEntries.html の再構築について、関連はありません。
それではよろしくお願い致します。
いつもいつもお世話になります。
試しに“Recent Entries”を四苦八苦しつつ(笑)モジュール化してみたのですが、Firefoxでは折り畳みの動作も含めキチンと表示されるのですが、IE(Sleipnir)ではメニューそのものが表示されません。ブラウザによる違いの原因がどこにあるのかつかみかねております。MTIfタグを外した状態をモジュール化しています。
アドバイスいただけますと幸いです。
>toycozyさん
こんばんは。
ご質問の件ですが、prototype.js のバージョンを1.6ではなく、1.5.1.1で試してみてもらえますでしょうか。
それではよろしくお願い致します。
御手数をお掛けしてます。
1.5.1.1に入れ替えて試してみたのですがIEがダメみたいです。
もう少し試行錯誤してみます。アドバイス有り難うございました。
>toycozyさん
こんばんは。
ご返事遅くなりすいません。
色々調べてみましたが、分かったのは「newsing」のリストが前にあると正常に動作しなくなる、ということだけでした。
解決策はみつかっておりません。
お役に立てず申し訳ありません。
それではよろしくお願い致します。
別件ですが、行き違いで質問させていただいたところでした。
こちらこそ御手数をお掛けし申し訳ありません。やっぱりブログパーツですか・・・。
firefoxだと問題ないようなので、そこはスルーしてました。IEとの相性やブログパーツそのものとの整合性みたいなものもあるんでしょうね~・・・。もうちょっと試行錯誤の旅を続けてみます(笑)。御回答いただき有り難うございました。
いつもお世話になっております。
本記事の「Ajax によるモジュール化」と以前の記事にありました「新着に New マークをつける」記事にありましたスクリプトを一緒に使いたいと思っております。
いろいろ試しては見ましたが、上の8項function end(req)のところをどうしてよいのかわかりません。
ご教示いただけますでしょうか。
よろしくお願いいたします。
>Mwaveさん
こんにちは。
ご質問の件ですが、別途エントリーしたいと思います。
すいませんがお時間ください。