通常のスタティックな Web サイトにおいて、Web ページの中で更新頻度の高いパーツを別ファイルにして、それをインクルードするシーンは多々あるかと思います。 Movable Type でも、モジュールやウィジェットを「インデックステンプレートのコンテキストで全ページに表示させたい」なんてとき、インデックステンプレートに読み込み用のファイルを作って、それを MTInclude で読み込むという手法...
通常のスタティックな Web サイトにおいて、Web ページの中で更新頻度の高いパーツを別ファイルにして、それをインクルードするシーンは多々あるかと思います。
Movable Type でも、モジュールやウィジェットを「インデックステンプレートのコンテキストで全ページに表示させたい」なんてとき、インデックステンプレートに読み込み用のファイルを作って、それを MTInclude で読み込むという手法で実現するのが一般的だと思います。
さて、ファイルを読み込む方法には、大きく分けると、サーバーサイドインクルード( SSI )とクライアントサイドインクルード( CSI )、がありますが、今回は後者の「クライアントサイド」で読み込む方法を jQuery を使ってやってみました。
いわゆる「 jQuery によるモジュール化」と言ったところです。
jQuery でのファイルの読み込みは、「Movable Type 備忘録 - jQuery でカンタンに外部ファイルを読込む(jquery.inc)」で紹介されている便利な jQuery プラグインを使う手もあります。手軽で便利なので試してみてください。
ただ、僕が使ったときは、ちゃんと UTF-8 で保存したのになぜか IE 6 で表示すると日本語が文字化けしてしまいました。なんで? また、インクルードしたファイルは、インクルードを指定した要素の子要素としてしか読み込めないようなので、ウィジェット部分の dt、dd 要素だけを読み込みたいときにはちょっと困りました。
そこで、今回は自分的にもう少し使いやすくした jQuery_inc.js を作ってみました。
この JavaScript のメリットをいくつかあげてみます。
1 つのファイルから、読み込むモジュールをCSS セレクタのように指定するので、複数のパーツを 1 ファイルにまとめて管理できます。
1 モジュール = 1 ファイルだと、数が増えてくると管理が大変になります。その点、全てのモジュールを 1 ファイルにまとめられれば管理が楽です。
XHTML ファイルにまとめることで、head 要素内で文字コードも宣言するので、IE でも文字化けしないと思います。
極端な話、モジュール用のインデックステンプレートすら作らなくても良くなります。メインインデックス( index.html )からインクルードするという荒業も可能です。お勧めしませんが。。
「<div class="読み込み元"><p>ここに読み込む</p></div>」
のように子要素に読み込むだけでなく、
「<div class="読み込み元"></div><p>ここに読み込む</p>」
のように読み込み要素と置換することも可能です。
この柔軟性のおかげで、valid なソースを書きやすくなります。
モジュール用ファイルを編集しなくても、読込先を指定するセレクタを変更すれば、読み込む要素を変えられます。
/*
* jQuery_inc.js
*
* Copyright (c) 2008 Tomohiro Okuwaki (/blog/)
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* Modified: 2008-11-10
* Document: /blog/2008/11/10-173717.html
*
*/
function strRef (text) {
text = text.replace(/&/g,'&');
text = text.replace(/</g,'<');
text = text.replace(/>/g,'>');
text = text.replace(/"/g,'"');
return text;
}
jQuery(document).ready(function(){
jQuery('.jquery_inc').each(function(){
var inc_url = '/jquery_inc.html'; /* <== Edit it first */
var inc_selector = jQuery(this).attr('title');
var replace_inc = jQuery(this).filter('.replace_inc').size();
var file_inc = jQuery(this).filter('.file_inc').size();
var child_inc = jQuery(this).filter('.child_inc').size();
inc_selector = strRef(inc_selector);
if (jQuery.browser.msie) {
/* for IE [start] */
if (file_inc) {
inc_selector = inc_selector.replace(/ ?/,':');
inc_selector = inc_selector.split(':');
inc_url = inc_selector[0];
inc_selector = inc_selector[1];
}
if (child_inc) {
var matchStr = inc_url.match(' ');
if (matchStr) {
inc_selector = inc_selector + '>*';
}
}
jQuery.ajax({cache: false});
if (replace_inc) {
jQuery(this).load(
inc_url,
function () {
var default_content = jQuery(this).clone();
var inc_content = default_content.find(inc_selector);
jQuery(this).replaceWith(inc_content);
}
);
} else {
jQuery(this).load(
inc_url,
function () {
var default_content = jQuery(this).clone();
var inc_content = default_content.find(inc_selector);
jQuery(this).html(inc_content);
}
);
}
/* for IE [ end ] */
} else {
if (file_inc) {
inc_url = inc_selector;
} else {
inc_url = inc_url + ' ' + inc_selector;
}
if (child_inc) {
var matchStr = inc_url.match(' ');
if (matchStr) {
inc_url = inc_url + '>*';
}
}
jQuery.ajax({cache: false});
if (replace_inc) {
jQuery(this).load(
inc_url,
function () {
var default_content = jQuery(this).clone();
var inc_content = default_content.html();
jQuery(this).replaceWith(inc_content);
}
);
} else {
jQuery(this).load(inc_url);
}
}
});
});
このソースをコピーして保存するか、以下よりダウンロードしたファイルを解凍して保存します。
ここでは、Movable Type で使う場合を例に説明しますが、もちろん普通の Web サイトでも同様の考え方で使えます。
まず初めに、モジュール用ファイルを作成しておきましょう。Movable Type の場合、モジュールとして読み込みたい部分をまとめてインデックステンプレートとして作成すればOKです。
ここでは、「Recent Comments (最近のコメント)」と「Recommended (オススメ)」をモジュール化してみます。
なお、読み込むファイルをできるだけ軽くするために、余計な要素は排除してシンプルにしましょう。また、以下の例では、検索ロボットは一応拒否しています。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>jQuery Include - <$mt:BlogName$></title>
<meta name="ROBOTS" content="NONE" />
</head>
<body>
<dl id="wdg_include">
<dt>Recent Comments</dt>
<dd class="recentComments"><ul class="recentComments"><mt:Entries recently_commented_on="5">
<li><a href="<$mt:EntryLink$>"><$mt:EntryTitle$></a>
<ul><mt:Comments>
<li><a href="<mt:CommentEntry><$mt:EntryLink$></mt:CommentEntry>#comment<$mt:CommentID$>" title="<mt:SetVarBlock name="commentBodyCount"><$mt:CommentBody count_characters="1"$></mt:SetVarBlock><mt:If name="commentBodyCount" gt="50"><$mt:CommentBody remove_html="1" encode_html="1" trim_to="50" cat="..." regex_replace="/\n|\r\n/g",""$><mt:Else><$mt:CommentBody remove_html="1" encode_html="1"$></mt:If>" rel="nofollow"><mt:IfNonZero tag="CommentAuthor"><$mt:CommentAuthor$><mt:Else>No Name</mt:IfNonZero> - <$mt:CommentDate format="%m/%d"$></a></li></mt:Comments>
</ul></li></mt:Entries>
</ul></dd>
<dt>Recommended</dt>
<dd class="recommended">
<p><a href="http://getfirefox.jp/"><img src="<$mt:BlogURL$>img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125" /></a></p>
</dd>
</dl>
</body>
</html>
再構築したファイルは次のようになります。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja" dir="ltr">
<head>
<meta name="ROBOTS" content="NONE" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>jQuery Include - かたつむりくんのWWW</title>
</head>
<body>
<dl id="wdg_include">
<dt>Recent Comments</dt>
<dd class="recentComments">
<ul class="recentComments">
省略
</ul>
</dd>
<dt>Recommended</dt>
<dd class="recommended">
<p><a href="http://getfirefox.jp/"><img src="/blog/img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125" /></a></p>
</dd>
</dl>
</body>
</html>
以下の説明で出てくるサンプルも、基本的にこのモジュール用ファイルからインクルードすることにします。
jquery_inc.js の 22 行目当たりのファイルのパスを、作成したモジュール用ファイルのパスに変更します。
var inc_url = '/jquery_inc.html'; /* <== Edit it first */
jquery_inc.js をサーバーにアップロードし、jQuery とともに読み込みます。ファイルへのパス部分は適宜変更してください。ここでは jQuery は 「AJAX Libraries API - Google Code」を使って読み込んでいます。
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.2");</script>
<script type="text/javascript" src="/js/jquery_inc.js" charset="UTF-8"></script>
インクルードしたい場所のソースに、以下のような title 属性、class 属性を設定します。
モジュール用ファイルの読み込みたい要素を jQuery のセレクタで指定します。jQuery のセレクタについては、次のページが参考になります。シンプルな CSS セレクタなら、ほぼそのまま使えます。
なお、< > & などは実体参照にすることを忘れずに。
jquery_inc.js を使ってモジュールを読み込みたい要素に設定します。必須です。
<Element class="jquery_inc" title="selector"> ~ </Element>
【サンプル】 dd.recommended 内の p 要素をインクルート
[読み込みたいソースは次の p 要素]
<dd class="recommended">
<p><a href="http://getfirefox.jp/"><img src="/blog/img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125" /></a></p>
</dd>
[読み込みたい場所のソース]
<div class="jquery_inc" title="#wdg_List_RecentComments dd.recommended p">
ここに読み込みます
</div>
[読み込み後のソース]
<div class="jquery_inc lastChild" title="#wdg_List_RecentComments dd.recommended p">
<p><a href="http://getfirefox.jp/"><img src="/blog/img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125"></a></p>
</div>
title 属性で指定した要素の「子要素」をインクルードしたい場合に設定します。
<Element class="jquery_inc child_inc" title="selector"> ~ </Element>
一つ手前のサンプルでは、セレクタで dd.recommended の子要素の p 要素まで指定しましたが、child_inc クラスをつければ少しシンプルになります。
[セレクタで指定]
<div class="jquery_inc" title="#wdg_include dd.recommended p">
[child_inc クラスで指定]
<div class="jquery_inc child_inc" title="#wdg_include dd.recommended">
このように子要素が一つのときは無意味に思えるかもしれませんが、dl 要素の子要素の dt、dd 要素など、複数の子要素をまとめてインクルードしたいときに威力を発揮します。
インクルードしたい場所の要素を、インクルードした要素と置き換えます。
<Element class="jquery_inc replace_inc" title="selector"> ~ </Element>
【サンプル】 span.test を dd.recommended 内の p 要素と置換
[読み込みたいソースは次の p 要素]
<dd class="recommended">
<p><a href="http://getfirefox.jp/"><img src="/blog/img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125" /></a></p>
</dd>
[読み込みたい場所のソース]
<dl>
<dt>Recommended</dt>
<dd class="recommended">
<span class="test jquery_inc replace_inc" title="dd.recommended p">ここに読み込みます</span>
</dd>
</dl>
[読み込み後のソース]
<dl>
<dt>Recommended</dt>
<dd class="recommended lastChild">
<p><a href="http://getfirefox.jp/"><img src="/blog/img/banner/firefox_125x125_rounded_blue.png" alt="Mozilla Firefox ブラウザ無料ダウンロード" title="Mozilla Firefox ブラウザ無料ダウンロード" width="125" height="125"></a></p>
</dd>
</dl>
通常は、最初に設定した一つのファイルからモジュールをインクルードしますが、file_inc クラスをつけると、別のファイルからインクルードすることができます。その場合、title 属性を「(読み込みたいファイルの URL ) + (半角スペース) + (セレクタ)」と記述します。
<Element class="jquery_inc file_inc" title="URL selector"> ~ </Element>
【サンプル】 トップページの最新記事タイトルをインクルード
[読み込みたい場所のソース]
<p>最新の記事 : <span class="jquery_inc replace_inc file_inc" title="/blog/ #primary h2 a:first">最新記事を読み込みます</span></p>
[読み込み後のソース]
<p>最新の記事 : <a href="/blog/2008/11/05-124152.html">ブログ記事を「公開した日時」を自動的にカスタムフィールドで保存するカスタマイズ</a></p>
この jQuery を使ったインクルードは、読み込み後のコンテンツがソースに反映されていないため、SEO 的に若干問題があるかもしれません。また、JavaScript がオフの状態だと、全く機能しなくなります。
しかし、replace_inc クラスを使えば、読み込みたい場所のソースを丸々置換できるので、代替コンテンツを入れておくことが可能です。
例えば、Movable Type の場合、全ページに同じ「インデックステンプレートのコンテキストの最新のブログ記事」を表示したいけど、保険として「ブログ記事コンテキスト(カテゴリごと)の最新のブログ記事」を表示させておく、などの方法が可能です。
jQuery について本で勉強したい場合は、以下の書籍がお勧めです。
以上です。