Question

I have this piece of html code:

<p><span>h</span><span>o</span><span>l</span><span>a</span></p>

And I'm using the jQuery on it to replace all the spans:

$('p span').each(function(){
   $(this).replaceWith($(this).text());     
});

When I look into my DOM I see the script created 4 text nodes, for each letter one. How can I prevent this from happening? I only want 1 text node!

Note: the given example is very very simplified. I'm actually doing it on:

<p>This is an <b>example</b>: <span>h</span><span>o</span><span>l</span><span>a</span>!</p>

That should look like:

<p>{text}This is an {/text}<b>{text}example{/text}</b>{text}: hola!{/text}</p>

{text} is a DOM-text node :-)

Was it helpful?

Solution

One thing you could do is at the end, call the native normalize() method:

$('p').find('span').each(function(){
   $(this).replaceWith($(this).text());     
}).end()[0].normalize();

EDIT: I was previously using parent()(docs) to traverse up from the <span> elements, but they were removed from the DOM, so they no longer had a parent.

Instead now I first select the <p>, then find()(docs) the <span> elements. This way I can use end()(docs) to get back to the <p>, and call .normalize().

If there are several <p> elements, you'll want to do another loop.

$('p').find('span').each(function(){
   $(this).replaceWith($(this).text());     
}).end().each(function() {
    this.normalize();
});

You could also pass a function as a parameter to replaceWith()(docs) which returns the text of each element.

$('p').find('span').replaceWith(function(i,el){ 
    return $.text([this]);
}).end().each(function() {
    this.normalize();
});

OTHER TIPS

Perhaps you really want this?

$('p').text(function (i, txt) {
    return txt;
});

In action: http://jsfiddle.net/2qNGY/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top