2007年8月18日

Ajax 月送りカレンダー(MT4版)

August 18,2007 3:33 AM
Tag:[, , , ]
Permalink
Ajax 月送りカレンダーMovable Type 4 版の Ajax 月送りカレンダーのカスタマイズです。リアルタイムカレンダー(本日の日付の装飾)および土・日・休日表示も盛り込まれています。

MT4 では、MT3 で紹介した「Ajax 月送りカレンダー」とは、アーカイブマッピングの方法が異なっており、「MT4でのカスタマイズ方法が分かりません」というリクエストを頂きましたので、本エントリーにて説明致します。
Ajax 月送りカレンダーの概要は割愛します(「Ajax 月送りカレンダー」をご覧ください)。

ここではデフォルトテンプレートおよび公開テンプレートをサンプルにしますが、Ajax の動作はテンプレートに依存するものではありませんので、CSS を変更すれば他のテンプレートでもお使いになれます。

1.スクリプトのダウンロード・アップロード

下記のスクリプトをダウンロードします。

ダウンロードした ajaxCalendar.jsdayChecker.js はメインページと同じディレクトリにアップロードしてください。
また prototype.js も、ダウンロードしたスクリプトをメインページと同じディレクトリにアップロードしてください。

2.カレンダーテンプレート作成

注:ブログの文字コードが UTF-8 以外で運用されている場合は、2.1項のカスタマイズも併せて行ってください。

管理メニューの「デザイン」→「テンプレート」→「アーカイブテンプレート」→「アーカイブテンプレートを作成」の「ブログ記事リスト」をクリック。

テンプレート新規作成

次画面で下記を設定してください。

  • テンプレート名(一番上のテキストフィールド):カレンダー
  • ファイルへのリンク:(設定不要)
  • テンプレートの内容(テキストエリア):下記のいずれか
    注:テキストエリアにペーストする際はテキストエリア右上にある構文強調表示切替を「強調表示なし」を選択してから作業を行ってください。「構文強調表示」の状態でペーストするとテンプレートの内容の改行が失われます。
    構文強調表示

デフォルトテンプレートの場合

<div class="widget-calendar widget">
<h3 class="widget-header"><MTArchivePrevious><a href="javascript:void(0);" onclick="changeMonth('<$MTBlogArchiveURL$><MTArchiveDate format="calendar/%Y/%m/%i">');">&#65308;</a> </MTArchivePrevious><$MTArchiveDate format="%B %Y"$><MTArchiveNext> <a href="javascript:void(0);" onclick="changeMonth('<$MTBlogArchiveURL$><MTArchiveDate format="calendar/%Y/%m/%i">');" >&#65310;</a></MTArchiveNext></h3>
<div class="widget-content">
<table summary="<MTArchiveDate format="%Y/%m">">
<tr height="15">
<th abbr="Sunday" class="sunday">Sun</th>
<th abbr="Monday">Mon</th>
<th abbr="Tuesday">Tue</th>
<th abbr="Wednesday">Wed</th>
<th abbr="Thursday">Thu</th>
<th abbr="Friday">Fri</th>
<th abbr="Saturday" class="saturday">Sat</th>
</tr>
<MTCalendar month="this">
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<td><MTCalendarIfBlank><MTElse><span></MTElse></MTCalendarIfBlank><MTCalendarIfEntries>
<MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"><$MTCalendarDay$></a></MTEntries>
</MTCalendarIfEntries><MTCalendarIfNoEntries><$MTCalendarDay$></MTCalendarIfNoEntries><MTCalendarIfBlank>
<MTElse></span></MTElse></MTCalendarIfBlank></td><MTCalendarWeekFooter></tr></MTCalendarWeekFooter></MTCalendar>
</table>
</div>
</div>

公開テンプレートの場合

<table summary="<MTArchiveDate format="%Y/%m">">
<caption class="calendarhead">
<MTArchivePrevious>
<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogArchiveURL$><MTArchiveDate format="calendar/%Y/%m/%i">');">&#65308;</a>
</MTArchivePrevious>
<$MTArchiveDate format="%B %Y"$> 
<MTArchiveNext>
<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogArchiveURL$><MTArchiveDate format="calendar/%Y/%m/%i">');" >&#65310;</a>
</MTArchiveNext>
</caption>
<tr height="15">
<th abbr="Sunday" class="sunday">Sun</th>
<th abbr="Monday">Mon</th>
<th abbr="Tuesday">Tue</th>
<th abbr="Wednesday">Wed</th>
<th abbr="Thursday">Thu</th>
<th abbr="Friday">Fri</th>
<th abbr="Saturday" class="saturday">Sat</th>
</tr>
<MTCalendar month="this">
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<td><MTCalendarIfBlank><MTElse><span></MTElse></MTCalendarIfBlank><MTCalendarIfEntries>
<MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>"><$MTCalendarDay$></a></MTEntries>
</MTCalendarIfEntries><MTCalendarIfNoEntries><$MTCalendarDay$></MTCalendarIfNoEntries><MTCalendarIfBlank>
<MTElse></span></MTElse></MTCalendarIfBlank></td><MTCalendarWeekFooter></tr></MTCalendarWeekFooter></MTCalendar>
</table>

設定後は次のような感じになります。

テンプレート作成

設定が終わったら「保存」をクリックしてください。

2.1 ブログの文字コードがUTF-8以外の場合

Ajax(XMLHttpRequest)は UTF-8 で動作することを前提としています。他の文字コードでブログを運用している場合、本カスタマイズが正常に動作しない可能性があります。*1

ここではひとつの解決方法として Ogawa::memoranda さんの MT-I18N プラグインを利用する方法を紹介します。つまりブログの文字コードが UTF-8 以外の場合、プラグインを利用してカレンダーアーカイブの文字コードだけ UTF-8 で出力するという作戦です。

まず、MT-I18N Plugin.ja JP をダウンロードして、プラグイン mt-i18n.pl を plugins フォルダにアップロードします。

そして、2項で示したカレンダーテンプレート全体を下記の青色のタグで括ってください。

<MTEncodeText to="utf8">
      :
 (カレンダーテンプレート)
      :
</MTEncodeText>

本プラグインを利用し、EUC-JP、Shith_JIS で作成した Movable Type のサイトで、カレンダー動作と日本語表示の正常性は確認済です。ただし、.htaccess 等で文字コードを強制的に指定している場合は未確認です。

3.カレンダーテンプレートを月別アーカイブに関連付け

テンプレートを保存すると、同じページの下に「アーカイブマッピング」の項目が表示されるので、「新しいアーカイブマッピングを作成」をクリック。

アーカイブマッピング

「種類」から「月別」を選択して「追加」をクリック。

アーカイブマッピング追加

これでカレンダーテンプレートが月別アーカイブとして定義され、カレンダー用の「パス」が表示されます。
注:「月別」欄の右側にあるチェックボックスは絶対にチェックしないでください。

アーカイブマッピング追加完了

次に「パス」欄の右にあるセレクトボックスより「カスタム」を選択。

セレクトボックスより「カスタム」を選択

「パス」欄に下記の内容を設定して、「保存」をクリックしてください。

calendar/%y/%m/%i

パス変更

下のようになればアーカイブマッピングの設定完了です。

パス変更完了

