2009-04-11 2 views
1

Wenn Sie in Ihrem Browser eine Textdatei (.txt, .js, .css, ...) öffnen, wird diese in eine schöne DOM-Struktur eingefügt.Wie benutzt man innerHTML in einfachen txt-Dateien in Firefox?

Zum Beispiel öffnet this .txt file und

javascript:alert(document.documentElement.innerHTML); 

in der Adressleiste eingeben. Nett ... jeder große Browser unterstützt DOM-Manipulation an diesen umschlossenen Textdateien, was eine großartige Sache ist, um starke Bookmarklets zu schreiben oder user scripts.

Allerdings scheitert Firefox Zuordnung ElementHTMLHTML. Zum Beispiel

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

funktioniert in jedem Browser außer Firefox.

Gibt es einen Trick, um dieses Problem zu umgehen?

(Nein, ich möchte nicht manuell den innerHTML- Zeichenfolge analysieren, und nein, es mit jQuery nicht funktioniert entweder.)

+0

DOM wurde entwickelt, um mit HTML und XML zu arbeiten. Ein Textdokument ist keines von beiden. http://en.wikipedia.org/wiki/Document_Object_Model Ein Textdokument mit ein paar zufälligen HTML-Tags ist immer noch ein Textdokument. – Calvin

Antwort

1

Ich denke, ich habe eine funktionierende Lösung gefunden. Lassen Sie mich zunächst einige Details zu dieser Frage nennen.

Das Problem ist: Firefox schafft so etwas wie

[some wrapper] 
+---document 
    +---<html>[=documentElement] 
     +---<body> 
      +---<head/> 
      +---<pre> 
       +---[actual plain text contents] 

aber das umwickelte Dokumentobjekt nicht unterstützt innerHTML- richtig einstellen. Die Grundidee ist also, ein neues Dokumentobjekt mit vollständiger innerHTML-Unterstützung zu erstellen. Hier ist, wie es funktioniert:

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

edit:

Diese Version ist besser und schneller; Verwenden von XSLTProcessor anstelle von 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

Verwendung Greasemonkey

1

Es versagt, weil es keine body - selbst die Datei, die du verlinkt hast, ist nur eine Textdatei ohne Körper (vielleicht siehst du es in einem Firebug an?).

Die beste Sache zu tun wäre ein Regex ersetzen, da Sie mit Text arbeiten.

0

Es scheint auf einem Textdokument in Firefox 3, die Innerhtml von irgendwelchen Knoten wirken zuweisen, als ob Sie zu Innertext zuweisen (mit „< html> < body> < pre>“ vorangestellt).

(Da DOM Scripting auf einer Nicht-XML/HTML-Dokument vollständig nicht definiert ist, ist es sicherlich innerhalb Rechte Firefox, dies zu tun,. Es erscheint eine schnelle Hack um Textdateien in einer HTML-Seite anzuzeigen)

Sie können also innerHTML nicht in Firefox verwenden, aber andere DOM-Methoden funktionieren:

+0

Richtig. Die Sache ist, damit das funktioniert, brauchen Sie einen Parser. Entweder - verwenden Sie eine in JavaScript (z. B. http://ejohn.org/blog/pure-javascript-html-parser/) geschrieben, die langsam und sperrig ist, oder - finden Sie einen Weg, um die Analyse von Firefox zu machen , die ich bevorzuge – user123444555621

+0

Nicht wirklich, Sie könnten nur über die Text-Knoten-Daten suchen und SplitText() verwenden, um jede gefundene Übereinstimmung aufzuteilen und das obige Span-Element einzufügen. Kein Parsen beteiligt. – bobince