Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript wrapping unwrapped plain text

I have some non-static content on my webpage and I need all unwrapped plain text to be wrapped inside an anchor element with a class, however, I need to maintain the placement of that text.

I've search around on this site and found questions like these which are asking the same question except the text is always in the beginning or the end and the answers always prepend/append the content back into the <div>.

To make the question even more complicated, there are scenarios where the content will be only unwrapped plain text and I'll need to wrap that as well.

My HTML:

<div>
  <a>1</a>
  <a>2</a>
  3
  <a>4</a>
</div>

Sometimes:

<div>
  1
</div>

I've tried all the answers on this page but they all reorder the text.

Any ideas?

like image 912
henryaaron Avatar asked Dec 09 '22 11:12

henryaaron


1 Answers

Iterate over all text nodes of the element:

$('div').contents().filter(function() {
    return this.nodeType === 3;
}).wrap('<a class="awesomeClass"></a>');

DEMO

.contents() retrieves all child nodes of the element, not only element nodes.

The .filter callback discards all nodes that are not text nodes. It works as follows:
Each DOM node has the property nodeType which specifies its type (what surprise). This value is a constant. Element nodes have the value 1 and text nodes have the value 3. .filter will remove all elements from the set for which the callback returns false.

Then each of the text nodes is wrapped in a new element.

I'm having a whitespace problem.

If your HTML looks like

<div>
  1
</div>

then the element has one child node, a text node. The value of the text node does not only consist of the visible character(s), but also of all the whitespace characters, e.g. the line break following the opening tag. Here they are made visible ( is a space, ¬ is a line break):

<div>¬
⋅⋅1¬
</div>

The value of the text node is therefore ¬⋅⋅1¬.

A way to solve this would be to trim the node values, removing trailing and preceding whitespace character:

$('div').contents().filter(function() {
    return this.nodeType === 3;
}).each(function() {
    this.nodeValue = $.trim(this.nodeValue);
}).wrap('<a class="awesomeClass"></a>');

DEMO

like image 188
Felix Kling Avatar answered Dec 11 '22 01:12

Felix Kling