4.日別アーカイブの追加

この設定は、カレンダーに表示された日付のリンク先のページとして日別アーカイブを生成するためのものです。
注:この設定を行わないと月別アーカイブの再構築で下記のエラーが表示されます。

再構築エラー

「デザイン」→「テンプレート」→「アーカイブテンプレート」→「ブログ記事リスト」を選択し、アーカイブマッピングの「新しいアーカイブマッピングを作成」をクリック。

アーカイブマッピング

「日別」を選択して「追加」をクリック。

アーカイブマッピング

これで日別アーカイブが追加されました。

日別アーカイブの追加

5.テンプレート修正

5.1 外部ファイルのインクルード

「デザイン」→「テンプレート」→「テンプレートモジュール」→「ヘッダー」をクリックし、<head>~</head> の間に下記を追加して「保存」をクリック。

<script type="text/javascript" src="<$MTBlogURL$>prototype.js"></script>
<script type="text/javascript" src="<$MTBlogURL$>ajaxCalendar.js"></script>
<script type="text/javascript" src="<$MTBlogURL$>dayChecker.js"></script>

5.2 カレンダー表示部分の設定

「デザイン」→「テンプレート」→「テンプレートモジュール」→「サイドバー2(またはサイドバー)」をクリックし、カレンダーを表示させたい位置に下記を追加して「保存」をクリック。

<div id="calendar"></div>
<script type="text/javascript">
getCalendar("<$MTBlogArchiveURL$>", "<$MTBlogID$>", "<$MTBlogArchiveURL$><MTEntries lastn="1" sort_order="descend"><$MTEntryDate format="calendar/%Y/%m/" $></MTEntries>");
</script>

div は空要素ですが、Ajax によってこの部分にカレンダーが表示されます。

6.CSS修正

「デザイン」→「テンプレート」→「スタイルシート(メインまたはベーステーマ)」を選択し、下記を追加して「保存および再構築」をクリックします。

デフォルトテンプレートの場合

確認中

公開テンプレートの場合

#calendar {
    margin: 5px 0 10px;;
    color: #444444;
}
.calendarhead {
    padding-bottom: 5px;
    font-size: 9px;
    letter-spacing: 0.2em;
}
#calendar table {
    padding: 0;
    border-collapse: collapse;
}
#calendar th {
    padding-bottom: 3px;
    text-align: center;
    font-size: 9px;
    width: 23px;
}
#calendar td {
    padding: 2px 0;
    text-align: center;
    font-size: 10px;
    line-height: 120%;
}
.today {
    display: block;
    border: 1px solid #444444;
}
.sunday,
.holiday,
.holiday a:link,
.holiday a:visited {
    color: #e50003;
}
.saturday,
.saturday a:link,
.saturday a:visited {
    color: #0000ff;
}

公開テンプレートの場合、すでにカレンダー関係のスタイル設定が行われており、設定の競合を避けるため、古い設定(下)を削除またはコメントアウトしてください。

/* カレンダー */
.calendarhead {
    padding-bottom: 5px;
    text-align: center;
    color: #333;
    font-size: 9px;
    background: none;
    letter-spacing: 0.2em;
}
#calendar table {
    text-align: center;
    padding: 0px;
    border-collapse: collapse;
}
#calendar th {
    padding-bottom: 3px;
    font-size: 8px;
    width: 23px;
}
#calendar td {
    padding: 2px 0;
    font-size: 9px;
    line-height: 120%;
}
span.day {
    text-align: center;
    font-size: 9px;
}
span.saturday {
    color: blue;
}
span.sunday {
    color: #e50003;
}
td.today {
    display: block;
    border: 1px solid #333;
}

7.再構築

全てのページを再構築します。これでメインページ等を表示してカレンダーが表示されれば完成です。

8.ページ表示時にローディング状態を表示する場合

インチキっぽいですが、4.2項で設定した

<div id="calendar"></div>

に、例えば青色の

<div id="calendar">loading ...</div>

を追加することで、ページ描画でカレンダーが表示されるまでローディング状態を示すことができます。img タグを設定すれば画像を表示することも可能です。

月送り時は挿入した文字は表示されません。またカレンダー取得失敗の場合は表示が消えます(これは7項の設定と関連します)。

9.カレンダー取得失敗時にメッセージ等を表示する

Ajax 月送りカレンダーは HTTP 非同期通信でカレンダーファイルを取得・表示しますが、何らかの原因で通信に失敗し、正常に取得できない可能性があります。当サイトで運用していた時も 503 エラーが多発すると取得に失敗するようです。

このカスタマイズではカレンダーの取得に失敗した場合、カレンダー表示エリアに正常に取得できなかったメッセージ

File Not Found

を表示するようにしています。このメッセージは ajaxCalendar.js の下記の青色部分が対応します。

function errorProcess() {
    $('calendar').innerHTML = 'File Not Found';
}

メッセージを変更したい場合はこの青色部分を修正してください。またこの1行を丸ごと削除すれば、HTTP 非同期通信に失敗した場合にカレンダー表示エリアの書き換えが行われなくなりますが、6項の表示がそのまま残りますのでご注意ください。

「失敗してもカレンダーを表示させたい」という場合は、上記メッセージ出力の1行を削除して、6項の「loading ...」というメッセージの代わりに、カレンダータグ(通常のカレンダータグ)を埋め込んでおくという手もあります。通信が成功すれば Ajax 月送りカレンダーに切り替わり、失敗すれば通常のカレンダーがそのまま表示されます。

10.トラブルシューティング

10.1 一度も表示されない場合

カレンダーが正常に表示されない場合、つまり上記のカスタマイズをそのまま行って、カレンダーが表示される位置に "File Not Found" が表示された場合、以下の問題が考えられます(全てではありませんが思いついたものを挙げておきます)。

  • カレンダーアーカイブの再構築ができていない
  • カレンダーアーカイブページへのパス設定が誤っている
  • テンプレートに設定したカレンダーアーカイブページの拡張子が不一致
  • カレンダーアーカイブが UTF-8 で出力されていない

ご質問の前に確認していただきたいのは、

  1. ブラウザの[表示]-[ソース](あるいは「ソースの表示」)で、カレンダーを設定しているページのソースを表示
  2. 表示されたソースから下記のタグをみつけ、getCalendar() の3番目のパラメータに設定されている URL(赤色)をブラウザに設定して実行
<div id="calendar"></div>
<script type="text/javascript">
getCalendar("http://user-domain/", "1", "http://user-domain/calendar/yyyy/mm/");
</script>

何も表示されない場合(404 Not Found)はカレンダーアーカイブへのパスの設定が誤っているか、アーカイブが生成されていない可能性があります。

逆に、カレンダーが表示されてブラウザにそのカレンダーが表示されない場合は、ブラウザの再起動や、ブラウザのキャッシュ・一時ファイルの削除等を行ってみてください。また UTF-8 以外で運用されている方は、カレンダーが表示されている状態で、ブラウザの[表示]-[エンコード]でカレンダーのページの文字コードが UTF-8 になっていることを確認してください。

10.2 一度表示され、リロードすると表示されなくなる場合

クッキーを削除した直後のカレンダーは表示されるけれども、月送りのリンクをクリックすると File Not Found が表示されるという場合は、2項のテンプレートに埋め込んでいるアーカイブパスが誤っている可能性があります。よくあるのは次のように最後の"/"が抜けているケースです。

