window.onload 前でも DOM 処理が可能なら通知してくれる domready.js
DOM 読み込み完了のタイミングで、任意の関数を実行できるようにする JavaScript ライブラリを書いてみた。
mootools の同様の機能を基にしていて、単体として使いやすいように外部ライブラリへの依存性をなくし、prototype.js とも併用できるようにしたもの。
現状、手元の環境では以下のブラウザで動作確認済み。
- IE 7 (XP standalone)
- IE 6 SP2
- Firefox 2.0.0.4
- Opera 9.21
- Safari 2.0.4
- Mac Firefox 2.0.0.4
- Mac IE 5.2.3
ただし、Mac IE では window.onload
で代用するように実装してある。まあ、スクリプトエラーが出るよりマシだろう。
使い方
まず、domready.js を読み込む。
<script type="text/javascript" src="/javascripts/domready.js"></script>
prototype.js
と併用する場合は prototype.js
より後に読み込む。
<script type="text/javascript" src="/javascripts/prototype.js"></script>
<script type="text/javascript" src="/javascripts/domready.js"></script>
あとは、DOM 読み込み完了のタイミングで実行したい関数を Event.domReady.add
で登録するだけ。
Event.domReady.add(function() {
...
});
他のイベントと登録方法が異なるのは直感的じゃない、とか言われそうだけど、正直あんまり気にならない。
経緯: window.onload の欠点
多くの Ajax 系実装では、ページ読み込み完了時に初期化などを実行するようになっている。
Event.observe(window, 'load', function() {
...
});
これは prototype.js によるイベント処理だが、window.onload
イベントで処理を実行するために、関数を登録しているのが分かるだろう。
わざわざこんなことをしているのは、DOM を操作したいからだ。
だから、ほとんどの Ajax 系実装は window.onload
イベントがやってくるのをじっと待っている。window.onload
イベントのあとでは DOM ツリーは完全に構築されているし、他に DOM ツリーが構築済みなのを知る、適当なイベントもないからね。
もちろん、window.onload
は完全じゃない … いや、それは嘘で、完全すぎる。DOM ツリーの構築を待つだけじゃなく、すべての画像の読み込みも待ってしまうんだ。そうすると、画像を多く含むようなページでは、Ajax の処理がいつまでたってもはじまらない、なんてことが起こって、これは、あんまり嬉しくない。
解決策: onDOMContentLoaded とクロスブラウザな実装
ブラウザごとにさまざまな解決策がある。
たとえば、Firefox など Mozilla 系のブラウザでは onDOMContentLoaded
というイベントがあって、これはそのものずばり、DOM ツリーが読み込み完了したときに通知してくれるイベントだ。そして、Safari では document.readyState
が、IE では defer
属性を有効にした script
要素の読み込みが利用できる(このへんの詳細は Dean Edwards: The window.onload Problem - Solved! に詳しい)。
また、mootools には window.addEvent('domready', ...)
、JQuery には同様に、$(document).ready()
というクロスブラウザな実装が用意されている。嬉しいことに、prototype.js にも近いうちに同様の機能を取り込もう、という動きがあるようだ。
- #5414 (PATCH) Faster onload for Event.onload
- Changeset 6596: Support for “DOMContentLoaded” event handling (prototype.js event branch)
今回つくった domready.js は mootools の実装を基にしているが、だいたいどれも同じような実装みたいだ。