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
6 Answers
Reset to default 4function 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/