<div id="calendar"></div>
<script type="text/javascript">
getCalendar("http://user-domain/archives", "1", "http://user-domain/archives/calendar/yyyy/mm/");
</script>

これは、管理画面の [設定] - [公開] で「アーカイブの設定」にチェックをつけていて、 [アーカイブURL] の最後に "/" がない場合に発生します。

2007.08.21
2項と4項の「ブログ記事」を「ブログ記事リスト」に修正しました。

2007.11.08
5.2項のタグに一部誤りがありましたので修正致しました。

2008.02.04
typo を修正しました(Wen → Wed)。


*1:文字コードの設定を行わずに Movable Type をインストールした場合の文字コードは UTF-8 です。

Comments [93] | Trackbacks [12]
2007年8月 6日

Ajax でキャッシュさせない方法

August 6,2007 12:55 AM
Tag:[, ]
Permalink

先日エントリーした、「Ajax によるモジュール化」で「Ajax を利用した時にキャッシュから取得しないようにしています」と書きましたが、最初にみつけた参考サイトが見つかりました。

Script雑感:Ajax?文字化け対策とブラウザキャッシュ対策

他にも、キャッシュの問題回避について、結構情報ありました。

まとめると、

  • POSTメソッドを用いる
  • ランダムなクエリーを与える
  • If-Modified-Sinceヘッダを用いる

の3パターンのようです。
クエリーにはタイムスタンプがいいみたいですね。

Comments [2] | Trackbacks [0]
2007年7月30日

Ajax によるモジュール化

July 30,2007 2:50 AM
Tag:[]
Permalink

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

Comments [8] | Trackbacks [2]
2007年7月 2日

ページ分割の Ajax 化

July 2,2007 2:35 AM
Tag:[, , , ]
Permalink

Movable Type で MTPaginate を利用したページ分割の Ajax 化です。

このカスタマイズは1年以上前に作ったもので、実装がいまひとつなため公開していなかったのですが、「こういうやり方もあります」という、案レベルの位置づけで公開します。

サンプルを用意しましたのでお試しください(ファイルサイズが小さいため効果が分かりにくいです)。

仕組みは、ページナビゲーションのリンクをクリックした時、リンク先のページを Ajax 経由で呼び出し、取得したファイルから必要な部分だけを切り出して、ページに表示させるというものです。

以下、カスタマイズ方法です。

ページ分割用プラグインは MTPaginate バージョン 1.28 を利用しています。プラグインは「MT Extensions: MTPaginate」よりダウンロードし、Movable Type に予めインストールし、ページ分割の設定まで行っておいてください。ページ分割の方法については「ページ分割」のカテゴリーを参照願います。

本エントリーのカスタマイズはトップページまたはエントリー・アーカイブ以外のアーカイブページでのみ有効です。またブログの文字コードが UTF-8 のみ適用可能です。

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

Prototype JavaScript Framework

上記のサイトにある Download the latest version のリンクをクリックし、アーカイブをダウンロードします。アーカイブを解凍して、dist フォルダの中にある prototype.js を使用します(他は使いません)。
prototype.js は index.php と同じディレクトリにアップロードしてください。

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

下記の paginate.js をダウンロードし、index.php と同じディレクトリにアップロードしてください。

paginate.js

3.プラグインファイル修正

MTPaginate/lib/MTPaginate.pm

を任意のエディタで開き、下記の赤色部分を青色の内容に書き換えます。

sub PaginateNavigator {
    :
  (中略)
    :
    } else {
        my $target = $args->{target} || "";
        if($pg->{mode} eq 'cgi') {
            $target = " target=\"$target\"" if $target;
            if ($format_all && $place_all ne 'after') {
                my $title = "";
                $title =  sprintf(" title=\"$format_all_title\"", $num_pages) if $format_all_title;
                if($pg->{current_page} eq 'all') {
                    $res .= "$all_current$separator";
                } else {
                    $res .= "<a href=\"" . $pg->{paginate_self} . "=all$anchor\"$title$target>$all</a>$separator";
                    $res .= "<a href=\"\#\" onclick=\"changePage('" . $pg->{paginate_self} . "=all$anchor')\"$title$target>$all</a>$separator";
                }
            }
 
            $start = ($list_pages eq 'after') ? $pg->{current_page}+1 : 1;
            $end = ($list_pages eq 'before') ? $pg->{current_page}-1 : $num_pages;
            $format_title = " title=\"$format_title\"" if $format_title;
            for(my $i = $start; $i <= $end; $i++) {
                $res .= $separator if($i > $start);
                if($i eq $pg->{current_page}) {
                    $res .= sprintf("$format_current", $i);
                } else {
                    $res .= "<a href=\"" . $pg->{paginate_self} . "=$i$anchor\"$target" .  sprintf($format_title, $i) .  sprintf(">$format", $i) . '</a>';
                    $res .= "<a href=\"\#\" onclick=\"changePage('" . $pg->{paginate_self} . "=$i$anchor')\"$target" .  sprintf($format_title, $i) .  sprintf(">$format", $i) . '</a>';
                }
            }
 
            if ($format_all && $place_all eq 'after') {
                my $title = "";
                $title =  sprintf(" title=\"$format_all_title\"", $num_pages) if $format_all_title;
                if($pg->{current_page} eq 'all') {
                    $res .="$all_current$separator";
                } else {
                    $res .= "<a href=\"" . $pg->{paginate_self} . "=all$anchor\"$title$target>$all</a>$separator";
                    $res .= "<a href=\"\#\" onclick=\"changePage('" . $pg->{paginate_self} . "=all$anchor')\"$title$target>$all</a>$separator";
                }
            }
        } else {
            $target = " target=\\\"$target\\\"" if $target;
            $res = "<?php\n";
            if ($format_all && $place_all ne 'after') {
                my $title = "";
                $title =  sprintf(" title=\\\"$format_all_title\\\"", $num_pages) if $format_all_title;
                $res .=<<PHP
    if(\$paginate_current_page == 'all') {
        echo '$all_current$separator';
    } else {
        echo "<a href=\\\"\$paginate_self=all$anchor\\\"$title$target>$all</a>$separator";
        echo "<a href=\\\"\#\\\" onclick=\\\"changePage('\$paginate_self=all$anchor')\\\"$title$target>$all</a>$separator";
    }
PHP
            }
            
            $format_title = " . sprintf(' title=\"$format_title\"', \$i)" if $format_title;
            $res .=<<PHP;
for(\$i = $start; \$i <= $end; \$i++) {
    if(\$i > $start)
        echo '$separator';
    if(\$i == \$paginate_current_page) {
        echo sprintf("$format_current", \$i);
    } else {
        echo "<a href=\\\"\$paginate_self=\$i$anchor\\\"$target" $format_title .  sprintf('>$format', \$i) . '</a>';
        echo "<a href=\\\"\#\\\" onclick=\\\"changePage('\$paginate_self=\$i$anchor')\\\"$target" $format_title .  sprintf('>$format', \$i) . '</a>';
    }
}
PHP
            if ($format_all && $place_all eq 'after') {
                my $title = "";
                $title =  sprintf(" title=\\\"$format_all_title\\\"", $num_pages) if $format_all_title;
                $res .=<<PHP
    if(\$paginate_current_page == 'all') {
        echo '$separator$all_current';
    } else {
        echo "$separator<a href=\\\"\$paginate_self=all$anchor\\\"$title$target>$all</a>";
        echo "$separator<a href=\\\"\#\\\" onclick=\\\"changePage('\$paginate_self=all$anchor')\\\"$title$target>$all</a>";
    }
PHP
            }
            $res .=<<PHP;
?>
PHP
        }
    }
    return $res;
}

修正後、保存して元のディレクトリにアップロードしてください。

4.テンプレートに script 要素追加

ページ分割を行いたいテンプレートに、下記の script 要素を追加します。

<script type="text/javascript" src="<$MTBlogURL$>prototype.js"></script>
<script type="text/javascript" src="<$MTBlogURL$>paginate.js"></script>

5.Ajax 対象部分にHTMLコメント追加

Ajax 化を行ないたい部分に、下の HTML コメント(青色)を追加します。ここでは当サイトの配布テンプレートを使用しているので、中央カラム全体を括っている div 要素(id 属性 content)のすぐ内側に設定します。

     :
<div id="content">
<!-- AjaxStart -->
     :
   (中略)
     :
<!-- AjaxEnd -->
</div>
     :

2007.12.06
最後のリストより、<!-- /content --> を削除(MT4でコメントタグを削除したため)

Comments [16] | Trackbacks [2]
2007年5月 4日

Safari の Ajax 文字化け対処

May 4,2007 1:27 AM
Tag:[, ]
Permalink

BlogPeople 等のリンクリストによる表示の遅延を解消する(その2:Ajax編)」で「Safari で文字化けします」というご質問を頂き、不具合を修正致しました。

1.問題点

調べたところ、(今更ですが)Safari2.0 では UTF-8 でも Ajax の responseText で文字化けすることを知りました。

WEBプログラミング NOW!:Googleサジェスト--Safariで文字化け

XMLHTTPを使った簡単なプログラムでもSafariは日本語が文字化けします。正しくresponseTextを取得できないようです。本来UTF-8で返されているデータなのに、ISO-8859-1として取得しています。そのために文字化けが発生しています。

この問題は日本語が含まれていなければ顕在化しませんが、BlogPeople のリンクリストは当然日本語だらけなので、Safari で閲覧されている場合はリンクリストが文字化けして表示されます。
UTF-8で表示しているブログ等で、ブラウザの文字コードを「ISO-8859-1」にすれば同じ事象を体験できます。

2.対処

下記のサイトで対処方法が掲載されています。

Kawa.netブログ(川崎有亮)Safari の responseText で UTF-8 コード文字化け回避

BlogPeople 等のリンクリストによる表示の遅延を解消する(その2:Ajax編)」については、紹介されているコードを JavaScript に挿入することで文字化けを回避しましたので、本カスタマイズをご利用の方は、配布 JavaScript(bp.js)を差し替えてお使いになることをお勧めします。

当サイトで紹介している、responseText に日本語を含む Ajax カスタマイズについても別途修正したいと思います。また当サイト自体も Ajax を多用しているので JavaScript の実装を見直します。

3.参考・関連サイト

Comments [2] | Trackbacks [1]
2007年3月 9日

複数ブログで Ajax 月送りカレンダーを利用する方法

March 9,2007 1:28 AM
Tag:[, , , ]
Permalink

Ajax 月送りカレンダー」を複数ブログで利用している場合の変更方法です。

2007.03.20 この方法は元記事に反映しました。

月送りカレンダーは表示月を cookie で保存することで、リロードや次回のブラウザ起動時に前回と同じ月を表示するようにしていますが、複数ブログで利用した場合、同じ cookie データ(=カレンダーの表示年月)にアクセスしてしまうため、一方のブログがもう一方のブログの表示年月を取得してしまう可能性があります。

仮に、ブログAに2007年3月(のエントリー)があり、ブログBにはその月のエントリーが存在しない場合、ブログBの表示でブログAの「2007年3月」という cookie データを取得した場合、ブログBではカレンダーが正常に表示されないという不具合が生じます。

ということで、とりあえずテーブル型カレンダーで複数ブログに対応するためのカスタマイズを紹介します。ここでは「Ajax 月送りカレンダー」との差分のみ説明します。

1.スクリプトのダウンロード・アップロード

下記のリンクより ajaxCalendar.js をダウンロードしてください。

ajaxCalendar.js

このファイルを編集する必要はありませんので、そのままメインページと同じディレクトリにアップロードしてください。

4.2 カレンダー表示部分の設定

カレンダーを表示させたい位置に下記を追加します。
これまでと異なり、パラメータに MTBlogURL と MTBlogID を渡しています。cookie は MTBlogID を付与して保存するようにしているので、他のブログの cookie を取得することはありません。

<div id="calendar"></div>
<script type="text/javascript">
getCalendar("<$MTBlogURL$>", "<$MTBlogID$>", "<$MTBlogURL$><MTEntries lastn="1" sort_order="descend"><$MTEntryDate format="calendar/%Y/%m/" $></MTEntries>");
</script>

アーカイブパス(3.2 以降であれば管理画面の「設定」→「公開」→「アーカイブの設定」)を設定している場合は、上記リストの赤色部分を修正します。
例えば archives というアーカイブパスを設定している場合は下記のようにします。

getCalendar("<$MTBlogURL$>archives/", "<$MTBlogID$>", "<$MTBlogURL$><MTEntries lastn="1" sort_order="descend"><$MTEntryDate format="archives/calendar/%Y/%m/" $></MTEntries>");

以上です。

2007.03.21 追記
元記事の「Ajax 月送りカレンダー」に本カスタマイズを反映させました。

Comments [0] | Trackbacks [0]
2007年2月26日

はてなブックマークの「人気エントリー/注目エントリー」を Ajax + Perl でブログに表示する

February 26,2007 1:38 AM
Tag:[, ]
Permalink

はてなブックマークの「人気エントリー」や「注目エントリー」を Ajax + Perl を利用して、スクリーンショットのように「記事タイトル+被ブックマーク数」のフォーマットでブログ等に表示させるカスタマイズです。

はてなブックマークの「人気エントリー/注目エントリー」をブログに表示する

他のサイトで同じようなリストを見かけたのですが、そのようなインタフェースあるいはツールを探し出せなかったので、自作しました(すでに同じものが提供されていたらお恥ずかしい限りですが)。

単に一覧を表示するのであれば、RSS + feed2JS でも可能ですが、被ブックマーク数まで表示することができないため、はてなブックマークで表示される HTML ファイルを Ajax + Perl で取得し、JavaScript で加工しています。
きめ細かいエラー処理等実装していないので、動作に不具合がございましたらご連絡ください。

なお、ここで紹介するカスタマイズは、アクセス毎に CGI が起動されます。サーバのパフォーマンスを考慮した、HTML ファイルを周期的に取得し、それを Ajax で取得する方法につきましては別エントリーで紹介する予定です(お分かりになる方はスクリプトを適宜修正してください)。

1.アーカイブのダウンロード

下記のいずれかのリンクからスクリプト一式をダウンロードしてください。

hatenabookmark.zip
hatenabookmark.lzh

