- 2008-09-18 (木)
- 技術
Safari3.1でDOM構築が終わったタイミングでイベントを登録していたのですが、うまくいかなかったときのお話です。
jQueryを使っていたので自動的にDOMContentLoadedイベントに登録されると思っているのですが、これがどうもDOM構築が終わっていないんじゃないかと。
それが判明したのが、画像をスライドするパーツを製作していたときにスライド対象のdivタグのwidthを取得していて、このwidthがなぜかSafari3.1だと小さく取得されました。
以下にその例を載せて起きます。
SafariのDOMContentLoadedで失敗したパターン
画像がたくさん並んだボックスを左や右へスライドさせるときに、何枚あるか分からなかったので画像が入っているボックスのwidthを取得して計算をしていました。
以下にサンプルのHTMLを載せています。
このページの全体の高さは2500pxほどあります。ちょっと縦長なページ。
わけあってdivが2階層いますが、スライドさせる対象のエレメントはulタグになります。
このulのmargin-leftやmargin-rightを変更することによって画像がスライドしているように見せる感じで作っていました。
んで画面のDOM構築が終わった段階で、ulタグの幅を取得しようとしたのですが、なぜかSafari3.1でだけwidthが少なかったのです。
たとえばFirefox3では1000pxあったのに、Safari3.1では650pxとか。
かなり中途半端なwidthが取れていたので、これはもしやDOM構築終わってないんじゃ?
と思ってwindow.onloadにfunctionをセットしてみたところ・・・
「Safari3.1でもwidthが1000pxで取得できました。が~~~ん」
jQueryのreadyの中身について
久々にjQueryのreadyの部分を追ってみました。
bindReadyというメソッドが2329行目あたりにあります。
その中に以下の記述があるのですが、これは「webkit nightlies currently support this event」とコメントされているとおりSafari3.1ではDOMContentLoadedがあるのでif文に入ります。
参考リンク:Changeset 26101 -- WebKit -- Trac
そしてこのDOMContentLoadedを登録しつつ、その先に進みます。
2366行目あたり。
ここでSafariの場合に2つの方法を使ってDOMContentがLoadedになったかを確認しています
まずdocument.redayStateがloadedかcompleteになるまで自分自身の関数をループします。
ここのチェックが終わったらstyleタグとlinkタグの合計数とdocument.stylesheets.lengthが一致するまで繰り返します。
これら2つの条件をクリアしたらやっとDOMContentがLoadedになった状態とみなすようです。
なかなか複雑ですねw
ここでちょっと気になるのですが、Safari3.1では「DOMContentLoaded」がありますが、その後の「if ( jQuery.browser.safari ) {」にも入ってしまうのです。
なので2重のほうほうでDOM構築を待つ感じになっています。どっちのほうが速いの?w
ちょろっと簡単にテストしてみました
上記のコードを実行した場合の挙動が少しへんでした。
まずDOMContentLoadedでjQuery.readyが登録され、その後のSafariの分岐でdocument.readyStateの状態を監視します。
するとdocument.readyStateのif文には約1回くらいしか入らず、その下にあるif文には一切入りませんでした。
順番にしてみました。
- DOMContentLoadedにjQuery.readyを登録
- Safariの場合にdocument.readyStateを監視
- DOMContentLoadedイベント発生でjQuery.isReadyがtrueになる
- document.readyStateを監視しているがjQuery.isReadyがtrueなのでループを抜ける
- だからdocument.stylesheetsのlengthチェックが走らない
う~~~ん・・・
だとするとSafariのDOMContentLoadedのほうがjQueryのDOM構築待ちより速いということでしょうか。
速い故にまだ構築し終わってない?w
まさかね!
まとめ
かなりイレギュラーなパターンだと思いますが、Safariでこういう現象があったのは確かです。
なのでwindow.onloadを待つか、documentのDOMContentLoadedを待つかはテストしながら判断したほうがよいかもしれません。
Firefox3.0やIE7、IE6では特に問題がなかったです。
SafariのDOM構築って少しくせがあるので、そこが悩みどころですね。
レンダリング超速いですが・・・
【関連する記事】
- Newer: Mac OS Xで環境変数にPATHを追加する方法
- Older: JavaScriptで単体テストをするならQUnitはいかが?
Comments:0
Trackback:0
- TrackBack URL for this entry
- http://hisasann.com/cgi-bin/mt/mt-tb.cgi/1124
- Listed below are links to weblogs that reference
- WebkitのDOMContentLoadedはDOM構築が完了していないかもしれない from HouseTect, JavaScripter Blog

