| |
HTML のロード中にスクリプトで HTML を出力する場合は従来どおり document.write を使用することができますが、 onLoad 後に HTML の一部を変更するような場合には IE のように insertAdjacentHTML や NN4 のようなレイアに document.write を使用する方法は使えません。
ここでは onLoad 後に HTML の一部を変更する方法について 研究してみましょう
W3C DOM Level 1 な方法
「ECMAScript Binding」の「オブジェクトの生成」でも言及したのですが、 W3C DOM でオブジェクトを生成するには createElement や createTextNode などの関数を駆使する必要があります。
これは従来の NN や IE での方法とは異なり、直感的に HTML を作成し
これをそのまま出力することが難しいことを意味します。
つまり、これを実現するクロスなドキュメント出力関数は、そのインターフェイスとして
出力するドキュメントの構造を指定しなければならなくなるわけです。
writeDivHTML(div,op,cl,html1,html2,...);ではなく
writeDivHTML(div,op,cl,obj1,obj2,...);と言うように HTML ではなく生成済みのオブジェクトを引数としなければならなくなります。
また、オブジェクトの生成は NN4 や IE4,5 では従来どおり HTML で良いのですが、 Mozilla の場合は createElement や createTextNode を 使用するので、これを隠蔽する必要があります。
writeDivHTML(div,true,true, pElement(null,null,textElement('Hello! Mozilla')) );という具合に HTML ではなく概念的なオブジェクトを指定するわけです。
_dom=(document.all?3: (document.getElementById?1:(document.layers?2:0))); function textElement(text){ if(_dom==1) return document.createTextNode(text); // Mozilla return text; // NN4,IE4,5 } function pElement(nm,cls){ if(_dom==1){ // Mozilla var p=document.createElement('P'); if(nm) p.setAttribute('id', nm); if(cls) p.setAttribute('class',cls); for(var i=2; i<arguments.length; i++) p.appendChild(arguments[i]); return p; } else if(_dom==2 || _dom==3){ // NN4,IE4,5 var chlds=''; for(var i=2; i<arguments.length; i++) chlds+=arguments[i]; var attrName =nm?(' name="'+nm+'"'):''; var attrClass =cls?(' class="'+cls+'"'):''; return '<p'+attrName+attrClass+'>'+chlds+'</p>'; } return ''; }因みに、writeDivHTML 関数の内容は以下のようになるわけです。
function writeDivHTML(div,op,cl){ if(_dom==1){ // Mozilla if(op){ for(var i=div.childNodes.length; i>0; i--) div.removeChild(div.childNodes.item(i-1)); } for(var i=3; i<arguments.length; i++) div.appendChild(arguments[i]); } if(_dom==2){ // NN4 var s=''; if(op) div.document.open('text/html','replace'); for(var i=3; i<arguments.length; i++) s+=arguments[i]; div.document.write(s); if(cl) div.document.close(); } if(_dom==3){ // IE4,5 var s=''; for(var i=3; i<arguments.length; i++) s+=arguments[i]; if(op) div.innerHTML=''; div.insertAdjacentHTML('BeforeEnd',s); } }
ん〜。...これじゃあ、今まで作成したスクリプトは大改造を余儀なくされますよね。
#> それに、HTML を指定するのも面倒だし... f(^^;;
Mozilla の開発者もこの点を問題視していたらしく( 類推 )、 W3C DOM Level2 にもない関数をいくつか追加した結果、 HTML からオブジェクトを直接生成する手段が提供されているようです。
Mozilla な方法 1
HTML から直接オブジェクトを生成する手法は HTML Model ではなく、
Range Model にあります。
Range Model は W3C DOM Level 2 で規定されている、ツリー状に構築された DOM に
おけるセレクションのためのモデルで、ある特定の2点間の HTML の断片
( Document Fragment )を示すためのオブジェクトです。
Mozilla では NSRange というクラスに
createContextualFragment 及び isValidFrgment
というメソッドを追加しているため、HTML の断片から
DocumentFragment( Node のサブクラス ) を生成することができます。
これを利用すれば writeDivHTML 関数は以下のように 従来のインターフェイスのままレイアに HTML を出力することができます。
function writeDivHTML(div,op,cl){ var s=''; for(var i=3; i<arguments.length; i++) s+=arguments[i]; if(_dom==1){ // Mozilla if(op){ // レイアの下位にある Node を全て削除 while(div.hasChildNodes()) div.removeChild(div.lastChild); } // DocumentFragment を生成する var range=document.createRange(); range.selectNodeContents(div); range.collapse(true); var cf = range.createContextualFragment(s); // レイアの管理下におく div.appendChild(cf); } if(_dom==2){ // NN4 if(op) div.document.open('text/html','replace'); div.document.write(s); if(cl) div.document.close(); } if(_dom==3){ // IE4,5 if(op) div.innerHTML=''; div.insertAdjacentHTML('BeforeEnd',s); } }
Mozilla な方法 2
もう1つの Mozilla な方法は M16 から追加された innerHTML
プロパティを使用する方法です。
このプロパティは IE との互換動作のために M16 で( 試験的に? )追加されたプロパティで
良くも悪くもほぼ IE の innerHTML と同様の動作をするようです。
#> このプロパティを使用する際の注意事項は
「DHTML 〜 怪談! Cross Browser」の「innerHTML と insertAdjacentHTML」を
参照してください。
例によって、 writeDivHTML 関数としての実装をしてみると
function writeDivHTML(div,op,cl){ var s=''; for(var i=3; i<arguments.length; i++) s+=arguments[i]; if(_dom==1){ // Mozilla if(op) div.innerHTML=''; div.innerHTML+=s; } if(_dom==2){ // NN4 if(op) div.document.open('text/html','replace'); div.document.write(s); if(cl) div.document.close(); } if(_dom==3){ // IE4,5 if(op) div.innerHTML=''; div.insertAdjacentHTML('BeforeEnd',s); } }
ってところでしょうか。
まとめ
...ってことで、 W3C DOM な方法と Mozilla な方法の3種類を紹介したわけですが、
考慮すべき点がないわけではありません。
つまり、
結論を言えば「Mozilla な方法 2」はまだ様子見ですので
最初の2つの方法だけに限定すれば、どーせ IE は IE5 を見てもわかるように、
W3C DOM の実装は自分の都合で行うでしょうから、最初の項目はあまり気にせず、
高頻度で大量の出力を行うかどうかで、どちらの方法を採用するか決定しても
よさそうな気がします。 f(^^;;
戻る | Copyright(c) 2000 ShinSoft. All rights reserved. |