ダウンロードしたアーカイブを解凍してください。中には下記のファイルが含まれています。

ajax-loader.gif(ローディング画像)
hatenabookmark.js(Ajax 起動スクリプト)
hatenabookmark.cgi(HTML 取得スクリプト)

上記の他、Ajax ライブラリの prototype.js が必要です。

Prototype JavaScript Framework

上記のサイトにある Download the latest version のリンクをクリックし、アーカイブをダウンロードします。アーカイブを解凍して、dist フォルダの中にある prototype.js を使用します(他は使いません)。
prototype.js はブログの任意のディレクトリにアップロードしてください。

2.HTML の修正

script 要素を、リストを表示させたい HTML(あるいはテンプレート)の </head> の直前に設定します。

<script type="text/javascript" src="http://user-domain/prototype.js"></script>
<script type="text/javascript" src="http://user-domain/hatenabookmark.js"></script>

赤色の user-domain は、それぞれのファイルをアップロードした URL を設定してください。

次に、リストを表示したい位置に下記のタグを設定してください。

<div id="hatena"></div>
<script type="text/javascript">
//<![CDATA[
getHatenaBookmark('[人気エントリー/注目エントリーのURL]', '[表示数]', 'hatena');
//]]>
</script>

[人気エントリーまたは注目エントリーのURL] は、下記の手順で取得・設定してください。

  1. はてなブックマークのトップページへジャンプ
  2. 右上にあるテキストエリアに表示したいサイト(のトップページ)のURLを入力し、ラジオボタンで「URL」を選択して「検索」をクリック
  3. 次ページでブラウザに表示された URL をコピー
  4. コピーした URL を上記の [人気エントリー/注目エントリーのURL] に設定

エントリーリストからトップページを外したい場合は、検索する時にアーカイブページのURLまで指定すればうまく取得できます。Movable Type を利用している当サイトの場合、

http://www.koikikukan.com/archives/

としています(Movable Type であれば一律可能という訳ではなく、管理画面でアーカイブパスを設定していればこのような取得が可能です)。

[表示数] は表示したい記事数です。HTMLから取得するので最大50件です。

3.Perl スクリプトのアップロード

hatenabookmark.cgi をサーバの任意のディレクトリにアップロードしてください。アップロード後、ファイルのパーミッションを 755 等に変更してください(値はご利用のサーバによって異なりますのでご確認ください)。

4.JavaScript 外部ファイルの修正

hatenabookmark.js を任意のエディタで開き、下記の user-domain を、先程アップロードした hatenabookmark.cgi の URL になるよう、修正してください。

// CGI の URL
var cgiURL = 'http://user-domain/hatenabookmark.cgi';

以下はオプションです(変更は動作確認後の方が良いでしょう)。

// リストに用いるタグ
var htnHeader = '<dl>';
var htnTitle = '<dt>最近の人気エントリー<\/dt>';
var htnListHeader = '<dd>';
var htnListFooter = '<\/dd>';
var htnFooter = '<\/dl>';
  
// ブックマーク数を括る span タグに付与する class 属性値
var htnListClassName = 'hatenaCount';
 
// 記事タイトルから削除したい文字列
var deleteChar = '';
 
// ローディング画像
var htnImage = 'ajax-loader.gif';

生成するリストのデフォルトマークアップは下記のようになっています。上記の「リストに用いるタグ」を変更する際の参考にしてください。

<dl>
<dt>[htnTitle]の内容</dt>
<dd><a href="...">記事タイトル1</a><a href="..."><span class="[htnListClassName]の内容">ブックマーク数1</span></a></dd>
<dd><a href="...">記事タイトル2</a><a href="..."><span class="[htnListClassName]の内容">ブックマーク数2</span></a></dd>
      :
<dd><a href="...">記事タイトル3</a><a href="..."><span class="[htnListClassName]の内容">ブックマーク数3</span></a></dd>
</dl>

[記事タイトルから削除したい文字列] は、サイト名等を記事タイトルから削除したい場合に用います。

hatenabookmark.js の修正が終わったら、サーバにアップロードしてください。

5.ローディング画像のアップロード

ajax-loader.gifhatenabookmark.js と同じディレクトリにアップロードしてください。異なるディレクトリにアップロードした場合は、hatenabookmark.js の、

// ローディング画像
var htnImage = 'ajax-loader.gif';

の赤色部分に ajax-loader.gif を含む URL を入力してください。

6.CSS 追加

下記のようなスタイルを追加すれば、被ブックマーク数部分がいい感じになります。

.hatenaCount a:link,
.hatenaCount a:visited {
    font-size: 10px;
    font-weight: bold;
    color: #ff0000;
    background-color: #ffcccc;
}

公式サイトでは被ブックマーク数によって与えるタグを振り分けてますが、このカスタマイズでは今のところそこまで凝っていません。

6.その他

以下覚え書きです。

Ajax で取得した HTML ファイルは一旦ページに読み込まれ、Opera9 で表示すると HTML ページが一瞬表示されてしまう場合があります。気になる場合はローディング画像の代わりに、display プロパティで加工が終わるまで非表示にした方がいいかもしれません。

また、読み込まれた HTML は img 要素の src 属性をもとに画像ファイルを取得を試みます。この HTML の src 属性はドキュメントルートで記述されているため、Firebug の Net で確認すると取得エラーが表示されてしまいます。
そのため Perl での取得後、故意に他の属性名に変更しています。

2006.02.26 追記
文中およびリストのファイル名に誤りがありましたので修正しました。

Comments [0] | Trackbacks [0]
2006年11月23日

BlogPeople 等のリンクリストによる表示の遅延を解消する(その2:Ajax編)

November 23,2006 3:33 AM
Tag:[, , ]
Permalink

BlogPeopleドリコム RSS がサービスとして提供しているリンクリスト。ご自身のページに直接HTMLでリンク集を作成するより、表示件数のカスタマイズやサイトの更新状況がわかる等、大変便利なサービスなので利用されている方はかなり多いと思います。

しかしながら、リンクリストはサーバに一旦アクセスしてから表示される仕組みになっているため、少なからずタイムラグが発生します。
このタイムラグはHTMLページの表示に大きく影響します。その理由は次の通りです。

例えばIEでサイトを閲覧する場合、そのサイトのページはHTMLソースの先頭から記述された順番に表示されるようになっています *1。つまり、ページの最初や途中にこのリンクリストを表示するタグが記述されている場合、サーバの応答が返ってくるまでそれ以降のHTMLソースの内容が表示されないという問題があります。
サーバからの応答がある場合はまだ良いのですが、サーバダウン等といった不測の事態が発生すると、それ以降のページがしばらく表示されなくなる可能性もあり、閲覧者にとってはかなりのストレスになります。

したがって、リンクリストを表示する位置についてはページの(少なくとも本文より)後方やリンクリスト専用のページに配置したり、あるいは「中継君関連記事)」を利用されているのではないでしょうか。

このエントリーは、その解消策として、以前公開した「BlogPeople 等のリンクリストによる表示の遅延を解消する(その1:JavaScript編)」の第2弾で、Ajax と CGI の組み合わせでリンクリスト表示のタイムラグを解消する方法です(下記のスクリーンショットは表示イメージ)。

BlogPeople リンクリストの Ajax 化

