16

I want to select the text inside the div element and wrap it with a <b> tag. The <b> tag should only wrap to text inside div and not text inside a child element such as the <p> tag in this example.

<div>Testing
    <p>Some more text inside p</p>
    <p>asdasdasdasdasde p</p>
    Test
</div>

I'm able to select the <p> text using the following, but I'm not able to do the same for div. I only want the text of div and not p. For this case it should select and wrap Testing and Test.

var x = $('p')[0].textContent; // this is not working for div.
console.log(x);

JSFiddle

Keavon
  • 6,837
  • 9
  • 51
  • 79
Pinkie
  • 10,126
  • 22
  • 78
  • 124

3 Answers3

45

You can use contents, and filter by node type (3 is for text node):

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

Example: http://jsfiddle.net/nJqKq/8

See also: Node Types, at MDC

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • Thanks guys. Actually, this one is quite verbose compared to the average jQuery line `:)` – Kobi Mar 13 '11 at 19:46
  • For me it not only wraps "Test" in `b` tag but also creates 4-5 additional `b` tags in between all other tags (ie in empty places - probably empty text nodes), so it's not working well. Testing in Chrome Canary - it looks like it adds unwanted white spaces. – Atadj Mar 18 '13 at 18:33
  • It does this for every: `data: "↵"` (printed `contents()` to find this) and it adds carriage return/enter automatically. – Atadj Mar 18 '13 at 18:41
  • Note: `contents` function cannot access cross domain site's iframe –  Aug 07 '14 at 11:19
  • This is perfect! – Joel Apr 13 '18 at 18:34
7

Via pure JS and the DOM:

HTML:

<div id="test">Testing
    <p>Some more text inside p</p>
    <p>asdasdasdasdasde p</p>
    Test
</div>

JS:

getTextNodes(document.getElementById("test"));

function getTextNodes(parent)
{
    var textNodes = [];
    var nodes = parent.childNodes;
    for(var i=0;i<nodes.length;i++)
    {
        if(nodes[i].nodeType === 3)
        {   
            textNodes.push(nodes[i]);
            wrapBold(nodes[i], parent);
        }
    }
}

function wrapBold(node, parent)
{
    //check for whitespace text nodes
    if(node.data.match(/[^\t\n\r ]/))
    {
        var bold = document.createElement("strong");
        parent.insertBefore(bold, node);
        bold.appendChild(node);
    }else
    {
        return false;   
    }
}

http://jsfiddle.net/dnjsY/5/

5

if you dont want to wrap empty nodes use the following:

$('div').contents()
        .filter(function(){ 
            return this.nodeType === 3  && this.data.trim().length > 0
         }).wrap('<b />');
George
  • 4,323
  • 3
  • 30
  • 33