2007-12-12

IE/DOMLoad : cached htc

document.write を使わず、外部ファイルのダウンロードをしない、IE用の DOM ロードイベントを取得する方法を考えました。

DHTMLの ondocumentready イベントを利用します。
そのためには、DOM要素に behavior 属性で htc ファイルへの参照設定が必要となります。そこで、外部ファイルのダウンロードを不要とするために、ブラウザのキャッシュ機能の利用を考えて、javascriptファイルの拡張子を htc とします。そしてブラウザ判定でIEならば、拡張子が htc である javascript ファイル自身のURLをbehavior属性に渡します。これによりブラウザのキャッシュが使用され、新たな通信が不要となることが期待されます。

HTML :

<script src="http:// ... /onready.htc" 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.htc :
/*
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<public:component xmlns="http://www.w3.org/1999/xhtml" xmlns:public="urn:HTMLComponent">
<public:attach event="ondocumentready" onevent="element.init();" />
<!--

    onready.htc : Cross-Browser DOMContentLoaded Event Listener with Cached HTC script hack for IE

    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,
        init = function(){
                   var f, j = 0;
                   if(done) return;
                   done = true;
                   /*@cc_on
                   document.documentElement.init = null;
                   if(id != undefined) document.documentElement.removeBehavior(id);
                   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();
               },
    /*@cc_on
        url  = (function(e, ok){
                   while(e = e.lastChild)
                       if(e.nodeName.toLowerCase() == 'script' && ok.test(e.src))
                           return e.src;
               })(document, /^[^?#]+\.htc$/),
    @*/
        set  = function(){
                   var ok;
                   /*@cc_on
                   document.documentElement.init = init;
                   if(url) id = document.documentElement.addBehavior(url);
                   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;
    };
})();
//--></public:component>


参考資料

0 件のコメント: