おはようございます。最新版のリリースに向けて、近頃はそれなりに時間を充てています。ppBlogでは、JavaScriptはかなり重要な位置を占めています。一応、JavaScriptオフでも閲覧には問題ないとは思うのですが、管理モードなどでは必須です。
で、ppBlogでの主要なJavaScriptライブラリである、js/script.jsの見直しを進めているところです。この中で、windowのonloadイベントには、いくつかの関数を割り当てています。これまでは、
addEvent(window, "load", function (){ roundedStyle(); quotedStyle(); initCSSHover(); if(moz) hackFirefoxToolTip(); });
でしたが、これだと、HTMLのDOMエレメントのみならず、外部リンクや画像やらも読み込んだ後でないと発動しません。画像など読み終えてなくても、DOMエレメントを読み込んでパースした時点で動く関数などはさっさと動いて欲しいものです。このようなことは誰もが思っているみたいで、JavaScriptマスターのDean Edwardsは、Firefoxに DOMContentLoaded という隠し属性みたいなやつを見つけて、それで、ごにょごにょやっています。→ The window.onload Problem - Solved!
でも、個人的には、あまりスマートな方法には見えないんで(IE向けには外部スクリプトを別に用意しないといけないし)、自分なりにも考えてみました。そもそも、IEにあるdocument.readyStateG みたいなやつが標準で提供されていれば、みんな悩まずに済むのだけれど、ないから仕方なし(IEでも、挙動不審なところがあるようだし)。
で、原始的な方法ではあるが、DOMエレメントの数を取得する d.documentElement.getElementsByTagName("*").length をミリ秒単位で監視しておき、それがプラトーに達した時点を読み込み完了とするというアプローチでスクリプトを書いてみた。こんな感じ。
DOM = { ready : false, size : d.documentElement.getElementsByTagName("*").length, check : function(){ DOM.ready ? DOM.onload() : DOM.update.await(100)(DOM.size); }, update : function(i){ if(d.documentElement.getElementsByTagName("*").length==i){ DOM.ready = true; DOM.onload(); } else { DOM.size = d.documentElement.getElementsByTagName("*").length; DOM.update.await(50)(DOM.size); } }, onload : function(){} } DOM.check();
あまり深くは考えていないけど、これで期待通りの動作をしている感じ。このサイトのppBlogでは、先ほどのwindow.onloadのイベントを、こっちに割り当てて、
DOM.onload = function(){ roundedStyle(); quotedStyle(); initCSSHover(); if(moz) hackFirefoxToolTip(); }
というふうにしています。このやり方だとブラウザを選ばなくてベターではなかろうか。アイコン画像なんかを全部表示していなくても、DOMツリーを読み込んだ時点で発動します。エドワーズのとこにあるデモのスクリプト(http://dean.edwards.name/my/busted.html )に似せて同じことをDOM.onload で実現したサンプルを載せておきます。→http://p2b.jp/demos/busted.html
ちなみに、Functionオブジェクトに、新たにawaitというメソッドを定義してそれを使っています。まぁ普通にsetTimeoutでやれば良いのだけれど、勉強がてら。JavaScriptマスターである最速インターフェース研究会さんのエントリーを参考にしました。→ Function.prototypeを拡張して遅延実行を実現する
まだよく理解していないので違うかもしれないけれど、このawaitメソッドをまねて、loopというのを定義しました。正しいのかな? 狙いとしては、limitで指定した回数だけ、msミリ秒おきに関数を実行するというやつです。
Function.prototype.loop = function(ms, limit){ var count = 0, self = this; return function(a){ if(limit <= count) return; count++; self.await(ms)(a); arguments.callee.await(ms)(a); } }
今のところppBlogでは、これは使っていないけど使うかもしれない。簡単な例としては、
var func = function(v){alert(v);} func.loop(1000,3)("1秒おきにアラートを3回表示");
とか。
あと、ログインの際にAjaxを使って、少しだけログインの手順を減らすというのを考えています。その際にAjaxのPOSTメソッドでユーザー名とパスワードを送信するのですが、このままだとセキュリティー的に気持ち悪いので、MD5で暗号化してから送信するようにする予定です。大まかな動作は確認出来ています。とりあえず。(あぁ、コメント数がマイナスになるのも直さないと・・・)
Comments