2004年08月20日 (金)

もっと「前後のエントリ」を

なんだか .Mac ネタはどうしたという感じの OKAMURA です。
# 出だしがあっちになっているような気が...

他ならぬ t0moriさん希望に応えて「前後のエントリ」の機能強化用 JavaScript ファイルを作成したので公開します。

iblogPatcher(1.3以前でもよい) を前提としているので、なんと iBlog 1.3.8 より前のバージョンでも使えます。しかも以前公開したカスタム CommonLib.js(こっちは iblogPatcher を前提にしていない) によるカテゴリ内での前後のリンクより処理効率が数段アップしています。


この機能のデモは「僕は見ていた」のエントリページを見てください。エントリページはエントリのタイトルに付いているリンクを辿ると表示されます。

特徴

機能強化された「前後のエントリ」用 JavaScript ファイルを用いたときの長所と短所は次のとおりです。長短の比較は以前公開したカスタム CommonLib.jsによる「前後のエントリ」との比較です。
  • [長所] カテゴリに絞ったリンクに関する処理効率が大幅にアップしている。
    いわゆる処理のオーダーっていうのが線形になっています。恐らく細かい部分は除いてこれ以上はないでしょう。
    CommonLib.js のエンハンスとして実装したカテゴリに絞った前後のエントリの処理のオーダはエントリ数に関して三乗のオーダのアルゴリズムにならざるを得ませんが、ここで紹介するものは一乗のオーダになっています。つまりエントリ数が多くなっても急激に時間がかかるということはありません。
  • [長所] 前後のエントリへのリンクの title 属性にリンク先のエントリのタイトルが入っている。
    ブラウザによりますが、リンクの上にマウスポインタを載せるとタイトルがツールヒントと言うかポップアップと言うか、そういう機能で表示されます。事前に飛び先の内容を知らせることができます。
  • [長所] iBlog 1.3.8 より前の iBlog でも利用可能。
    ただし一部制限があります。1.3.8 より前の iBlog の場合は同じ日のエントリの順序が必ずしも正しくありません。一日に一エントリでしたら問題ありません。
  • [長所] iblogPatcher ユーザでない iBlog サイトに差を付けられる。(^_^)
  • [短所] iblogPatcher とそのプラグイン ENTRIES_JS.plugin が必要です。このプラグインが作成する entries.js を利用しています。
  • [短所] エントリページの表示時にブラウザがロードするバイト数が多くなります。
    entries.js をロードするからです。

設置手順

僕は見ていた」と同じように表示する場合を例にとって説明します。
  1. iblogPatcher を導入していないときは、ダウンロードして README.txt の記述に従ってインストール&設定する。
    ENTRIES_JS.plugin のための設定は後述します。
  2. AroundEntries.js をダウンロードして自サイトにアップロードする。
  3. iBlog の各種データをバックアップする。
  4. 必要な JavaScript ファイルをロードするタグを EntryPage.txt に入れる。
    head 要素内(<head> から </head> の間)に次のコードを挿入します。
    <script type="text/javascript" src="{AroundEntries.jsのURL}" charset="Shift_JIS"></script>
    <script type="text/javascript" src="<$BlogBaseURL$>entries.js"></script>
  5. 前後のエントリへのリンクを EntryPage.txt に入れる。
    前後のエントリへのリンクを入れたいところに次のコードを入れます。既にある場合は置き換えます。
    <script type="text/javascript">
    	NextEntryLinkString = '{前のエントリへのリンクの文字列}';
    	PrevEntryLinkString = '{次のエントリへのリンクの文字列}';
    	AroundEntries = GetAroundEntries('<$EntryUUID$>');
    </script>
    <table border="0" width="100%" align="center" summary="Entry Navigation">
    	<tbody>
    		<tr>
    			<td width="50%" align="right">
    				<script type="text/javascript">
    					WriteEntryLink4EntryPage(AroundEntries[3], NextEntryLinkString);
    				</script>
    				<br />
    			</td>
    			<td nowrap="nowrap" align="center">
    				< a href="../index.html" title="カテゴリーページ"><script type="text/javascript">getCategoryName("<$EntryCategoryUUID$>");</script></a>
    			</td>
    			<td width="50%" align="left">
    				<script type="text/javascript">
    					WriteEntryLink4EntryPage(AroundEntries[0], PrevEntryLinkString);
    				</script>
    				<br />
    			</td>
    		</tr>
    		<tr>
    			<td width="50%" align="right">
    				<script type="text/javascript">
    					WriteEntryLink4EntryPage(AroundEntries[2], NextEntryLinkString);
    				</script>
    				<br />
    			</td>
    			<td nowrap="nowrap" align="center">
    				< a href="<$BlogBaseURL$>index.html" title="トップページ"><script type="text/javascript">getBlogName();</script></a>
    			</td>
    			<td width="50%" align="left">
    				<script type="text/javascript">
    					WriteEntryLink4EntryPage(AroundEntries[1], PrevEntryLinkString);
    				</script>
    				<br />
    			</td>
    		</tr>
    	</tbody>
    </table>
    • iBlog が勝手に a タグによるリンクを作るのを防ぐ為に < と a との間にスペースを入れています。実際には取り除いてください。二カ所あります。
    • 各部の解説は後述します。
    • table でレイアウトしていますが、ご自分のページに合わせて適当にやってください。
  6. iBlog 1.3.8 以上の場合は FileSharingPage.txt にも EntryPage.txt と同じ変更をする。
  7. iBlog 1.3.9 以上の場合は MusicPage.txt にも EntryPage.txt と同じ変更をする。
  8. プレビュー状態をリセットしてプレビューする。
    複数のブログを運営していて一つのブログだけをリセットしたい場合は、ブログの表示設定で一旦別なテンプレートセットを選んだ上で、再度元のテンプレートセットを選んでください。次にプレビューするときに html ファイルが再生成されます。
  9. プレビューでエントリを辿って確認したら公開する。

