読者です 読者をやめる 読者になる 読者になる

jQueryMobileで$(document).ready()が動かない現象と、その対処

最近はjQueryMobileをつかってhtml5/css3でウェブアプリを作っている。
jQuery Mobileは通常のhtmlをマークアップするだけで、それらしいモバイルサイトが作れる。
とても便利なのだが、前々から$(document).ready()がうまく動かないと感じていた。

以下はその調査と解決の記録である。

htmlを分割すると遷移先の画面で$(document).ready()が動かない

現象としてはhtmlが2つ以上ある場合に、遷移先のhtmlヘッダに記述された$(document).ready()が動作しない。

確実な原因はわからないのだが、デバッグしてみるとどうもjQueryMobileの仕様のようである。
ページ遷移をする際に、新しくhtmlを読み込むのではなく、既存のhtmlにdiv要素だけ挿入しているようなのである。
分かりにくのでスクリーンショットを貼った。

ページ遷移前

ページ遷移後

実際にjQueryMobileで表示されるコンテンツはの中の<div data-role="page">に記述されている内容である。
上の二つを見比べるとページ遷移後にの末尾に<div data-role="page">が挿入されていることがわかる。

の内容は再読込されないため、遷移先のhtmlにjavaScriptを記述しても実行されないのではないかと思われる。

画面遷移した際にJavaScriptを実行するには

実際にやりたいことは以下の二つになる。

  • 画面遷移をした際にJavaScriptを実行したい
  • 遷移先の画面によって処理を変更したい

一つ目はjQueryMobileの処理を使って解決できる。
詳しいことはここを見てもらいたいのだが、
要するに以下のコードをindex.htmlに記述しておいて、ページ遷移したイベントを拾えばよい。

$(function() {
    $("div[data-role*='page']").live('pageshow', function(event) {
        //do something on page shown
    });
});

二つ目はページにidを振ることで解決できそうだ。
たとえば以下のようにhtmlを記述していたとする

<html>
    <head>...</head>
    <body>
        <div data-role="page" id="hoge">...</div>
        <div data-role="page" id="fuga">...</div>
    </body>
</html>

上記のJavaScriptの中でidを拾って処理を振り分けてやれば良い。

$(function() {
    $("div[data-role*='page']").live('pageshow', function(event) {
        if (this.id == "hoge"){
            //do something when page is hoge
        } else if (this.id == "fuga") {
            //do something when page is fuga
        }
    });
});

参照したURLではもうちょっとスマートな方法も紹介されていたようだが、英語が読みきれずに理解出来ていない。
英語が得意な方は内容を読んで教えて下さいw

追記

こちらを参照したところ、アンカーリンクにrel="external"などをつけるとdivの挿入ではなく、単純なページ遷移になるようだ。
jquery.mobile-1.0a4.1でこれを指定してみたところ、確かに普通のページ遷移になった。
一方で通常は自動で生成されるBackボタンが作成されなかったので、こちらは自分で記述する必要があるようだ。