jQuery の $(document).ready(fn) と IE

IE 6 と jQuery 1.1.4 ですが,$(document).ready(fn) イベントが,ページを表示するたびに実行されるような気がします。

単純に,

$(document).ready(function () {
    alert('hoge');
});

みたいなコードを読み込む html 1 があったとして,そこからリンク等で html 2 に遷移させます。

で,html 2 からブラウザの「戻る」ボタン等で html 1 に戻ると,再度 alert が表示されます。

Firefox / Opera / Safari では,html 1 に戻っても ready イベントは再度実行はされません(すでに ready イベントが発生した後の DOM ツリーになっていますので問題はありません)。

jQuery 自体を JavaScript で遅延ロードさせているからかなぁ。もうちょっと検証してみます。

追記

遅延ロードは関係なかったです。

以降 Cache-Control については無視します。

検証用コード。

<html>
    <head>
        <title>HTML 1</title>
        <script type="text/javascript" src="jquery.js"></script>
        <script type="text/javascript">
$(function () {
    alert('ready');

    if ($('#hidden1').val() != 'loaded') {
        $('#hidden1').val('loaded');

        $('#btn1').click( function () { alert('clicked'); } );

        alert('loaded for the first time');
    }
});
        </script>
    </head>
    <body>
        <h1>HTML 1</h1>
        <p>
            <a href="html2.html">to HTML 2</a>
        </p>
        <p>
            <input type="button" id="btn1" value="押す" />
            <input type="hidden" name="dummy" id="hidden1" value="" />
        </p>
    </body>
</html>

html2.html は適宜用意するとして。

Firefox / Opera / Safari の場合,

  1. HTML 1 を開く
  2. 「ready」と alert が出る
  3. 「loaded for the first time」と alert が出る
  4. 「押す」ボタンを押すと「clicked」と alert が出る
  5. HTML 2 へのリンクをクリックする
  6. 「戻る」ボタンで戻る
  7. 「押す」ボタンを押すと「clicked」と alert が出る

IE 6 の場合,

  1. HTML 1 を開く
  2. 「ready」と alert が出る
  3. 「loaded for the first time」と alert が出る
  4. 「押す」ボタンを押すと「clicked」と alert が出る
  5. HTML 2 へのリンクをクリックする
  6. 「戻る」ボタンで戻る
  7. 「ready」と alert が出る
  8. 「押す」ボタンを押しても「clicked」と alert が出ない

どういうことかというと,IE 以外のモダンブラウザの場合,ブラウザの「戻る」等で遷移した場合,JavaScript でいじられた DOM ツリー・イベントリスナ系はそのままに戻ります。ready イベントは発生しません。

IE の場合,ブラウザの「戻る」等で遷移した場合,サーバから html をロードした時点まで巻戻り(DOM ツリー・イベントリスナも初期状態になります),再度 JavaScript を実行します。

IE のときは裏技的に?<input>タグの値を設定しておくことで挙動を変えることができますが*1,そのかわりイベントリスナ等もリセットされているのでボタンを押してもメッセージが出ません。また DOM ツリーもリセットされるので,DOM ツリーをいじって既ロードかどうかを判定させることはできません。


JavaScript 詳しくないんで間違いとか多々あるかもしれません。

*1:type = hidden じゃなくて text にするとわかりやすいかも