2013-05-21 8 views
18

Ich habe einen kleinen Textknoten bekam:HTML einfügen in Textknoten mit JavaScript

var node 

Und ich möchte eine Spanne umschlingen jedes Vorkommen von „lol“.

node.nodeValue = node.nodeValue.replace(/lol/, "<span>lol</span>") 

Es druckt es aus, wenn ich "<span>lol<span>""lol" als Element span wollen.

+0

in diesem Fall, dass Sie Repace den Textknoten mit HTML-Inhalt –

+0

@ArunPJohny haben Wie kann ich das tun? – alt

+0

@ JacksonGariety - Sie müssen den Textknoten durch ein neues DOM-Bereichselement und Textknoten ersetzen oder die InnerHTML-Eigenschaft des übergeordneten Elements ändern. Probieren Sie aus, was Sie versuchen. – RobG

Antwort

3

Sie können node müssen die übergeordneten Knoten sein, auf diese Weise einfach innerHTML- verwenden können:

node.innerHTML=node.childNodes[0].nodeValue.replace(/lol/, "<span>lol</span>"); 

Hier node.childNodes[0] dem eigentlichen Textknoten bezieht, und node ist die darin enthaltenen Element.

+6

Seien Sie gewarnt, die ersetzen innerHTML des enthaltenen Knotens ist für untergeordnete Knoten destruktiv, für die Ereignis-Listener über Skripts hinzugefügt wurden. – ccjuju

+0

Das funktioniert nicht für mich (Chrome 50); es gibt keine visuelle Veränderung. Ich kann in der Konsole sehen, dass 'node.innerHTML' sich geändert hat, aber es gibt keine Änderungen an der Benutzeroberfläche. Außerdem enthält 'node.parentNode.innerHTML' die neue Änderung nicht. – Jeff

15

Der folgende Artikel gibt Ihnen den Code Text mit HTML-Elemente zu ersetzen:

http://blog.alexanderdickson.com/javascript-replacing-text

Aus dem Artikel:

var matchText = function(node, regex, callback, excludeElements) { 

    excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']); 
    var child = node.firstChild; 

    do { 
     switch (child.nodeType) { 
     case 1: 
      if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) { 
       continue; 
      } 
      matchText(child, regex, callback, excludeElements); 
      break; 
     case 3: 
      child.data.replace(regex, function(all) { 
       var args = [].slice.call(arguments), 
        offset = args[args.length - 2], 
        newTextNode = child.splitText(offset); 

       newTextNode.data = newTextNode.data.substr(all.length); 
       callback.apply(window, [child].concat(args)); 
       child = newTextNode; 
      }); 
      break; 
     } 
    } while (child = child.nextSibling); 

    return node; 
} 

Verbrauch:

matchText(document.getElementsByTagName("article")[0], new RegExp("\\b" + searchTerm + "\\b", "g"), function(node, match, offset) { 
    var span = document.createElement("span"); 
    span.className = "search-term"; 
    span.textContent = match; 
    node.parentNode.insertBefore(span, node.nextSibling); 
}); 

Und die Erklärung :

Im Wesentlichen ist der richtige Weg, es zu tun ...

  1. Iterate über alle Textknoten.
  2. Suchen Sie die Teilzeichenfolge in Textknoten.
  3. Split es am Offset.
  4. Ein Span-Element zwischen die Teilung einfügen.
13

Die Antwort von Andreas Josas ist ziemlich gut. Der Code hatte jedoch mehrere Fehler, wenn der Suchbegriff mehrmals im selben Textknoten erschien. Hier ist die Lösung mit diesen Bugs behoben und zusätzlich ist die Einfügung in matchText für eine einfachere Verwendung und Verständnis berücksichtigt. Jetzt wird nur das neue Tag im Callback erstellt und durch eine Rückgabe an matchText zurückgegeben.

Aktualisiert matchText Funktion mit Fehlerbehebungen:

var matchText = function(node, regex, callback, excludeElements) { 

    excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']); 
    var child = node.firstChild; 

    while (child) { 
     switch (child.nodeType) { 
     case 1: 
      if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) 
       break; 
      matchText(child, regex, callback, excludeElements); 
      break; 
     case 3: 
      var bk = 0; 
      child.data.replace(regex, function(all) { 
       var args = [].slice.call(arguments), 
        offset = args[args.length - 2], 
        newTextNode = child.splitText(offset+bk), tag; 
       bk -= child.data.length + all.length; 

       newTextNode.data = newTextNode.data.substr(all.length); 
       tag = callback.apply(window, [child].concat(args)); 
       child.parentNode.insertBefore(tag, newTextNode); 
       child = newTextNode; 
      }); 
      regex.lastIndex = 0; 
      break; 
     } 

     child = child.nextSibling; 
    } 

    return node; 
}; 

Verbrauch:

matchText(document.getElementsByTagName("article")[0], new RegExp("\\b" + searchTerm + "\\b", "g"), function(node, match, offset) { 
    var span = document.createElement("span"); 
    span.className = "search-term"; 
    span.textContent = match; 
    return span; 
}); 

Wenn Sie Anker einfügen wollen (Link) Tags statt span-Tags, das Element erstellen ändern „a sein "Fügen Sie anstelle von" span "eine Zeile hinzu, um das href-Attribut zum -Tag hinzuzufügen, und fügen Sie der Liste" excludeElements "ein" a "hinzu, damit in den Links keine Links erstellt werden.

+1

Ich habe einen Fix 'regex.lastIndex = 0' hinzugefügt, um den Regex bei der Wiederverwendung zurückzusetzen. Siehe http://stackoverflow.com/questions/1520800/why-regexp-with-global-flag-in-javascript-give-wrong-results – Jeff

2

Nicht zu sagen, das ist eine bessere Antwort, aber ich poste, was ich getan habe für die Vollständigkeit. In meinem Fall habe ich bereits nachgeschlagen oder die Offsets des Textes bestimmt, den ich in einem bestimmten # Textknoten hervorheben wollte. Dies verdeutlicht auch die Schritte.

//node is a #text node, startIndex is the beginning location of the text to highlight, and endIndex is the index of the character just after the text to highlight  

var parentNode = node.parentNode; 

// break the node text into 3 parts: part1 - before the selected text, part2- the text to highlight, and part3 - the text after the highlight 
var s = node.nodeValue; 

// get the text before the highlight 
var part1 = s.substring(0, startIndex); 

// get the text that will be highlighted 
var part2 = s.substring(startIndex, endIndex); 

// get the part after the highlight 
var part3 = s.substring(endIndex); 

// replace the text node with the new nodes 
var textNode = document.createTextNode(part1); 
parentNode.replaceChild(textNode, node); 

// create a span node and add it to the parent immediately after the first text node 
var spanNode = document.createElement("span"); 
spanNode.className = "HighlightedText"; 
parentNode.insertBefore(spanNode, textNode.nextSibling); 

// create a text node for the highlighted text and add it to the span node 
textNode = document.createTextNode(part2); 
spanNode.appendChild(textNode); 

// create a text node for the text after the highlight and add it after the span node 
textNode = document.createTextNode(part3); 
parentNode.insertBefore(textNode, spanNode.nextSibling); 
+0

Danke dafür, es war die beste Antwort für mich – romuleald