sanjeev sanjeev - 4 months ago 20
jQuery Question

wrap text with div excluding all children

I have got a problem which I have been trying to solve for past 2 days, but couldn't solve it.

Problem:

I have a HTML as

<div class="string-box">
Text 1 wrap me
<span class="inner-span">Don't search me</span>
<span class="inner-span">Identical text</span>
Identical text
substring match
<span class="inner-span">Don't search substring match</span>
<br>
Finally wrap me
</div>


I want to wrap the content has below

<div class="string-box">
<span> Text 1 wrap me </span>
<span class="inner-span">Don't search me</span>
<span class="inner-span">Identical text</span>
<span>Identical text</span>
<span>substring match</span>
<span class="inner-span">Don't search substring match</span>
<br>
<span>Finally wrap me</span>
</div>


What I have tried

a) I firstly tried to search for string in the html and used string replace to replace the string with wrapped string.
The problem with this approach is that it replaces things in child too..

b) I tried cloning the node and removing all child , but then I am lost with the position of the string.

c) I tried the following code to replace textNode, but I ended up getting HTML

$('.string-box').contents().filter(function(){
return this.nodeType == 3;
}).each(function(){
this.nodeValue = '<span>'+this.nodeValue+'</span>';
})


Thanks in advance for you time & help..

Answer

Your code is close, however the nodeValue cannot contain HTML - hence why it gets encoded in your attempt. Instead you can wrap() the textNode in HTML, like this:

$('.string-box').contents().filter(function() {
    return this.nodeType == 3;
}).each(function() {
    $(this).wrap('<span />');
})

Working example

Update

Here's a fix for occasions where the nodeValue contains a line break, and you want to wrap each line of the node in its own span:

$('.string-box').contents().filter(function() {
    return this.nodeType == 3 && this.nodeValue.trim();
}).each(function() {
    var $spans = this.nodeValue.trim().split(/\r?\n/).map(function(i, v) {
        return $('<span />', { text: i + ' ' });
    });
    $(this).replaceWith($spans);
})

Working example