Ajax によるモジュール化

Ajax によるモジュール化

Posted at July 30,2007 2:50 AM
Tag:[Ajax]

Movable Type のサイドバーの各リストを、Ajax でモジュール化を行う方法を紹介します。

1.PHP モジュール化と Ajax モジュール化の違い

Movable Type における PHP モジュール化には次のようなメリットがあります。

  1. 再構築時間の削減
  2. アーカイブに依存しないリストの生成(今回はここに言及しません)

ただし PHP モジュール化は、ユーザがブラウザからインクルード元のページにアクセスした時、インクルード元のページはインクルード先の各モジュールを読み込んだコンテンツを生成・返却するため、サイドバーに多くの情報をインクルードしていると、PHP でページを生成する分、表示が遅延します。

本題とはそれますが、WordPress で表示までに若干のタイムラグが生じるのは、この PHP によるページ生成が行われるためです(キャッシュや条件付きGETが機能していればこの限りではありません)。

Ajax モジュール化を利用すれば、サイドバーの情報は非同期で表示させられるので、ユーザはページをストレスなく閲覧することが可能になります。
再構築時間は PHPモジュール化と同じ効果があります。

ただし内部リンク等がインクルード元のページに表れないため、SEO という観点では注意が必要かもしれません。

当サイトでは、数ヶ月前からサイドバーやメインページ上部にある多くのリストを Ajax モジュール化しており、安定して表示されることが確認できたので、本エントリーにて設定方法を説明します。
また、Ajax と JavaScript の併用や関連テクニックについても分かる範囲で解説しています。

以下、当サイトの配布テンプレートをサンプルに、「最近のエントリー」の Ajax モジュール化を例にします。

2.prototype.js のダウンロード・アップロード

Prototype JavaScript Framework

上記のサイトにある 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 の解説は下記に詳しく書かれています。

IT戦記:prototype.js 1.4rc4 Part.3

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項に再構築オプションの設定の説明を追加しました。

関連記事
トラックバックURL


トラックバック

SEO対策セミナー・コンサルティング・塾 from SEO対策セミナー・コンサルティング・塾
本物のSEO対策!3億2100万件中1位表示の実績!会員制SEOサポート塾が遂に開講! [続きを読む]

Tracked on July 30, 2007 4:35 AM

zz from ブログ検査ブログテストブログ検査ブログテストブログ検査
adgasdg [続きを読む]

Tracked on July 30, 2007 4:55 PM
コメント

javascriptエラーが出たので、


5.JavaScript の追加 で、

onComplete: 'end',
onFailure: 'error'

と、シングルクォートで囲み、

6.script 要素の追加 で、prototype.js も読ませてエラーが消せたのですが、

「Recent Entries」下の表示が、<$MTEntryTitle$>とそのまま出てきてしまいます。またリンク先もMTタグがそのまま出てきます。どうすれば正常に表示できるか、ご存知でしたらお教えください。よろしく願いいたします。

[1] Posted by yakitoribank : August 16, 2007 5:07 PM

お騒がせします。MTタグが表示される問題は解消されましたが、

7.モジュールの内容を常に更新する
prototype.js + IE では、モジュールの内容が更新されても…

の件に書かれてある通り、エントリを追加しても、そのあと
recentEntries.html を再構築しないと画面表示されませんでした。

解決法をお探し中と書かれておりましたので
recentEntries.html をその都度再構築する運用をしつつ、気長に待たせていただきます。

[2] Posted by yakitoribank : August 16, 2007 5:42 PM

>yakitoribankさん
こんにちは。
説明不足ですいません。
recentEntries.htmlのテンプレート編集画面で「再構築オプション」にチェックをつけてください。これでエントリ追加時に自動的に再構築されるので、個別に再構築する必要はなくなります(本文にその旨追記致しました)。
ちなみに7項の対処とrecentEntries.html の再構築について、関連はありません。
それではよろしくお願い致します。

[3] Posted by yujiro : August 20, 2007 3:05 PM

いつもいつもお世話になります。

試しに“Recent Entries”を四苦八苦しつつ(笑)モジュール化してみたのですが、Firefoxでは折り畳みの動作も含めキチンと表示されるのですが、IE(Sleipnir)ではメニューそのものが表示されません。ブラウザによる違いの原因がどこにあるのかつかみかねております。MTIfタグを外した状態をモジュール化しています。

アドバイスいただけますと幸いです。

[4] Posted by toycozy : December 7, 2007 10:27 PM

>toycozyさん
こんばんは。
ご質問の件ですが、prototype.js のバージョンを1.6ではなく、1.5.1.1で試してみてもらえますでしょうか。
それではよろしくお願い致します。

[5] Posted by yujiro logo : December 9, 2007 12:24 AM

御手数をお掛けしてます。
1.5.1.1に入れ替えて試してみたのですがIEがダメみたいです。
もう少し試行錯誤してみます。アドバイス有り難うございました。

[6] Posted by toycozy : December 9, 2007 12:04 PM

>toycozyさん
こんばんは。
ご返事遅くなりすいません。
色々調べてみましたが、分かったのは「newsing」のリストが前にあると正常に動作しなくなる、ということだけでした。
解決策はみつかっておりません。
お役に立てず申し訳ありません。
それではよろしくお願い致します。

[7] Posted by yujiro logo : December 18, 2007 10:31 PM

別件ですが、行き違いで質問させていただいたところでした。
こちらこそ御手数をお掛けし申し訳ありません。やっぱりブログパーツですか・・・。
firefoxだと問題ないようなので、そこはスルーしてました。IEとの相性やブログパーツそのものとの整合性みたいなものもあるんでしょうね~・・・。もうちょっと試行錯誤の旅を続けてみます(笑)。御回答いただき有り難うございました。

[8] Posted by toycozy : December 18, 2007 11:36 PM

いつもお世話になっております。
本記事の「Ajax によるモジュール化」と以前の記事にありました「新着に New マークをつける」記事にありましたスクリプトを一緒に使いたいと思っております。
いろいろ試しては見ましたが、上の8項function end(req)のところをどうしてよいのかわかりません。
ご教示いただけますでしょうか。
よろしくお願いいたします。

[9] Posted by Mwave : November 19, 2008 6:10 PM

>Mwaveさん
こんにちは。
ご質問の件ですが、別途エントリーしたいと思います。
すいませんがお時間ください。

[10] Posted by yujiro logo : November 21, 2008 3:25 PM
コメントする
greeting

*必須

*必須(非表示)


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

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

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

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