XHTML文書内の script 要素内に書かれたスクリプトが、 注釈宣言<!-- -->内にあるために User Agent からスクリプトとして解釈されない場合に、 宣言内のスクリプトに DOM からアクセスをかけるスクリプト
JavaScript が標準の DOM をサポートしていれば、コメント内のスクリプトに 直接アクセスが可能である。
次のリンクで呼び出される関数は、簡単なアラートを表示するだけのものである。 注釈宣言内のスクリプトを解析対象としない User Agent が実在しない(*1)ため、 この例ではスクリプト全体を /* ~ */ でコメントアウトした。 ソースを見て確認して欲しい。
*1 Mozilla/Netsvcape6 では XHTML 文書の MIME が text/xml であれば、 script 要素の内容を #PCDATA として扱い<!-- -->を注釈として認識し、 スクリプトとは解さず HTML をレンダリングするようである。 しかし、text/xml ということは、即ちCDATAセクションが正しく処理されることを期待してよいことであり、 一方で、ユーザーエージェントが文書を HTML としてレンダリングしなくてもよいということでもある。 これらの点から、ここでは例を示さないことにする。
// DOM 判定:ビットフラグ UA = 0; bitIE=0x80; bitNN4=0x40; bitDOM=0x01; UA |= !!document.layers && bitNN4; UA |= !!document.all && bitIE; UA |= !!document.getElementById && bitDOM; if( !!!window.jsParsed ){ // jsParsed が定義されていなかったら解析開始 scriptid='testscript'; if( UA & bitIE ){ // IEフラグが true の場合 eval( document.all(scriptid).text .replace(/<!--/,'') // 注釈宣言削除 .replace(/\/\*|\*\//g,'') // 動作テスト用 ); }else if( UA & bitDOM ){ // DOMフラグが true の場合 var el = document.getElementById(scriptid).firstChild; if( el ){ eval( el.nodeValue .replace(/<!--/,'') // 注釈宣言削除 .replace( /\/\*|\*\//g, '' ) // 動作テスト用 ); } } }
実際はこのような関数の戻り値に対して eval() を行えばよいだろう。 関数内で eval() を行うと注釈内のスクリプトを実行はするが、 そこで定義された変数及び関数を保持しないようである。
function getScript(scriptid){ // 引数は script の id 属性 if( UA & bitDOM ){ // DOMフラグが true の場合 var el = document.getElementById(scriptid); if( el.nodeName=='script' // スクリプト要素で && el.hasChildNodes() // 子要素を持ち && el.firstChild.nodeType==8 ){ // 最初の子要素が注釈である場合 return( el.firstChild.nodeValue ); } } }
なお、DOMの対応度による分岐処理はかなりいい加減なのでその点は留意されたし。 XHTML 文書内の SCRIPT 要素の内容モデルを #PCDATA としてマーク宣言を正しく処理するような ユーザーエージェントには、標準DOMの充分なサポートを期待する。
このページ自体は Windows98 Internet Explore 4.01, 5.5 及び Netscape 6 で動作を確認している。 Netscape Nagivator 4.x/4.0x でこのスクリプトを動作させることは不可能なのだが、 Navigator 4 は script 内の注釈をスクリプトとして解釈するので 運用面での支障はないと考える。
それにしても IE の DOM サポートはひどい。