JQuery recursively remove empty children

I have a nested set of html tags and I want to remove 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 the gaps with images and text to remain, while others to go.

I need this result after my function :

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

I realized this had to be done recursively with either JavaScript or jQuery with its .children () method, here is my code that I wanted to use, but I cannot figure out 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 removes and leaves empty spaces ... How do I get the result with recursion?

EDITED

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

EDITED 2 times

I found a mistake in the correct answer, but it is small. If I have a 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 this will result in:

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

the previous β€œRight” answer to my question gave the wrong result in <span> <br> Some text</span> . Other answers were incorrect after testing a bit.

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

+8
javascript jquery recursion
source share
6 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:

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

+2
source share

You can try this, without recursion, using each, check also a tag containing text, for example 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 tags such as $(this).has('img, input, iframe').length ==0

+2
source share

This is a very quick and dirty way to solve your problem.

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

That should do it. But it will also delete the image. You need to add a condition so as not to delete the 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; }​ 
+1
source share

You can use the filter function to get the elements you need, rather than trying to find what you don't need .. then clone and add them to the 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.net/wirey00/5jymK/

+1
source share
 $.each($("#mydiv").find("span"),function(index,value){ if($.trim($(value).html())) { $(value).remove(); } }); 

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

 $("#mydiv br").remove(); 
+1
source share

All Articles