コード解説

リンクの文字列の設定
上の 5 の次の箇所は前後のエントリへのリンクになる文字列を設定している部分です。
NextEntryLinkString = '{前のエントリへのリンクの文字列}';
PrevEntryLinkString = '{次のエントリへのリンクの文字列}';
{前のエントリへのリンクの文字列}{次のエントリへのリンクの文字列} はあなたのページ合わせた文言に置き換えてください。

Next が「前」で Prev が「次」と逆転しているのは iBlog における前後の概念を変数名に継承しているからです。これについては「iBlog 1.3.8 用カスタム CommonLib.js」で説明しています。XHTML 中に書く文字列なので & < " > はそれぞれ &amp; &lt; &quot; &gt; に置き換えて書いてください。

特定の文字列をリンクの文字列にするのではなく、リンク先のエントリのタイトルをリンクの文字列にしたい場合は、この二行は不要です。取り払ってください。

前後のエントリの EntryUUID の取得
カテゴリに絞った前後のエントリと絞らない前後のエントリの EntryUUID(エントリを一意に識別するシンボル) を取得しているのが次の箇所です。
AroundEntries = GetAroundEntries('<$EntryUUID$>');
この結果、AroundEntries には長さが 4 の配列が代入されます。各要素は次のようになっています。
配列の添字 0 1 2 3
要素の内容 同一カテゴリの
次のエントリの EntryUUID
次のエントリの EntryUUID 前のエントリの EntryUUID 同一カテゴリの
前のエントリの EntryUUID
  • 要素の順序と「前」「後」が逆のような感じがしますが、iBlog の前後の概念と同じです。プログラマー的にはこの方が自然なんです。使用するデータの並びの前後を表しています。
  • iBlog 1.3.8 以上の場合、iBlog が CommonLib.js に書き込む EntryUUID の順序における前後に一致します。
  • iBlog 1.3.8 未満の場合、ENTRIES_JS.plugin が entries.js に書き込む EntryUUID の順序における前後に一致します。これは同じ日のエントリ間の順序が正しいとは限りません。
エントリへのリンクの書き出し
取得した前後のエントリの EntryUUID を使ってリンクを書き出しているのが次の箇所です。最大四つの EntryUUID が取得されるので四カ所あります。
<script type="text/javascript">
	WriteEntryLink4EntryPage(AroundEntries[3], NextEntryLinkString);
</script>
<script type="text/javascript">
	WriteEntryLink4EntryPage(AroundEntries[0], NextEntryLinkString);
</script>
<script type="text/javascript">
	WriteEntryLink4EntryPage(AroundEntries[2], PrevEntryLinkString);
</script>
<script type="text/javascript">
	WriteEntryLink4EntryPage(AroundEntries[1], PrevEntryLinkString);
