increase Mather
increase Mather

Reputation: 139

Converting a Text NodeType into an Element in Javascript

This is sort of a continuation of an earlier question.

I have some html.

<h3>things that are red:</h3>
<ul>
   <li><a href="html://www.redapples.com">Red Apples</a></li>
   <li><a href="html://www.redmeat.com">Red Meat</a></li>
   <li><a href="html://www.redcar.com">All Red Cars</a></li>
</ul>

I want to use javascript to wrap all of the text elements with a element

The result I am looking for.

<h3>things that are <span class="red">red</span>:</h3>
<ul>
   <li><a href="html://www.redapples.com"><span class="red">Red</span> Apples</a></li>
   <li><a href="html://www.redmeat.com"><span class="red">Red</span> Meat</a></li>
   <li><a href="html://www.redcar.com">All <span class="red">Red</span> Cars</a></li>
</ul>

After a lot of thought I realized that I had to distinguish between text nodeTypes and Element NodeTypes while navigating the DOM. I used some of the feedback from my earlier question, and wrote this little script.

function walkTheDOM(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, func);
        node = node.nextSibling;
    }
}

walkTheDOM(document.body, function (node) {
// Is it a Text node?       
if (node.nodeType === 3) { 
    var text = node.data.trim();
    // Does it have non white-space text content?       
    if (text.length > 0) {              
        node.data = text.replace(/(RED)/gi, '<span class="red">$1</span>'); 
    }
}
});

This does pretty much what I want it to do, except the output is text rather than html. So my question is this, is there an easy way to fix this line

node.data = text.replace(/(RED)/gi, '<span class="red">$1</span>'); 

So that the output is html?

Upvotes: 7

Views: 11312

Answers (3)

coder23846528634
coder23846528634

Reputation: 29

The answer from Amadan is perfect to manipulate (convert from textnode to element for css purposes) for instance some VAT-text-information in the cart-totals section on the cart page in the storefront-child-theme in woocommerce in wordpress. There is no other usual or better way of changing this little piece of textnode that lies within a div containing different textnodes and elementnodes. So i wanted to say thanks for this solution.

Of course, this only works if you use only one language.

var cart_totals = document.querySelector(".cart_totals .shop_table");
if( !!cart_totals ) {
  for( var x = 0; x < cart_totals.childNodes.length; x++ ) {
    if( cart_totals.childNodes[x].nodeType === 3 && 
        cart_totals.childNodes[x].nodeValue.includes( 'inkl. 19 % MwSt.' ) ) {
      var textNode = cart_totals.childNodes[x];
      wrapTextNode( textNode ); /* see function from Amadan above */
    }
  }
}

Upvotes: 0

Amadan
Amadan

Reputation: 198334

What you need to do to make this generic, as I have hinted in the comment, is to create a new element, put the text node into it, then replace the text node with the new element.

function wrapTextNode(textNode) {
    var spanNode = document.createElement('span');
    spanNode.setAttribute('class', 'red');
    var newTextNode = document.createTextNode(textNode.textContent);
    spanNode.appendChild(newTextNode);
    textNode.parentNode.replaceChild(spanNode, textNode);
}

[].forEach.call(document.querySelectorAll('a'), function(el) {
    var textNode = el.childNodes[0];
    wrapTextNode(textNode);
});

EDIT: fiddle

Upvotes: 7

PeterKA
PeterKA

Reputation: 24638

DEMO

$(function() {
    $('li a').html(function(i,html) {
        return html.replace(/(RED)/gi, '<span class="red">$1</span>');
    });
});

Upvotes: 0

Related Questions