Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert HTML into text node with JavaScript

Tags:

I've got a little text node:

var node 

And I want to wrap a span around every occurrence of "lol".

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

It it prints out "<span>lol<span>" when I want "lol" as a span element.

like image 311
alt Avatar asked May 21 '13 04:05

alt


People also ask

How do I get HTML data in node JS?

Show activity on this post. var http = require("http"); var getGitKey = function (context, callback) { http. get("http://integration.twosmiles.com/status", function(res) { var data = ""; res. on('data', function (chunk) { data += chunk; }); res.

How do you inject text in HTML?

The <ins> tag defines a text that has been inserted into a document. Browsers will usually underline inserted text. Tip: Also look at the <del> tag to markup deleted text.

What does createTextNode do in JavaScript?

createTextNode() Creates a new Text node. This method can be used to escape HTML characters.


2 Answers

The answer presented by Andreas Josas is quite good. However the code had several bugs when the search term appeared several times in the same text node. Here is the solution with those bugs fixed and additionally the insert is factored up into matchText for easier use and understanding. Now only the new tag is constructed in the callback and passed back to matchText by a return.

Updated matchText function with bug fixes:

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

Usage:

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

If you desire to insert anchor (link) tags instead of span tags, change the create element to be "a" instead of "span", add a line to add the href attribute to the tag, and add 'a' to the excludeElements list so that links will not be created inside links.

like image 190
d'Artagnan Evergreen Barbosa Avatar answered Sep 21 '22 10:09

d'Artagnan Evergreen Barbosa


The following article gives you the code to replace text with HTML elements:

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

From the article:

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

Usage:

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

And the explanation:

Essentially, the right way to do it is…

  1. Iterate over all text nodes.
  2. Find the substring in text nodes.
  3. Split it at the offset.
  4. Insert a span element in between the split.
like image 21
Andreas Josas Avatar answered Sep 23 '22 10:09

Andreas Josas