</script>
AroundEntries[n]n は上にテーブルを書いた AroundEntries の添字です。また NextEntryLinkStringPrevEntryLinkString は更に上で説明したリンクの文字列が代入されている変数です。

この NextEntryLinkStringPrevEntryLinkString を省略して次のような形式で書くとリンクの文字列にリンク先のエントリのタイトルが用いられるようになります。

<script type="text/javascript">
	WriteEntryLink4EntryPage(AroundEntries[n]);
</script>

ENTRIES_JS.plugin のための設定

ENTRIES_JS.plugin を有効にして iblogPatcher に entries.js を生成させるためには「ブログ定義ファイル」にそのための指定を入れる必要があります。エントリ一覧を既に利用している方はこのセクションは必要ありません。iblogPatcher-1.3 以上を導入している方は、サンプルのブログ定義ファイルをベースにしていると思います。サンプルのブログ定義ファイルでは既に以下に述べる設定が施されています。

ブログ定義ファイルの

%ACTION > 'preview' > 'after' > 'file'
の設定の中に次を入れてください。
# 全エントリをリストアップした entries.js のデータを収集する
ENTRIES_JS::File(@_);
挿入場所はコード変換用プラグイン CHANGE_ENCODE.plugin を使用している場合、CHANGE_ENCODE::File(@_); よりも後ろでなければなりません。

更にブログ定義ファイルの

%ACTION > 'preview' > 'after' > 'onFinish'
の設定の中に次を入れてください。
# 全エントリをリストアップした entries.js ファイルを作成する
ENTRIES_JS::OnFinish(@_);
を入れてください。挿入場所はコード変換用プラグイン CHANGE_ENCODE.plugin を使用している場合、CHANGE_ENCODE::OnFinish(@_); よりも前でなければなりません。

entries.js について

今まで ENTRIES_JS.plugin が生成する entries.js の応用例として、条件指定ができるエントリ一覧のみがありました。今回はその応用例の二つ目になります。このセクションでは JavaScript を使用できる方向けに entries.js の解説をします。

entries.js は次のようなデータが格納されていて JavaScript からそれを効率よく利用できるようになっています。
  • 順序付けられた EntryUUID
    これは EntryUUID という名前の JavaScript の配列として実装されています。EntryUUID[0] が最も新しい日付を持っているエントリの EntryUUID です。iBlog 1.3.8 以降は CommonLib.js に iBlog が格納した entryUUIDsList という名前の JavaScript の配列に相当します。
  • EntryUUID からエントリのサマリ情報への対応
    これは Entry という名前の JavaScript の配列として実装されています。この配列は EntryUUID を添字にとる「ハッシュ表」になっていて、entries.js の中で定義されたエントリのサマリ情報を表す iBlogEntry クラスのオブジェクトが要素になっています。つまり 'E012345678' という EntryUUID を添字にして Entry['E012345678'] とすると、その EntryUUID を持つエントリのサマリ情報 iBlogEntry クラスのオブジェクトが取得できます。
    この iBlogEntry オブジェクトは次の属性を持っています。
    属性
    m_CategoryUUID そのエントリの CategoryUUID
    m_Title そのエントリのタイトル
    m_Date そのエントリの日付
    YYYY/MM/DD という形式の文字列です。
    m_Time そのエントリへのリンクがある DayPage で 0 から数え始めて何番目に列挙されているかを表す数値です。
    ですから例えば 'E012345678' という EntryUUID を持ったエントリのタイトルは Entry['E012345678'].m_Title として取得できます。

今までこの entries.js は、サマリ情報とはいえエントリ数が多いと大きなファイルになってナローバンドユーザーにはつらいかもしれないと思い、利用を控えていました。しかし、例えば現在 176 個のエントリがある「僕は見ていた」では約 28 KB の大きさになっています。画像ファイルなどと比較すると思ったよりも大したことないような気がしてきましたが、ファイルのロードに加えてブラウザでの JavaScript の処理が入るので余丁町散人さんのように 1000 エントリを軽く超えるようなときはもしかするとちょっと辛いかもしれません。entries.js を使用する場所はよく吟味しておいた方がベターです。

今回公開した AroundEntries.js にはかなり詳しくコメントを入れてあります。JavaScript を書ける方、これから書けるようになりたい方は entries.js の利用例としてちょっと覗いてみてください。


Posted: 01:30    | Comment | Trackback


以下、類似エントリです。