最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuery recursively remove empty children - Stack Overflow

programmeradmin5浏览0评论

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: /

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: /

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/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/EGVQH/2/

Share Improve this question edited Oct 25, 2012 at 16:00 I Hate Lazy 48.8k13 gold badges88 silver badges78 bronze badges asked Oct 25, 2012 at 13:42 FeanorFeanor 3,6905 gold badges32 silver badges51 bronze badges 5
  • does it HAVE to be recursive? – Aprillion Commented Oct 25, 2012 at 14:02
  • i think it should be. because nesting level could be up to 10-20 elements, so 20+ "for" circles are bad:) – Feanor Commented Oct 25, 2012 at 14:03
  • 1 if an element doesn't have innerText, none of its children have either, so after testing for images the top parent can be safely removed without checking children.. or what am i missing here? – Aprillion Commented Oct 25, 2012 at 14:05
  • can you show your suggestion in the answer please? you can test it in my fiddle jsfiddle/EGVQH – Feanor Commented Oct 25, 2012 at 14:06
  • So is the only "permitted" element an <img> element? – I Hate Lazy Commented Oct 25, 2012 at 16:02
Add a ment  | 

6 Answers 6

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

    if (!$root.is("area,base,col,mand,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/LEKaL/1/

You can try this, without recursion, using each, check for non text containing tag also, like img

$(function(){
    $('#mydiv').find('span').each(function(){
        var self = $(this);
        if($.trim(self.html())==""){
            self.remove();
        }else if($.trim(self.text())=="" && self.has('img').length ==0)
            self.remove();
    });
});

you can change $(this).has('img').length ==0 for input, iframe or any other non text containing tags like $(this).has('img, input, iframe').length ==0

This is a very quick and dirty way of solving your problem

$('#mydiv span br').remove();
while($('#mydiv span:empty').length > 0){
    $('#mydiv span:empty').remove();
}

This should do it. But this will remove image as well. You need to add condition to not remove image.

removeempty($('#mydiv'));
function removeempty(parentnode){
var children=$(parentnode).children();
for(var i=0;i<children.length;i++){
    var text=$(children[i]).text();
    if($.trim(text).length==0){
        $(children[i]).remove();
    }
    else{
        removeempty($(children[i]));
    }
}
return;
}​
$.each($("#mydiv").find("span"),function(index,value){
   if($.trim($(value).html()))
   {
        $(value).remove();
   }
});

And if you want to remove the breaks, add this before the each statement:

$("#mydiv br").remove();

You can use the filter function to get the elements you need instead of trying to find what you don't need.. then clone and add them to your div

var x = $('#mydiv *').filter(function(){
   // return elements with a children of img or with some text
   return  $(this).children('img').length || $.trim($(this).text()).length ;
}).clone();
$('#mydiv').html(x);

http://jsfiddle/wirey00/5jymK/

发布评论

评论列表(0)

  1. 暂无评论