仕組みは、リンクリストの表示用タグ(リスト 3.1)はお好きな位置に埋め込み、そこから Ajax(bp.js) を起動し、さらに CGI(bp.cgi) を起動し、CGI 経由で BlogPeople のリンクリストを取得します。Ajax 起動なので、HTMLページ表示と BlogPeople のリンクリスト取得は並列に処理され、リンクリストが取得できた時点で HTMLに反映されます。

上記の基本的な動作に加え、ここでは下記の動作も加えた、少し凝った作りにしています。

  • リンクリストが表示されるまではローディング画像を表示(IE6では初回しか表示されないようです)
  • リンクリスト取得に失敗した場合は、ローディング画像を消去して、リスト表示位置に "Server Error" または非表示

下記にサンプルを用意してますので、動作をご確認ください。なお Ajax の特徴を分かりやすくするよう、リンクリスト表示までに1秒かかるよう、スクリプトを改変しています。Firefox で閲覧されると良く分かります。

BlogPeole の Ajax 化サンプル

このカスタマイズは設定がやや複雑ですので、自信がない方は前述した下記の方法をお勧めします。

BlogPeople 等のリンクリストによる表示の遅延を解消する(その1:JavaScript編)

それでは以下、設定方法です。CGI および外部ファイルが扱えるブログやホームページであれば利用可能と思われます。また特定のブログに依存する記述ではありませんので、予めご了承ください。

1.スクリプトのダウンロード

下記のファイルをダウンロードしてください(右クリックして「対象を保存」を選択してください)。

bp.zip(または bp.lzh)は解凍した中にある bp.cgi を使用します。

また、上記の他、Ajax ライブラリの prototype.js をダウンロードしてください。

Prototype JavaScript Framework

上記のサイトの Download the latest version のリンクをクリックし、アーカイブをダウンロード。アーカイブを解凍して、dist フォルダの中にある prototype.js を使用します(他は使いません)。

また、ajax-loader.gif はお好きな画像に変更して構いません。配布しているローディング画像は下記のサイトで作成したものです。

Ajaxload

2.bp.js の修正

ダウンロードした bp.js を任意のエディタで開き、1行目・2行目(リスト 2.1)を修正します。

var script = 'bp.cgi';
var image = 'ajax-loader.gif';
リスト 2.1 bp.js 変更箇所

bp.cgi の部分は URL 記述に変更してください。当サイトを例にすると、メインページと同じディレクトリに bp.cgi をアップロードしたのであれば、

var script = 'http://www.koikikukan.com/bp.cgi';
リスト 2.2 bp.js 変更例

という風に書き換えます。

ajax-loader.gif の部分も同じ要領で変更しますが、bp.js と異なるパスにアップロードする場合のみ、URL 記述に変更してください。bp.js と同じディレクトリであればこのままで問題ありません。

3.スクリプトのアップロード

1項でダウンロードしたファイルをサーバにアップロードします。bp.cgi はアップロード後、パーミッションを 755 または 777 に変更します(パーミッションの値はレンタルサーバによって異なる場合がありますので適宜確認してください)。

各ファイルのアップロードディレクトリは任意ですが、例えば Movable Type であれば、メインページと同じディレクトリが良いでしょう。CGI スクリプト(bp.cgi)はレンタルサーバによって実行可能ディレクトリの制限があるので、例えば cgi-bin ディレクトリ等になる場合があります。

4.リンクリスト表示用タグの追加

リスト 4.1 の内容を、リンクリストを表示したい位置へ設定します。

<div id="linklist"></div>
<script type="text/javascript">
getLinkList('[BlogPeopleリンクリストのURL]');
</script>
リスト 4.1 リンクリスト表示用タグ

[BlogPeopleリンクリストのURL] には、リンクリストのコード生成で出力された script 要素の src 属性の内容(リスト 4.2 の青色部分)を設定します。

<script language="javascript" type="text/javascript" src="http://www.blogpeople.net/display/usr/xxxxxxxxxxxxx.js"></script>
リスト 4.2 BlogPeopleリンクリスト表示コード

5.スクリプトのインクルード

リスト 5.1 の script 要素を、リスト 4.1 を設定したテンプレート(またはHTML)の <head>~</head> 部分に設定します。

<script type="text/javascript" src="http://domain/path/prototype.js"></script>
<script type="text/javascript" src="http://domain/path/bp.js"></script>
リスト 5.1 script 要素

赤色の src 属性値は環境に合わせて適宜変更してください。

6.スタイルシート設定

リスト 6.1 をスタイルシートに追加します。

#linklist {
    margin: 5px 1px 15px;
    background: none;
    color: #444444;
    font-size: 10px;
    _font-size: 9px;
    line-height: 150%;
}
.bp_loading {
    border: 1px solid #999999;
    padding: 83px 0;
    text-align: center;
}
.bp_loaded {
}
.blogpeople-main {
    height:162px;
    overflow: auto;
}
.blogpeople-powered-by {
    text-align: left;
}
.bp_error {
    padding: 83px 0 84px;
    text-align: center;
}
リスト 6.1 CSS

以下、CSS の各セレクタの説明です。

#linklist はリンクリスト全体のスタイルを設定しています。

.bp_loading はローディング画像を表示中のスタイルです。padding プロパティは、ローディング画像表示中の高さと、実際にリンクリストが表示されたときの高さを一致させるためのものです。ローディング画像のサイズによって高さが微妙に変わりますので、気になる場合は padding の値を適宜変更してください(Firefox で閲覧して高さが一致するようにしています)。

.bp_loaded はリンクリストが表示された時のリンクリスト全体のスタイルです。お好みに応じてプロパティを追加してください。

.blogpeople-main と .blogpeople-powered-by は「BlogPeople のリンクリストにスクロールバーをつける」のCSSと重複しています。すでにリンクリストのスクロール設定をされている場合はご注意ください。

.bp_error はリンクリスト取得失敗時のスタイルです。

7.リンクリストが表示されない場合

このカスタマイズのキモは「リンクリストが取得できるかどうか」ですが、それを確認するために、bp.cgi の下記の部分を変更して、bp.cgi をブラウザから直接実行してみると良いでしょう。

my $url = $query->param('url');
      ↓
my $url = '[BlogPeopleリンクリストのURL]';
リスト 7.1 bp.cgi 変更箇所

[BlogPeopleリンクリストのURL]は3項と同じものです。成功すればブラウザ上にリンクリストが表示されます。

上記でリンクリストが表示された後、bp.cgi の内容を元に戻します。それで表示できない場合は、

  • bp.js および prototype.js のパス誤り
  • bp.js に記述した bp.cgi のパスが誤り

等が考えられます。


*1:全てのブラウザが同じ動作であるかについては未確認です。実際、Firefox/Opera ではストレスなく表示されます。

Comments [6] | Trackbacks [2]
2006年10月11日

Ajax 月送りカレンダー(横型)

October 11,2006 12:11 AM
Tag:[, , , ]
Permalink

Ajax 月送りカレンダー」の横型版のカスタマイズを紹介します。

このカレンダーは、従来の月送りカレンダー(横型・iframe 利用)と比較して、下記のアドバンテージがあります。

  • クロスブラウザで悩まない
  • 月送りのリンクの履歴がブラウザの履歴に残らない

