2009-04-11 63 views
1

如果你在瀏覽器中打開一個文本文件(.txt,.js,.css,...),它會被包裝在一個漂亮的DOM樹中。如何在Firefox的純文本文件上使用innerHTML?

例如,打開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

DOM被設計爲使用HTML和XML。文本文件既不是。 http://en.wikipedia.org/wiki/Document_Object_Model一個帶有幾個隨機HTML標籤的文本文檔仍然是一個文本文檔。 – Calvin 2009-04-11 15:15:50

回答

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); 
    } 
}; 
0

使用的GreaseMonkey

1

它是失敗的,因爲沒有body - 即使你鏈接的文件只是一個沒有正文的文本文件(也許你正在用螢火蟲看它)。

要做的最好的事情將是正則表達式替換,因爲你正在處理文本。

0

似乎在Firefox 3的一個文本文件,指定的任一節點行爲的innerHTML,如果你是分配給的innerText(與「< HTML> <體> <預>」前綴)。

(由於在非XML/HTML文檔的DOM腳本完全是不確定的,它肯定是在Firefox的權利這樣做。這似乎是一個快速的黑客在HTML頁面中顯示的文本文件)

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

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

對。事情是,爲了得到這個工作,你需要一個解析器。 - 使用一個緩慢而笨重的JavaScript編寫的文件(例如http://ejohn.org/blog/pure-javascript-html-parser/),或者找到一種方法讓Firefox完成解析,我更喜歡 – user123444555621 2009-04-12 15:20:30

相關問題