tags:

views:

46

answers:

2

I need to be able to remove all DOM objects that have a class of .remove as long as ALL descendants have a class of either .remove or .removable. Ignoring whitespace. If a text node can be removed it must only contain whitespace (tabs, newlines, spaces).

The html objects with .remove and .removable can be any type of html entity that can recieve a class including input. If a descendant is a textnode that has anything other than whitespace then the ascendant can not be removed.

An object with .remove class can have a descendant with either .remove or .removable.

A descendant can be any number of generations away from the the node in question.

If a node is removed then all children are removed.

(in the examples there is no guarrentee that the node above is body.)

Examples:

Version 1: (ex1 should be removed)

<div id="div1" class="remove">  
  <input id="rad1" class="removable" type="radio" />  
  <img id="img1" src="img.gif" class="remove">  
  <div id="div2" class="removable">  
  </div>  
</div>

Version 2: (ex1 should not be removed as div2 contains a text nod with more than just whitespace but img1 should be removed)

<div id="div1" class="remove">  
  <input id="rad1" class="removable" type="radio" />  
  <img id="img1" src="img.gif" class="remove">  
  <div id="div2" class="removable">some text here  
  </div>  
</div>

Version 3: (div1 should not be removed as img1 is not .remove or .removeable)

<div id="div1" class="remove">  
  <input id="rad1" class="removable" type="radio"  />  
  <img id="img1" src="img.gif">  
  <div id="div2" class="removable">  
  </div>  
</div>
A: 

Possibly somethin like this?

$('div.remove').each(function() {
    var remove = true;
    $(this).children().each(function () {
        if (!$(this).is('.remove')) { remove = false; }
        if ($(this).is('div')) {
            if (!$(this).html().test(/^\s+$/) { remove = false; }
        }
    }
    if (remove == true) { $(this).remove(); }
});
Rob
+1  A: 

This one should work:

$("body > div.remove").not(":has(:not(.remove))").filter(function() {
    return $(this).text().trim().length == 0;
}).remove();

Actually, the credits of the :has(:not(.remove)) selector goes to Nick Craver, but he deleted the answer because he forgot the filter(). I waited for 5 minutes, but since there's no update even though I posted a subtle hint, I just posted one.

Here's a live demo.

BalusC
Very nice, both the answers and the speed of response. Thank you so much.Unfortunately, I wasn't specific enough unfortuantely.I can't assume that the parent is body, I also can't assume that the outer object is a div.The structure was just an example, it will vary significantly from iteration to iteration. The only constant is the requirement to remove all dom objects which have the remove class attached and all children of which also have the remove class (ignoring whitespace).If any child does not have the remove class attached then it and its children are not removed.
mike h
Also I have realised that what I asked above wont actually achieve what I need so I will ammend the question and try to be specific this time. Sorry
mike h