カテゴリー » 開発日誌 » JavaScript

このサイトのppBlog's webRingのリストは、BlogPeople からdocument.writeで書き出しています。というかBlogPeopleのスクリプトがそうなっているのですが。で、document.writeが、HTMLソースの最初の方にあると、document.writeによる書き出しが終わるまで、それ以降のページのレンダリング(HTMLの書き出し)はストップした状態となります。document.writeによって呼び出している外部サーバー(ここではBlogPeople)のレスポンスが速ければ、ページ描画で待たされることはありませんが、たまにはレスポンスが遅くて、ページの残りがなかなか表示されないという事態は起こりえます。このdocument.writeは、広告バナーなどでも当たり前のように使われていて、メインコンテンツの内容が知りたいのに、バナー広告がなかなか表示されず、イライラしたという経験もあるかと思います。確か、GoogleのADWordsなどでも使われているのではないでしょうか。

こういう事態を避けるには、HTMLソースの最後の方で document.write を呼び出すというのがあり、これはこれで有効ですが、そう汎用性のあるやり方ではなく、また、スクリプト(JavaScript)がHTMLの中で、あちこちに散らばるのは美しくないです。

ここでは、document.writeの内容をとりあえず配列などに一時的に退避させといて(この間にHTMLソースの描画は進んでいきます)、ページ読み込み完了と同時に、そのストックしておいたdocument.write内容を吐き出すという方法について書いておきます。

まず、普通にdocument.writeを含んだ外部スクリプトを呼び出すやり方。これは、BlogPeopleがこうしましょう、と述べているものです。

<script type="text/javascript" src="http://www.blogpeople.net/display/usr/0f0d40535b5b4103.js" charset="euc-jp"></script>

これの実際の中身は、次のようになっています。

document.write('<div class=¥'blogpeople-main¥'>'); document.write('登録されたサイト') ： ： document.write('</div>'); document.write('<div class=¥'blogpeople-powered-by¥'>'); document.write('<br /><a href=¥'･･･¥' target=¥'_blank¥'><img src=¥'･･･¥' border=¥'0¥' alt=¥'Powered By BlogPeople¥' /></a>'); document.write('</div>');

ここに使われているdocument.write内容をとりあえず配列に入れておけば良いのですが、それには次のようにします。

(function(){ var alts = []; // document.writeの内容を入れておく配列を準備 d._write = d.write; // オリジナルはコピーしておく d.write = function(s){ alts.push(s);} // d.writeを新たに定義 var src = "http://www.blogpeople.net/display/usr/0f0d40535b5b4103.js"; var script = d.createElement('script'); script.setAttribute('type', 'text/javascript'); script.setAttribute('charset', 'euc-jp'); script.setAttribute('src', src); d.getElementsByTagName('head')[0].appendChild(script); addEvent(window, "load", function(){ o("_webRing").innerHTML = alts.join(""); // 指定した場所に流し込む d.write = d._write; // d.writeを元の定義に戻しておく }); }());

ポイントは、既存のdocument.writeを新たに、

document.write = function(s){ alts.push(s); }

と再定義している点です。ここではaltsという配列に退避させています。こうすることで、document.writeによる書き出しを待つことなく、残りのページレンダリングを進めていくことが出来ます。このスクリプトで、SafariでもIE6でもFirefoxでもきちんと動くことを確認しています。

小生のブログであるmartin.p2b.jpのwebRing と、このサイトにあるwebRing とは同じ外部スクリプトを呼び出しているのですが、比較のために、このサイトのwebRingは上記の手法で、martin'sの方は従来の方法で呼び出しています。BlogPeopleのサーバーレスポンスは素早いので、なかなか差が実感できにくいかと思いますが、このサイトのやつは、(サイドバーのHTMLソースはdocument.writeよりも後にもかかわらず)サイドバーが先に表示されて、最後にwebRingのリストが表示されるのに対して、martin'sの方は、HTMLソースの順序通り、webRingリスト→サイドバーという順序で表示されています。

ちなみに、このサイトのwebRingは、ppBlogの「ページ作成機能」を使って作成しているのですが、具体的に、どのような内容になっているのか、理解の一助のために添付しておきますね。

まぁ、こんなアプローチもありますよということで