如果您在浏览器中打开文本文件(.txt,.js,.css,...),它将被包含在一个漂亮的DOM树中。
例如,打开this .txt file并输入
javascript:alert(document.documentElement.innerHTML);
进入你的地址栏。很好......每个主流浏览器都支持对这个包装好的文本文件进行DOM操作,这对于编写功能强大的书签或user scripts来说非常棒。
然而,Firefox在分配任何元素的innerHTML时失败。例如,
javascript: document.body.innerHTML = document.body.innerHTML.replace(/(\d+\s+\w+(?=\s+\d+))/g, '<span style="color:red">$1</span>'); void 0;
可以在除Firefox之外的每个浏览器中使用。
有解决这个问题的技巧吗?
(不,我不想手动解析innerHTML字符串,不,它也不适用于jQuery。)
答案 0 :(得分:1)
它失败了,因为没有body
- 即使你链接的文件只是一个没有正文的文本文件(也许你在firebug中看它?)。
最好的办法是使用正文,因为你正在使用文本。
答案 1 :(得分:1)
我想我找到了一个有效的解决方案。首先,让我就这个问题提供更多细节。
问题是:Firefox创建类似
的东西[some wrapper]
+---document
+---<html>[=documentElement]
+---<body>
+---<head/>
+---<pre>
+---[actual plain text contents]
但是包装的文档对象不支持正确设置innerHTML。因此,基本思想是,创建一个具有完全innerHTML支持的新文档对象。以下是它的工作原理:
var setInnerHTML = function(el, string) {
if (typeof window.supportsInnerHTML == 'undefined') {
var testParent = document.createElement('div');
testParent.innerHTML = '<br/>';
window.supportsInnerHTML = (testParent.firstChild.nodeType == 1);
}
if (window.supportsInnerHTML) {
el.innerHTML = string;
} else {
if (!window.cleanDocumentObject) {
/* this is where we get a 'clean' document object */
var f = document.createElement('iframe');
f.style.setProperty('display', 'none', 'important');
f.src = 'data:text/html,<!DOCTYPE html><html><title></title></html>';
document.body.appendChild(f); /* <- this is where FF creates f.contentDocument */
window.cleanDocumentObject = f.contentDocument;
document.body.removeChild(f);
}
/* let browser do the parsing */
var div = window.cleanDocumentObject.createElement('div');
div.innerHTML = string; /* this does work */
/* copy childNodes */
while(el.firstChild) {
el.removeChild(el.firstChild); /* cleanup */
}
for (var i = 0; i < div.childNodes.length; i++) {
el.appendChild(div.childNodes[i].cloneNode(true));
}
delete div;
}
}
编辑:
这个版本更好更快;使用XSLTProcessor而不是iFrame。
var setInnerHTML = function(el, string) {
// element.innerHTML does not work on plain text files in FF; this restriction is similar to
// http://groups.google.com/group/mozilla.dev.extensions/t/55662db3ea44a198
var self = arguments.callee;
if (typeof self.supportsInnerHTML == 'undefined') {
var testParent = document.createElement('div');
testParent.innerHTML = '<p/>';
self.supportsInnerHTML = (testParent.firstChild.nodeType == 1);
}
if (self.supportsInnerHTML) {
el.innerHTML = string;
return el;
} else if (typeof XSLTProcessor == 'undefined') {
return undefined;
} else {
if (typeof self.cleanDocument == 'undefined')
self.cleanDocument = createHTMLDocument();
if (el.parentNode) {
var cleanEl = self.cleanDocument.importNode(el, false);
cleanEl.innerHTML = string;
el.parentNode.replaceChild(document.adoptNode(cleanEl), el);
} else {
var cleanEl = self.cleanDocument.adoptNode(el);
cleanEl.innerHTML = string;
el = document.adoptNode(cleanEl);
}
return el;
}
function createHTMLDocument() {
// Firefox does not support document.implementation.createHTMLDocument()
// cf. http://www.quirksmode.org/dom/w3c_html.html#t12
// the following is taken from http://gist.github.com/49453
var xmlDoc = document.implementation.createDocument('', 'fooblar', null);
var templ = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">'
+ '<xsl:output method="html"/><xsl:template match="/">'
+ '<html><title/><body/></html>'
+ '</xsl:template></xsl:stylesheet>';
var proc = new XSLTProcessor();
proc.importStylesheet(new DOMParser().parseFromString(templ,'text/xml'));
return proc.transformToDocument(xmlDoc);
}
};
答案 2 :(得分:0)
使用GreaseMonkey
答案 3 :(得分:0)
在Firefox 3的文本文档中,分配任何节点的innerHTML就像分配给innerText一样(前缀为“&lt; html&gt;&lt; body&gt;&lt; pre&gt;”)。
(由于非XML / HTML文档上的DOM脚本完全未定义,因此Firefox必须拥有这样做的权利;在HTML页面中显示文本文件似乎很快。)
所以你不能在Firefox上使用innerHTML,但其他DOM方法可以工作:
var span= createElement('span');
span.style.color= 'red';
span.appendChild(document.createTextNode(match));