【问题标题】:How to use innerHTML on plain txt files in Firefox?如何在 Firefox 中的纯 txt 文件上使用 innerHTML?
【发布时间】:2009-04-11 14:11:15
【问题描述】:

如果您在浏览器中打开一个文本文件(.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。)

【问题讨论】:

标签: javascript firefox dom innerhtml


【解决方案1】:

它失败了,因为没有body - 即使您链接的文件也只是一个没有正文的文本文件(也许您在 firebug 中查看它?)。

最好的办法是替换正则表达式,因为您正在处理文本。

【讨论】:

    【解决方案2】:

    我想我找到了一个可行的解决方案。首先,让我详细说明一下这个问题。

    问题是: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);
        }
    };
    

    【讨论】:

      【解决方案3】:

      使用 GreaseMonkey

      【讨论】:

        【解决方案4】:

        似乎在 Firefox 3 的文本文档中,分配任何节点的 innerHTML 就像您分配给 innerText 一样(带有“

        ”前缀)。
        
        

        (由于非 XML/HTML 文档上的 DOM 脚本是完全未定义的,这当然是在 Firefox 的权利范围内;在 HTML 页面中显示文本文件似乎是一种快速破解。)

        所以你不能在 Firefox 上使用 innerHTML,但是其他 DOM 方法可以工作:

        var span= createElement('span');
        span.style.color= 'red';
        span.appendChild(document.createTextNode(match));
        

        【讨论】:

        • 对。问题是,要让它工作,你需要一个解析器。要么 - 使用一个用 JavaScript 编写的(例如 ejohn.org/blog/pure-javascript-html-parser ),它既慢又笨重,或者 - 找到一种方法让 Firefox 完成解析,我更喜欢
        • 并非如此,您可以只搜索文本节点数据并使用 splitText() 拆分您找到的每个匹配项并插入上述 span 元素。不涉及解析。
        猜你喜欢
        • 2015-10-03
        • 1970-01-01
        • 1970-01-01
        • 2014-11-01
        • 2011-10-20
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        相关资源
        最近更新 更多