IEの独自実装による document.write を使わない DOMロード の検知方法を考えました。
CSSのbehaviorとexpressionを使います。
behaviorは画面描画のたびに頻繁に評価されます。
expressionを用いると、javascriptを記述できます。
上記を利用することで、Diego Perini氏による doScroll の動作チェックコードの頻度をあげるというアイデアです。
アイデアの中心となるコードは次のようなものです。
document.documentElement.style.setExpression('behavior', 'document.documentElement.polling()');
これを利用したDOMロードイベントのライブラリを公開します。
利用方法は、関数 onready の引数に、DOMロード後に実行したい関数を渡すだけです。
HTML :
<script src="http:// ... /onready.js" type="text/javascript" charset="utf-8"></script>javascript :
onready(function(){
alert('how are you?');
});
onready(function(){
alert('fine! and you?');
});
onready(function(){
alert('me, too!');
});
onready.js :
/*
onready.js : Cross-Browser DOMContentLoaded Event Listener
Copyright (c) 2007 latchet (http://juce6ox.blogspot.com/)
Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
*/
var onready = (function(){
var id,
ua = navigator.userAgent.toLowerCase(),
fs = [],
i = 0,
done = false,
/*@cc_on
oldExp,
@*/
init = function(){
var f, j = 0;
if(done) return;
done = true;
/*@cc_on
if(oldExp) document.documentElement.style.setExpression('behavior', oldExp);
else document.documentElement.style.removeExpression('behavior');
window.detachEvent('onload', init);
document.onreadystatechange = null;
/*@if(false)@*/
document.removeEventListener('DOMContentLoaded', init, false);
window.removeEventListener('load', init, false);
/*@end@*/
window.onload = null;
while(f = fs[j++]) f();
},
set = function(){
var ok;
/*@cc_on
oldExp = document.documentElement.style.getExpression('behavior');
document.documentElement.polling = function(){
try{
document.documentElement.doScroll('left');
}catch(e){
return setTimeout(document.documentElement.polling, 0);
};
document.documentElement.polling = null;
init();
};
document.documentElement.style.setExpression('behavior', 'document.documentElement.polling()');
window.attachEvent('onload', init);
document.onreadystatechange = function(){
if(document.readyState == 'complete') init();
};
/*@if(false)@*/
if(/mozilla/.test(ua) && !/compatible|webkit/.test(ua) || /opera/.test(ua))
document.addEventListener('DOMContentLoaded', init, false);
else if(/webkit|khtml/.test(ua) && (ok = /loaded|complete/))
(function(){
return ok.test(document.readyState) ? init() : setTimeout(arguments.callee, 0);
})();
window.addEventListener('load', init, false);
/*@end@*/
var old = window.onload
window.onload = (typeof old == 'function') ? function(){old();init();} : init;
};
return function(f){
if(typeof f != 'function') return;
if(done) return f();
if(!i) set();
fs[i++] = f;
};
})();
参考資料
- Diego Perini : IEContentLoaded - An alternative for DOMContenloaded on Internet Explorer
- msdn : behavior Property
- msdn : setExpression Method
- Jesse Skinner : addDOMLoadEvent - The Future of the Web
このアイデアを思いついてコードを書き終えたころに、細かい違いはありますが、 同じようにbehaviorとexpressionを使うアイデアを、doScrollハックの考案者であるDiego Perini氏がjQueryのメーリングリストに投稿していたことを検索の結果、知りました(笑)
Nabble - Re: document.ready firing too early within iframe
その時は正直、すこしがっくりしましたが、気付かなかったからこそ取り組めた面もあるのかもしれません。コードを整えつつ、その後、新しい別の方法が無いか再び試行錯誤し、(自分にとって)新しいアプローチを見つけました。document.writeは使わず、IEのDHTMLのondocumentreadyイベントを利用しつつ、新たな通信をしなくてもすむとおもわれる方法です。
IE/DOMLoad : cached htc

0 件のコメント:
コメントを投稿