前回,Operaにおいて,
Content-Typeの判定誤りによって
text/plain扱いされてしまったページを
htmlとして認識させるUserJSを記述した
(『UserJS : Content-Typeの判定誤りを修正する』を参照).
しかし,この方法で認識されたhtmlでは,
scriptノード中のスクリプトが認識されないことが発覚した.
今回は,前回作ったスクリプトを改良し,
この問題を解消する.
問題の解決方法
innerHTMLに投げて認識されたscriptノードは,
ノードとして存在するものの,
その中のスクリプトが実行されないようである.
(Operaのバグだろうか?)
そのため,cloneNode()メソッドを用い,
新しくscriptのDOMノードを作り直す.
これにより,対象のノードに含まれるスクリプトを起動する.
また,この方法でスクリプトを起動しても,
document.write()メソッドを用いて
その場にテキストを書くことはできない.
そのため,document.write()メソッドが現れたら,
対象scriptノードの前に新しくspanノードを作る.
ここに,document.write()メソッドの引数を置く.
最後に,このノード内のテキストを,
eval()で評価した値に置き換えることで,
document.write()を行った時と同等の効果を図る.
使用方法
以下のテキストを,拡張子jsとして
OperaのUserJSディレクトリに設置する.
前回のヴァージョンを使用している場合は,
以下のスクリプトと置き換えること.
document.addEventListener('load',
function (e){
var html = document.getElementsByTagName('html')[0];
var body = document.getElementsByTagName('body')[0];
//テキスト扱いされたHTMLでないなら,無視
if(html.childNodes.length!=1 || /\.html?(#.*|\?.*)?$/.test(location.href) || !/<html\b.*>/.test(body.innerText) || !/<\/html>/.test(body.innerText)){
return;
}
html.innerHTML = body.innerText;
//scriptタグを新しく作り直す
//innerHTMLに投げたscriptは,そのままでは起動しないため,
//新しく作り直して起動する
function touchNode(obj){
switch(obj.nodeName.toLowerCase()){
case 'script':
var newObj = obj.cloneNode(true);
obj.parentNode.replaceChild(newObj, obj);
obj = newObj;
while(/document\.write\((.*)\);?/.test(obj.textContent)){
//document.writeは,touchNodeしても起動しないため,
//名称置換用の目印を作っておく
var span = document.createElement('span');
span.setAttribute('class', '_viewAsHtml_script_write');
span.appendChild(document.createTextNode(RegExp.$1));
obj.parentNode.insertBefore(span, obj);
obj.textContent = obj.textContent.replace(/document\.write\((.*)\);?/, '');
}
break;
}
for(var i=0; i<obj.childNodes.length; i++){
touchNode(obj.childNodes[i]);
}
}
touchNode(html);
//名称置換用の目印をevalした結果に置き換える
var spans = document.getElementsByTagName('span');
for(var i=0; i<spans.length; i++){
if(spans[i].getAttribute('class') != '_viewAsHtml_script_write'){
continue;
}
spans[i].textContent = eval(spans[i].textContent);
}
},
false
);
コメント (4)