Hatena::ブログ(Diary)

旧・私と私の猫の他は誰でも隠し事を持っている

2013年からはてなブログに引越しました。新旧ともども、今後もよろしくお願いします。

2011-10-20

jQuery - $(function(){}); の落とし穴

先日、いつものように Web ページで jQuery プログラムを書いててちょっとハマったのでメモ的に失敗談を開陳(恥)。

$(function(){}) は画像のロードを待たない?

きっかけは U/I 系の jQuery プラグイン jScrollPane が期待どおりに動作しないという現象でした。このプラグイン、固定サイズのブロック要素が overflow した際のスクロールバーをミニマルなデザインに差し替えてくれる優れものです。現象とは、そのブロック要素に画像が含まれている場合にスクロールバーが表示されない、というもの。しかも ChromeSafari の WebKib 系ブラウザに限って。

調べて判ったことを纏めると以下のようになります。

  • 普段深く考えもせずおまじない的に書いてた $(function(){}) は、$(document).ready(function(){}) の短縮形であり、DOMContentLoaded という DOM 構築完了イベントへのハンドラ記述法である。
  • WebKitブラウザでは DOMContentLoaded 発火の時点で画像のロードが完了しておらず(バグ?)、img タグに width や height 属性を明示しない限り画像のロードが完了するまで幅や高さ等が JavaScript で取得できない。
  • したがって画像を含むブロック内部の高さも算出することができず、画像抜きの高さとなってしまう。この理由により、jScrollPane が当該ブロックで overflow しないものと解釈してしまった。
  • これを回避するには DOMContentLoaded イベントではなく、画像のロードが全て完了した後で発火される window.onload を用いるといいみたい。

イベントは適材適所で使い分けましょうw ケースによっては window.onload を

ということで、万全を期すのであれば window.onload を常用すればいいのでしょうが、そうなると JavaScript 処理がとてももたついた動作になってしまう。なので、通常は $(function(){...}); で。今回のケースのように画像等の埋め込み要素をストリクトに操作したいような場合には window.onload を用いれば良い、という教訓というかバッドノウハウでした。この場合、JavaScript の記述的には

window.onload = function(){...};

でもいいのですが、これだと既存のイベントプロシジャをオーバーロードしてしまう危険性もあるので、イベントプロシジャを追加する書き方として以下のようにすれば良いみたいです(jQuery ってホントに良く出来てるなぁ)。

jQuery.event.add(window,"load",function(){...});

おまけ(デモ)

本件を再現するデモを作りました。

http://mariyudu.net/labo/jqueryEventDemo

このページには、画像を含んだブロック要素が左右二つあり、両方とも

height: 200px;
overflow: hidden;

とスタイル定義してあります。左側は $(document).ready() で、右側は window.onload 時に jScrollPane を適用するようにしてあります。これを ChromeSafari で表示させると、左のブロックにはスクロールバーが適用されずに下半分くらいが隠れたままなのが分かりますね。

aa 2011/10/22 12:23 $(window).load(fn)

mizutamamizutama 2012/03/09 19:05 chromeで表示されなくて困ってました。ありがとうございます!

taakumitaakumi 2012/07/09 23:38 とても参考になりました!
ありがとうございます。

すぷーすぷー 2012/10/17 00:00 同じ現象で悩んでいました・・・参考になりました。ありがとうございます!

hhrhhr 2013/03/12 18:02 さっくり問題解決しました。

c 2014/05/11 00:33 いまChromeでサンプルを確認してみたところ、どちらも問題なくスクロールできました。
すでにChromeのバグは解消されているということですかね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/Mariyudu/20111020/1319121759
リンク元
Connection: close