「クロスブラウザで悩まない」というのは、これまでの月送り版・横型カレンダーは、iframe の中に表示するカレンダーの垂直位置が IE系と Mozilla 系で微妙に異なったため、CSSハック等で表示位置の微調整を行っていました。今回の Ajax 版では iframe が不要なため、この問題で悩む必要が(多分)なくなります。

以下に簡単なサンプルを作りましたので動作をお試しください。

Ajax 月送りカレンダー(横型)サンプル

仕様

ここで紹介する月送りカレンダー(横型)の主な仕様です。

  • Ajax を利用して横型カレンダーを月送りにします。Ajax 化されるのはページ表示時および月送り時のカレンダー取得です
  • クッキーを利用して月送り状態を保持します
  • カレンダーの取得に失敗した場合、カレンダー表示エリアには何もされません(カスタマイズ可能)

以下、カスタマイズ方法です。テンプレートの指定はありませんので、CSS を変更すればどのテンプレートでもお使いになれます。

1.スクリプトのダウンロード・アップロード

下記のスクリプトをダウンロードします。

ダウンロードした ajaxCalendar.jsdayChecker.js はメインページと同じディレクトリにアップロードしてください。
また、prototype.js はダウンロードしたアーカイブを解凍して、dist フォルダの中にある prototype.js をメインページと同じディレクトリにアップロードしてください。

注:ここで配布している ajaxCalendar.js は横型カレンダー専用です。テーブルタイプのカレンダーで配布している ajaxCalendar.js はお使いになれません。

2.カレンダーテンプレート作成

注:ブログの文字コードが UTF-8 以外で運用されている場合は、2.1項のカスタマイズも併せて行ってください。

バージョンが 3.2-ja 以降の場合、管理メニューの「テンプレート」→「アーカイブ」→「テンプレートを新規作成」をクリック。3.1x-ja 以前の場合、管理メニューより「テンプレート」→「アーカイブに関連したテンプレート」で「新しいアーカイブテンプレートを作る」をクリック。
次画面で下記を設定してください。

  • テンプレート名:カレンダー(名称は何でもOKです)
  • このテンプレートにリンクするファイル:(設定不要)
  • テンプレートの内容:下記
<div title="<$MTArchiveDate format="%Y/%m"$>">
<span class="calendarHead">
<MTArchivePrevious>
<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogURL$><MTArchiveDate format="calendar/%Y/%m/%i">');">&#65308;</a>
</MTArchivePrevious>
<$MTArchiveDate format="%B %Y" language="en"$>
<MTArchiveNext>
<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogURL$><MTArchiveDate format="calendar/%Y/%m/%i">');">&#65310;</a>
</MTArchiveNext> |
</span>
<MTCalendar month="this">
<MTCalendarIfEntries><span><MTEntries lastn="1"><a href="<$MTEntryLink archive_type="Daily"$>" target="_top"><$MTCalendarDay$></a></MTEntries></MTCalendarIfEntries><MTCalendarIfNoEntries><span><$MTCalendarDay$></MTCalendarIfNoEntries><MTCalendarIfBlank><MTElse></span></MTElse></MTCalendarIfBlank>
</MTCalendar>
</div> 

設定が終わったら「保存」をクリックしてください。

なお、アーカイブパス(3.2 以降であれば管理画面の「設定」→「公開」→「アーカイブの設定」)を設定している場合は、上記リストで2ヶ所出現する

<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogURL$><MTArchiveDate format="calendar/%Y/%m/index.html">');"><</a>

の赤色部分を変更します。
例えば「archives」というパスを付与している場合は、

<a href="javascript:void(0);" onclick="changeMonth('<$MTBlogURL$><MTArchiveDate format="archives/calendar/%Y/%m/index.html">');"><</a>

とします。

2.1 ブログの文字コードがUTF-8以外の場合

Ajax(XMLHttpRequest)は UTF-8 で動作することを前提としています。他の文字コードでブログを運用している場合、本カスタマイズが正常に動作しない可能性があります。*1

ここではひとつの解決方法として Ogawa::memoranda さんの MT-I18N プラグインを利用する方法を紹介します。つまりブログの文字コードが UTF-8 以外の場合、プラグインを利用してカレンダーアーカイブの文字コードだけ UTF-8 で出力するという作戦です。

まず、MT-I18N Plugin.ja JP をダウンロードして、プラグイン mt-i18n.plplugins フォルダにアップロードします。

そして、2項で示したカレンダーテンプレート全体を下記の青色のタグで括ってください。

<MTEncodeText to="utf8">
      :
 (カレンダーテンプレート)
      :
</MTEncodeText>

本プラグインを利用し、EUC-JP、Shith_JIS で作成した Movable Type のサイトで、カレンダー動作と日本語表示の正常性は確認済です。ただし、.htaccess 等で文字コードを強制的に指定している場合は未確認です。

3.カレンダーテンプレートを月別アーカイブに関連付け

バージョンが 3.2-ja 以降の場合、管理メニューの「設定」→「公開」の「アーカイブ・マッピング」の項目の右側にある「マッピングを新規作成」をクリックして下記の設定を実施してください(バージョン 3.3 以降の場合、右上にある「詳細モードに切り替え」のリンクをクリックすることで「公開」というメニューが表示されます)。

バージョンが3.1x-ja 以前の場合は、管理メニューより「ウェブログの設定」→「アーカイブの設定」で「新しく、テンプレートとアーカイブを関連付ける」より下記の設定を実施してください。

  • アーカイブの種類:月別
  • テンプレート:カレンダー(←2項で設定した「テンプレート名」です)

「追加」をクリック後、その下の「アーカイブ」欄にある「月別」に、2項で付与した「テンプレート名(ここでは"カレンダー")」が追加されていればOKです。
次に同じ「アーカイブ」欄の「月別」の「カレンダー」の右側にある「出力フォーマット(3.2-ja 以降)」または「アーカイブ・ファイルのテンプレート(3.1x 以前)」に下記を設定してください。

出力フォーマット(3.2-ja 以降)

calendar/%y/%m/%i

アーカイブ・ファイルのテンプレート(3.1x-ja 以前)

<$MTArchiveDate format="calendar/%Y/%m/index.html"$>

これがカレンダー用のディレクトリおよびファイル名となります。
設定後、ページ下にある「変更を保存」をクリックしてください。

またカレンダーを初めてご利用になる場合は、「アーカイブ種類」欄の「日別アーカイブ」をチェックして保存してください。このチェックがされていないと、再構築で下記のようなエラーが発生します。

日付アーカイブ「Monthlyxxxx」の再構築に失敗しました: テンプレート「カレンダー」の再構築に失敗しました: <MTCalendar>タグでエラーが発生しました: <MTCalendarIfEntries>タグでエラーが発生しました: <MTEntryLink>タグでエラーが発生しました:<$MTEntryLink$>タグを使って、Dailyアーカイブにリンクしようとしましたが、そのアーカイブ・タイプは公開されていません。

4.テンプレート修正

カレンダーを表示させたいテンプレートに下記の設定を行います。

4.1 外部ファイルのインクルード

<head>~</head> の間に下記を追加します。

