window.onloadの代替スクリプト

category-icon

Updated Entry: http://p2b.jp/200805-events-orderLink

 今日は七夕Wですね。小学生の頃は、学校総出で「♪笹の葉さーらさら〜」ってやって、七夕伝説に思いを馳せたものですが。いつになってもガキの頃の心を忘れない大人でいたいものです。

 さて、Ajaxの隆盛によって、その根幹であるJavaScriptはブログに欠かせないものとなっています。ppBlogも例外ではなく、至るところで活躍してます。一般にブログの(トップ)ページは、色々な情報を詰め込んでいるために、ファイルサイズは大きくなる傾向にあり、また、画像も至るところで使われるために、読み込むべきコンテンツサイズは更に大きくなります。ブロードバンドが当たり前の今日でもページの表示にちょっと待たされるのは珍しいことではありません。で、JavaScriptは(画像も含めた)ページの内容物が全部読み込まれた後に作動させるのが一般的です。なので、もし、画像の読み込みに時間がかかったりすると、JavaScriptがうまく動かずに、狙い通りの効果が得られなかったり、スクリプトエラーが出たりします。こういうのはたいてい、window.onloadやBODYタグでのonloadイベントで制御しているんですが、JavaScript使いなら、画像の読み込みを待たずに、ページの構成要素(DOMエレメント)がパース(読み込まれて解釈)された時点でプログラムを走らせたいと思うものです。

 その解決法として、JavaScriptマスターのDean EdwardsLink 氏が、window.onload問題を解決した!Link と言ったのが昨年の9月頃で、このブログでも言及したLink ことがあります。彼のやり方は、Mozilla系ブラウザの隠し要素DOMContentLoadedを利用したもので、IEはこれに対応していないので、IEだけは、外部jsスクリプトを用意しないといけませんでした。その不完全さが好きになれなかったので、ppBlogではこれとは違うアプローチ(setTimeoutを利用するやり方)を取ってたんですが、このsetTimeoutがらみの手法は、PCの性能などにも大きく左右されるし、どうも不安定さがあるんですよね。角丸コーナースクリプトが上手く作動しなかったり。

 そんな折、先月にこれでほぼ100%解決と思われるやり方がEdwardsを含めたJavaScriptマスターたちによって「発見」されました。→http://dean.edwards.name/weblog/2006/06/again/Link

 この新しい方法では、IEでも外部スクリプトを別に用意する必要がなく、またSafariなどでも問題なく動くものです。いやぁ、みんな頭良いよなぁ。自分でも個人的に、IE向けにはdocument.readyStateを利用した方法を試したりしたんですが、IEの返すdocument.readyStateが、またいい加減なシロモノでしてあえなく挫折。しかも、DOMContentLoadedに関しては、Operaの最新バージョンであるOpera9でサポートされたりしたんで、自分もこの潮流に乗っかることにしました。そのうちSafariでもDOMContentLoadedはサポートされそうな予感。そういえば、Opera9では、とうとうdocument.designModeがサポートLink されましたね。以前、document.designModeGを利用して、ppBlog組み込みの本格的なエディターを作ろうとしたことがあったのですが、IEの吐き出すHTMLソースがあまりに後進的だったので放置したままになっていますねぇ。IE7βでどうかはまだ試していないです(期待してないけど)。

 少し逸れましたが、とにかくppBlogでもwindow.onloadに替わる新しいやり方を実装してみました。詳しい話はエドワーズのブロッグを読んでいただくとして、ppBlogでは現時点で、次のような感じにまとめています。

DOM = { /* window.onload alternative */
 complete : function(){
  if(arguments.callee.done) return;
  arguments.callee.done = true;
  if(typeof _timer != 'undefined'){
   clearInterval(_timer);
   _timer = null;
  }
  DOM.onload();
 },
 check : function(){
  if(d.addEventListener){ // Mozilla/Opera9向け
   d.addEventListener("DOMContentLoaded", DOM.complete, false);
  }
  if(navigator.userAgent.match(/webkit|safari|khtml/i)){// Safari向け
   var _timer = setInterval(function(){
    if(d.readyState.match(/loaded|complete/)){
     DOM.complete();
    }
   }, 50);
  }
   /*@cc_on @*/
   /*@if (@_win32)// IE向け
    d.write('<script id="_decoy_" defer src="javascript:void 0"><¥/script>');
    d.getElementById("_decoy_").onreadystatechange = function(){
     if(this.readyState=='complete'){
      DOM.complete();
     }
    };
   /*@end @*/
  addEvent(window, "load", DOM.complete);//その他
 },
 onload : function(){}
}

 ポイントは、DOMContentLoadedをサポートしているならそれを使い、Safari系ではdocument.readyStateを利用し(IEと違って信用できる値を返すようである)、IEではスクリプト属性のdeferを利用することです。このdeferは文字通り、(外部読み込み)スクリプトの実行を遅延させる属性でIEのみがサポートしています。このdeferは、document.readyStateよりずっと堅実です。ついでに言うと、ここで使われているdefer指定の外部スクリプト指定は、もはや単なる「飾り」になっています(それがIE7正式版でどういう扱いになるか一抹の不安が残りますが)。詳しくは、このトリッキーな手法を発見したMatthias MillerLink 氏のブログ(エントリーLink )をどうぞ。

 ちょっと話題がずれますが、IE7βは先日ベータの最新版かつベータ最終版が出ましたね。それに少し関連したErik氏の面白いエントリーがあったので紹介しておきます(まぁ、期待外れ感が漂う、ちょっとしたジョークなんでしょう)。

 →IE 7 DOM and JS ChangelogLink

 Erik氏は、昨日のエントリーにも出てきたWebFXの主宰者の一人で、彼もまたJavaScriptマスターです。このエントリーは時期的にIE7ベータ1-2についてのものかな。思わず笑ってしまいました

 


— posted by martin at 04:40 am   commentComment [0]  pingTrackBack [3]

T: Y: ALL: Online:
Created in 0.0049 sec.
prev
2006.7
next
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31