代码之家  ›  专栏  ›  技术社区  ›  user123444555621

如何在firefox中的纯文本文件上使用innerhtml?

  •  1
  • user123444555621  · 技术社区  · 15 年前

    如果您在浏览器中打开一个文本文件(.txt,.js,.css,…),它将被包装在一个漂亮的DOM树中。

    例如,打开 this .txt file 进入

    javascript:alert(document.documentElement.innerHTML);
    

    进入你的地址栏。很好…每个主要的浏览器都支持对这些包装好的文本文件进行DOM操作,这对于编写强大的书签或 user scripts .

    然而,火狐在 指派 任何元素的innerhtml。例如,

    javascript: document.body.innerHTML = document.body.innerHTML.replace(/(\d+\s+\w+(?=\s+\d+))/g, '<span style="color:red">$1</span>'); void 0;
    

    除了火狐,其他浏览器都可以使用。

    有没有解决这个问题的诀窍?

    (不,我不想手动解析innerhtml字符串,不,它也不适用于jquery。)

    4 回复  |  直到 15 年前
        1
  •  1
  •   Andrew Hare    15 年前

    失败是因为没有 body -甚至你链接的文件也只是一个没有正文的文本文件(也许你在Firebug中查看它?).

    最好的方法是使用regex替换,因为您使用的是文本。

        2
  •  1
  •   user123444555621    15 年前

    我想我找到了一个有效的解决办法。首先,让我详细介绍一下这个问题。

    问题是:火狐创建了

    [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
  •  0
  •   Itay Moav -Malimovka    15 年前

    使用润滑器

        4
  •  0
  •   bobince    15 年前

    在firefox 3的文本文档中,分配任何节点的innerhtml就像分配给innertext一样(预先准备好了“html><body><pre>pre&226;”)。

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

    所以你不能在火狐上使用innerhtml,但是其他的dom方法可以工作:

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