はじめに
Firefox 1.5 ではウェブページ全体をその JavaScript の状態も含めてメモリ内にキャッシュし、1 つのブラウザセッションとして使用します。訪問したページ間の戻る、進むという動作にページのロードが不要になり、JavaScript の状態も保存されます。この機能によってページナビゲーションが非常に高速化します。この機能は bfcache("Back-Forward Cache" のこと)と呼ばれることもあります。このキャッシュ状態はユーザがブラウザを閉じるまで保存されます。
Firefox がページをキャッシュしない場合があります。ページがキャッシュされないプログラム的な理由でよくあるものをいくつか以下に示します。
- ページが
unload
ハンドラを使用している - ページが "cache-control: no-store" をセットしている
- ページが "cache-control: no-cache" をセットしていて、サイトが HTTPS である
- ページが完全にはロードされないまま、ユーザがそのページから去るナビゲートをする
- トップレベルのページにキャッシュ不可能なフレームがある
- ページがフレーム内にあり、ユーザがそのフレーム内に新しいページをロードする(この場合、ユーザがそのページから去るナビゲートをするとそのフレームに最後にロードされたコンテンツがキャッシュされる)
この新しいキャッシュ機能により、ページロードの挙動が変わります。ウェブ作者は次のことをしたいと思うことがあるでしょう。
- ナビゲートされたことがあるページであることを知ること(そのページがユーザのキャッシュからロードされるとき)
- ユーザがそのページを去るときのページの挙動を定義すること(ページがキャッシュされるようになっている間)
ブラウザの 2 つの新しいイベントによってウェブ作者はそのどちらもできるようになります。
ブラウザの新しいイベント
これらの新しいイベントを使用すると、そのページは他のブラウザでは今までどおりにきちんと表示され(過去の Firefox、Internet Explorer、Opera、Safari でテスト済み)、Firefox 1.5 でロードしたときにこの新しいキャッシュ機能が使用されるようになります。
ウェブページの標準的な挙動は次のとおりです。
- ユーザがページにナビゲートする。
- ページロード時にインラインスクリプトが実行される。
- ページがロードされると
onload
ハンドラが実行される。
4 ステップ目があるページもあります。ページが unload
ハンドラを使用していると、ユーザがそのページから去るナビゲートをするときにそれが実行されます。unload
ハンドラが存在しているとそのページはキャッシュされません。
ユーザがキャッシュされたページにナビゲートしたとき、インラインスクリプトと onload
ハンドラは実行されません(ステップ 2 および 3)。ほとんどの場合、これらのスクリプトの効果が保存されているためです。
そのページにユーザがナビゲートするたびにロード中に実行されるようにしたいスクリプトや他の動作がそのページに含まれている場合、あるいはいつユーザがキャッシュされたページにナビゲートしたかを知りたい場合は、新しい pageshow
イベントを使用します。
ユーザがそのページから去るナビゲートをするときに実行されるようにしたい動作があるものの、この新しいキャッシュ機能を生かしたく、さらにそれゆえに unload ハンドラを使用したくないという場合は、新しい pagehide
イベントを使用します。
pageshow イベント
このイベントは load
イベントと同じように動作しますが、ページがロードされるたびに実行される点で異なります(一方、Firefox 1.5 ではページがキャッシュからロードされたときには load
イベントは発動しません)。初めてページがロードされるとき、load
イベントの発動直後に pageshow
イベントが発動します。pageshow
イベントは 初回ロード時には false
がセットされる persisted
という真偽値プロパティを使用します。初回ロードでなければ true
がセットされます(つまり、そのページがキャッシュされているときに true がセットされます)。
ページロードのたびに実行したい JavaScript は pageshow
イベントの発動時に実行されるようにセットします。
この記事で後に示すサンプルのように、JavaScript の関数を pageshow
イベントの一部として呼び出す場合、pageshow
イベントを load
イベントの一部として呼び出すことで、ページが Firefox 1.5 以外のブラウザでロードされたときにもその関数を呼び出せるようになります。
pagehide イベント
ユーザがそのページから去るナビゲートをするときに実行する動作を定義したいものの、unload
イベント(そのページがキャッシュされなくなる)を使用したくないという場合は、新しい pagehide
イベントを使用することができます。pageshow
のように、pagehide
イベントは persisted
という真偽値プロパティを使用します。このプロパティは、ブラウザがそのページをキャッシュしていなければ false
がセットされ、ブラウザがそのページをキャッシュしていれば true
がセットされます。このプロパティに false
がセットされているとき、unload
があれば pagehide
イベントの直後にそれが発動します。
Firefox 1.5 は、そのページの初回ロード時と同じ順番でロードに関するイベントをシミュレートします。フレームはトップレベルの文書と同じように扱われます。そのページにフレームがあると、キャッシュされたページがロードされるときに次のことが起こります。
- メイン文書で
pageshow
イベントが発動する前に、各フレームからpageshow
イベントが発動する。 - ユーザがキャッシュされたページから去るナビゲートをすると、メイン文書で
pagehide
イベントが発動する前に、各フレームからpagehide
イベントが発動する。 - 単一のフレーム内でのナビゲーションについては、影響を受けるフレームでのみイベントが発動する。
サンプルコード
下のサンプルは load
イベントと pageshow
イベントの両方を使用したページです。このサンプルページは次のような挙動をとります。
- Firefox 1.5 以外のブラウザでは、次のことがページロードのたびに起こる:
load
イベントがonLoad
関数をトリガする。onLoad
関数はonPageShow
関数を呼び出す(付随する関数はもちろんのこと)。
- Firefox 1.5 では、初めてそのページがロードされるときに他のブラウザと同じように
load
イベントが発動する。さらにpageshow
イベントが発動し、persisted
にfalse
がセットされるために他のアクションは生じない。
- Firefox 1.5 では、キャッシュからページがロードされるときは
pageshow
イベントだけが発動する。persisted
にはtrue
がセットされるため、onPageShow
関数内の JavaScript アクションだけがトリガされる。
この例では次のことが起こります。
- ページはロードされるたびに現在日時を算出し、表示する。この計算には秒とミリ秒が含まれるため、機能のテストが簡単になる。
- ページの初回ロード時にカーソルがフォームの Name フィールドに移動する。Firefox 1.5 では、ユーザがそのページに戻るナビゲートをすると、カーソルはユーザがそのページから去るナビゲートをしたときにあったフィールドに残る。他のブラウザではカーソルは Name フィールドに戻る。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <HTML> <head> <title>Order query : Firefox 1.5 Example</title> <style type="text/css"> body, p { font-family: Verdana, sans-serif; font-size: 12px; } </style> <script type="text/javascript"> function onLoad() { loadOnlyFirst(); onPageShow(); } function onPageShow() { // 現在時刻の算出 var currentTime= new Date(); var year=currentTime.getFullYear(); var month=currentTime.getMonth()+1; var day=currentTime.getDate(); var hour=currentTime.getHours(); var min=currentTime.getMinutes(); var sec=currentTime.getSeconds(); var mil=currentTime.getMilliseconds(); var displayTime = (month + "/" + day + "/" + year + " " + hour + ":" + min + ":" + sec + ":" + mil); document.getElementById("timefield").value=displayTime; } function loadOnlyFirst() { document.zipForm.name.focus(); } </script> </head> <body onload="onLoad();" onpageshow="if (event.persisted) onPageShow();"> <h2>Order query</h2> <form name="zipForm" action="https://www.example.com/formresult.html" method="get"> <label for="timefield">Date and time:</label> <input type="text" id="timefield"><br> <label for="name">Name:</label> <input type="text" id="name"><br> <label for="address">Email address:</label> <input type="text" id="address"><br> <label for="order">Order number:</label> <input type="text" id="order"><br> <input type="submit" name="submit" value="Submit Query"> </form> </body> </html>
一方、上記のページが pageshow
イベントをリスンせず、すべての計算を load
イベントの一部として扱う(そして代わりに下のサンプルコード片で置き換える)ものだとすると、ユーザがそのページから去るナビゲーションをするとカーソル位置も日時も Firefox 1.5 にキャッシュされます。ユーザがそのページに戻ると、キャッシュされた日時が表示されます。
<script> function onLoad() { loadOnlyFirst(); // 現在時刻の算出 var currentTime= new Date(); var year = currentTime.getFullYear(); var month = currentTime.getMonth()+1; var day = currentTime.getDate(); var hour=currentTime.getHours(); var min=currentTime.getMinutes(); var sec=currentTime.getSeconds(); var mil=currentTime.getMilliseconds(); var displayTime = (month + "/" + day + "/" + year + " " + hour + ":" + min + ":" + sec + ":" + mil); document.getElementById("timefield").value=displayTime; } function loadOnlyFirst() { document.zipForm.name.focus(); } </script> </head> <body onload="onLoad();">
Firefox 用拡張機能の開発
Firefox 1.5 の 拡張機能 はこのキャッシュ機能を許容するものである必要があります。1.5 とそれより前のバージョンの両方と互換性を持つ Firefox の拡張機能を開発したいのであれば、キャッシュされるようにするトリガについては load
イベントをリスンし、キャッシュされないようにするトリガについては pageshow
イベントをリスンしてください。
例えば Firefox 用 Google ツールバーは、1.5 とそれより前のバージョンの両方と互換性を持たせるためには、autolink 関数については load
イベントをリスンすべきであり、PageRank 関数については pageshow
イベントをリスンすべきです。