2009-04-11 19 views
1

Si vous ouvrez un fichier texte (.txt, .js, .css, ...) dans votre navigateur, il sera enveloppé dans un bon arbre DOM.Comment utiliser innerHTML sur des fichiers txt simples dans Firefox?

Par exemple, ouvrez this .txt file et entrez

javascript:alert(document.documentElement.innerHTML); 

dans votre barre d'adresse. Nice ... chaque navigateur majeur prend en charge la manipulation DOM sur ces fichiers texte enveloppés, ce qui est une bonne chose pour l'écriture de bookmarklets puissants ou user scripts. Cependant, Firefox ne parvient pas à en affectant à tout innerHTML d'un élément. Par exemple,

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

fonctionnera dans tous les navigateurs sauf Firefox.

Y at-il un truc pour contourner ce problème?

(Non, je ne veux pas analyser la chaîne innerHTML manuellement, et non, il ne fonctionne pas avec jQuery non plus.)

+0

DOM a été conçu pour fonctionner avec HTML et XML. Un document texte n'est ni. http://en.wikipedia.org/wiki/Document_Object_Model Un document texte contenant quelques balises HTML aléatoires est toujours un document texte. – Calvin

Répondre

1

Je pense avoir trouvé une solution de travail. Tout d'abord, permettez-moi de donner plus de détails sur la question.

Le problème est le suivant: Firefox crée quelque chose comme

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

mais l'objet document enveloppé ne prend pas en charge la mise en innerHTML correctement. Donc, l'idée de base est de créer un nouvel objet document avec un support complet de innerHTML. Voilà comment cela fonctionne:

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

modifier:

Cette version est meilleure et plus rapide; utilisant XSLTProcessor au lieu de 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

utilisation Greasemonkey

1

Il échoue parce qu'il n'y a pas body - même le fichier que vous avez lié est juste un fichier texte sans un corps (peut-être que vous le regardez dans firebug?). La meilleure chose à faire serait de remplacer un regex puisque vous travaillez avec du texte.

0

Il semble sur un document texte dans Firefox 3, l'attribution innerHTML de tout acte de noeud comme si vous assignez à innerText (avec « < html> < body> < pre> » préfixé).

(depuis les scripts DOM sur un non-XML/document HTML est complètement défini, il est certainement dans les droits de Firefox pour le faire;. Il semble être un hack rapide pour afficher les fichiers texte dans une page HTML)

Donc, vous ne pouvez pas utiliser innerHTML sur Firefox, mais d'autres méthodes DOM fonctionnent:

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

Droite. La chose est, pour que cela fonctionne, vous avez besoin d'un analyseur. Soit - utiliser un écrit en JavaScript (par exemple http://ejohn.org/blog/pure-javascript-html-parser/) qui est lent et volumineux, ou - trouver un moyen d'obtenir l'analyse effectuée par Firefox , ce que je préfère – user123444555621

+0

Pas vraiment, vous pouvez simplement rechercher sur les données de nœud de texte et utiliser splitText() pour séparer chaque correspondance que vous trouvez et insérer l'élément span ci-dessus. Pas d'analyse impliqué. – bobince

Questions connexes