Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery recursively remove empty children

I have a nested set of html tags and i want to delete all tags and their children without text.

Example:

<div id="mydiv">

<span></span>
<span><br></span>
<span> <span><br></span> </span>
<span>   <span><br> <span></span> </span>  </span>

<span> <img src="someimg.jpg" width="100" height="100"> </span>
<span>some text</span>

</div>​

So i want spans with images and text to stay and others leave.

I need that result after my function:

<div id="mydiv">

<span> <img src="someimg.jpg" width="100" height="100" /> </span>
<span>some text</span>
</div>​

I figured out, this is to be done recursively either by JavaScript or jQuery with its' method .children() here is my code i wanted to use, but i can't figure how to build recursion:

 var remove_filter = function () {
            children= $(this).children();

            for (var i = -1, l = children.length; ++i < l;) {
                if ($(children[i]).text() == "") {
                    $(children[i]).remove();
                }
                //may be recursion here
                //else if(){
                //}
            }
            return $(this).text() == "" && $(this).children().length == 0;
}
$('#mydiv').find('span').filter(remove_filter).remove();

This code is broken, it deletes and leaves empty spans... How an i gain my result with recursion?

EDITED

Here is my jsfiddle: http://jsfiddle.net/EGVQH/

EDITED 2 time

I found a bug in the right answer, but it is small. If i have code like this:

<div id="mydiv">
<span> <br> Some text</span>
<span>   <span><br> <span></span> </span>  </span>

<span> <img src="someimg.jpg" width="100" height="100"> </span>
<span>some text</span>

</div>​

I assume it to result in:

<div id="mydiv">
<span> Some text</span>
<span> <img src="someimg.jpg" width="100" height="100" /> </span>
<span>some text</span>
</div>​

previous "Correct" answer to my question was giving wrong result at <span> <br> Some text</span>. Other answers were wrong after testing a bit.

See my JSfiddle: http://jsfiddle.net/EGVQH/2/

like image 279
Feanor Avatar asked Oct 25 '12 13:10

Feanor


1 Answers

function rem(root) {
    var $root = $(root);
    $root.contents().each(function() {
        if (this.nodeType === 1) {
            rem(this);
        }
    });

    if (!$root.is("area,base,col,command,embed,hr,img,input,keygen,link,meta,param,source,track,wbr") && !$root.html().trim().length) {
        $root.remove();
    }
}


rem("#mydiv");​

Using on:

<div id="mydiv">
<span> <br> Some text</span>
<span>   <span><br> <span></span> </span>  </span>

<span> <img src="someimg.jpg" width="100" height="100"> </span>
<span>some text</span>

</div>​

Leaves:

<div id="mydiv">
<span>  Some text</span>


<span> <img src="someimg.jpg" width="100" height="100"> </span>
<span>some text</span>

</div>

http://jsfiddle.net/LEKaL/1/

like image 90
Esailija Avatar answered Oct 13 '22 00:10

Esailija