11

I have something like this.

<div id="firstDiv">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</div>

I want to remove 'This is some text' and need the html elements intact.

I tried using something like

$("#firstDiv")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text("");

But it didn't work.

Is there a way to get (and possibly remove, via something like .text("")) just the free text within a tag, and not the text within its child tags?

Thanks very much.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Okky
  • 10,338
  • 15
  • 75
  • 122

4 Answers4

7

Filter out text nodes and remove them:

$('#firstDiv').contents().filter(function() {
    return this.nodeType===3;
}).remove();

FIDDLE

To also filter on the text itself, you can do:

$('#firstDiv').contents().filter(function() {
    return this.nodeType === 3 && this.nodeValue.trim() === 'This is some text';
}).remove();

and to get the text :

var txt = [];

$('#firstDiv').contents().filter(function() {
    if ( this.nodeType === 3 ) txt.push(this.nodeValue);
    return this.nodeType === 3;
}).remove();
adeneo
  • 312,895
  • 29
  • 395
  • 388
2

Check out this fiddle

Suppose you have this html

<parent>
  <child>i want to keep the child</child>
  Some text I want to remove
  <child>i want to keep the child</child>
  <child>i want to keep the child</child>
</parent>

Then you can remove the parent's inner text like this:

var child = $('parent').children('child');
$('parent').html(child);

Check this fiddle for a solution to your html

var child = $('#firstDiv').children('span');
$('#firstDiv').html(child);

PS: Be aware that any event handlers bounded on that div will be lost as you delete and then recreate the elements

MaVRoSCy
  • 17,747
  • 15
  • 82
  • 125
  • 3
    At the same time you're creating all the elements again, so all data, event handlers etc. will be lost. – adeneo Jul 25 '13 at 07:37
2

Why try to force jQuery to do it when it's simpler with vanilla JS:

var div = document.getElementById('firstDiv'),
    i,
    el;

for (i = 0; i< div.childNodes.length; i++) {
    el = div.childNodes[i];
    if (el.nodeType === 3) {
        div.removeChild(el);
    }
}

Fiddle here: http://jsfiddle.net/YPKGQ/

RobH
  • 3,604
  • 1
  • 23
  • 46
  • I wouldn't say it's simpler (if you look at adeneo's `.filter` solution, it's just less code to write), but it's definitely not very difficult either. – Felix Kling Jul 25 '13 at 07:49
  • @FelixKling - That's very true. But it is much simpler than some of the jQuery solutions posted! – RobH Jul 25 '13 at 07:51
0

Check this out, not sure if it does what you want exactly... Note: i only tested it in chrome

http://jsfiddle.net/LgyJ8/

cleartext($('#firstDiv'));

function cleartext(node) {

    var children = $(node).children();
    if(children.length > 0) {

        var newhtml = "";
        children.each(function() {

            cleartext($(this));

            newhtml += $('<div/>').append(this).html();

        });

        $(node).html(newhtml);

    }
}
Lee
  • 10,496
  • 4
  • 37
  • 45
  • The problem with `.html` (and `.innerHTML`) is that the browser as to parse the HTML string and creates new elements from it. That's ok if you are with new elements. But if you converted existing elements to HTML and then set the HTML to "recreate" those elements, you will loose all event handlers and data bound to those elements. – Felix Kling Jul 25 '13 at 07:52
  • Well it's not the perfect solution of course, but since the OP didn't mention binding events to these BEFORE the stripping, i figured it was worthy of a jsfiddle to see if the idea that popped into my head would work. – Lee Jul 25 '13 at 07:55