<script type="text/javascript" src="<$MTBlogURL$>prototype.js"></script>
<script type="text/javascript" src="<$MTBlogURL$>ajaxCalendar.js"></script>
<script type="text/javascript" src="<$MTBlogURL$>dayChecker.js"></script>

4.2 カレンダー表示部分の設定

カレンダーを利用したいテンプレート(メインページ/カテゴリー・アーカイブ/日別アーカイブ/エントリーアーカイブ等)のバナータイトルの下に、下記のカレンダー表示用のタグ(青色部分)を追加してください。
リストは公開テンプレートの場合を例にしています。

<div id="banner">
<h1 id="banner-header"><a href="<$MTBlogURL$>" accesskey="1"><$MTBlogName encode_html="1"$></a></h1>
<div id="banner-description"><$MTBlogDescription$></div>
</div>
 
<div id="calendar"></div>
<script type="text/javascript">
getCalendar("<$MTBlogArchiveURL$>", "<$MTBlogID$>", "<$MTBlogURL$><MTEntries lastn="1" sort_order="descend"><$MTEntryDate format="calendar/%Y/%m/" $></MTEntries>");
</script>

div は空要素ですが、Ajax によってこの部分にカレンダーが表示されます。

また、2項と同様、アーカイブパス(3.2 以降であれば管理画面の「設定」→「公開」→「アーカイブの設定」)を設定している場合は、上記リストの赤色部分を修正します。
例えば archives というアーカイブパスを設定している場合は、下記の青色のように修正てください。

getCalendar("<$MTBlogArchiveURL$>", "<$MTBlogID$>", "<$MTBlogURL$><MTEntries lastn="1" sort_order="descend"><$MTEntryDate format="archives/calendar/%Y/%m/" $></MTEntries>");

5.CSS修正

下記をスタイルシートに追加します。すでにカレンダー関係のスタイル設定が行われている場合は競合を避けるため、古い設定を削除(またはコメントアウト)してください。

#calendar {
    text-align: center;
    padding: 5px 0;
    border-bottom : 1px solid #666699;
    font-family: Verdana, Arial, sans-serif; 
    font-size: 10px; 
    color:#444444; 
}
#calendar a,
#calendar a:link,
#calendar a:visited {
    color: #006699;
}
#calendar a:hover {
    text-decoration: underline;
}
#calendar a:active {
    color: #006699;
}
#calendar .calendarHead { 
    color:#444444; 
    padding-right: 5px;
} 
#calendar .today { 
    border : 1px solid #444444; 
    padding: 0 2px;
} 
#calendar .holiday,
#calendar .holiday a:link,
#calendar .holiday a:visited {
    color: #e50003;
}
#calendar .saturday,
#calendar .saturday a:link,
#calendar .saturday a:visited {
    color: #0000ff;
}
#calendar .tholiday {
    border: 1px solid #444444;
    padding: 0 2px;
    color: #e50003;
}
#calendar .tholiday a:link,
#calendar .tholiday a:visited {
    color: #e50003;
}
#calendar .tsaturday {
    border: 1px solid #444444;
    padding: 0 2px;
    color: #0000ff;
}
#calendar .tsaturday a:link,
#calendar .tsaturday a:visited {
    color: #0000ff;
}

6.ページ表示時にローディング状態を表示する場合

インチキっぽいですが、4.2項で設定した

<div id="calendar"></div>

に、例えば青色の

<div id="calendar">loading ...</div>

を追加することで、ページ描画でカレンダーが表示されるまでローディング状態を示すことができます。img タグを設定すれば画像を表示することも可能です。

月送り時は挿入した文字は表示されません。またカレンダー取得失敗の場合は表示が消えます(これは7項の設定と関連します)。

7.カレンダー取得失敗時にメッセージ等を表示する

Ajax 月送りカレンダーは HTTP 非同期通信でカレンダーファイルを取得・表示しますが、何らかの原因で通信に失敗し、正常に取得できない可能性があります。当サイトで運用していた時も 503 エラーが多発すると取得に失敗するようです。

このカスタマイズではカレンダーの取得に失敗した場合、カレンダー表示エリアに正常に取得できなかったメッセージ

File Not Found

を表示するようにしています。このメッセージは ajaxCalendar.js の下記の青色部分が対応します。

function errorProcess() {
    $('calendar').innerHTML = 'File Not Found';
}

メッセージを変更したい場合はこの青色部分を修正してください。またこの1行を丸ごと削除すれば、HTTP 非同期通信に失敗した場合にカレンダー表示エリアの書き換えが行われなくなりますが、6項の表示がそのまま残りますのでご注意ください。

「失敗してもカレンダーを表示させたい」という場合は、上記メッセージ出力の1行を削除して、6項の「loading ...」というメッセージの代わりに、カレンダータグ(通常のカレンダータグ)を埋め込んでおくという手もあります。通信が成功すれば Ajax 月送りカレンダーに切り替わり、失敗すれば通常のカレンダーがそのまま表示されます。

8.トラブルシューティング

カレンダーが正常に表示されない場合、つまり上記のカスタマイズをそのまま行って、カレンダーが表示される位置に "File Not Found" が表示された場合、以下の問題が考えられます(全てではありませんが思いついたものを挙げておきます)。

  • カレンダーアーカイブの再構築ができていない
  • カレンダーアーカイブページへのパス設定が誤っている
  • ajaxCalendar.js の修正誤り
  • テンプレートに設定したカレンダーアーカイブページの拡張子が不一致
  • カレンダーアーカイブが UTF-8 で出力されていない

ご質問の前に確認していただきたいのは、

  1. ブラウザの[表示]-[ソース](あるいは「ソースの表示」)で、カレンダーを設定しているページのソースを表示
  2. 表示されたソースから下記のタグをみつけ、そこに記述されている URL(赤色)をブラウザに設定して実行
<div id="calendar"></div>
<script type="text/javascript">
getCalendar("http://user-domain/calendar/yyyy/mm/");
</script>

何も表示されない場合(404 Not Found)はカレンダーアーカイブへのパスの設定が誤っているか、アーカイブが生成されていない可能性があります。

逆に、カレンダーが表示されてブラウザにそのカレンダーが表示されない場合は、ブラウザの再起動や、ブラウザのキャッシュ・一時ファイルの削除等を行ってみてください。また UTF-8 以外で運用されている方は、カレンダーが表示されている状態で、ブラウザの[表示]-[エンコード]でカレンダーのページの文字コードが UTF-8 になっていることを確認してください。

クッキーを削除した直後のカレンダーは表示されるけれども、月送りのリンクをクリックすると File Not Found が表示されるという場合は、2項のテンプレートに埋め込んでいるカレンダーアーカイブへのパスが誤っている可能性があります。

9.その他

当サイトで運用している月送りカレンダーの Ajax ライブラリは、prototype.js ではなく、「入門 Ajax」のサポートページで紹介されている jslb_ajax.js を使っていますが、紹介するカスタマイズでは知名度の高い protptype.js を用いています。

2007.03.21 追記
Cookie に保持された場合にカレンダーが表示されなくなる不具合および、複数ブログで利用可能になるよう、ajaxCalendar.js および4.2項のMTタグを修正しました。


*1:文字コードの設定を行わずに Movable Type をインストールした場合の文字コードは UTF-8 です。

Comments [25] | Trackbacks [4]
2006年10月10日