views:

203

answers:

4

I have a definition list and I need to delete all the <dt> tags who doesn't have any <dd> In this particular case: Herramientas, Suplementos, Repuestos, Herramientas and Anti pinchaduras

The list can vary wildly because it's stock dependent (any category <dt> can get empty)

I tried this

$('dt+dt').each(function() {
 $(this).remove();
});

But it deletes "partes" instead of "herramientas" and fails to delete "suplementos" Also tried with :empty but it seems like a dt without a dd isn't considered empty...

There must be a extremely simple and easy solution but my brain refuses to see it :-(

Example list:

<dl>
 <dt>Bicicletas</dt>
  <dd><a href="/bicicletas/">Bicicletas</a> (70)</dd>
 <dt>Accesorios</dt>
  <dd><a href="/accesorios/bocinas/">Bocinas, timbres y cornetas</a> (9)</dd>
  <dd><a href="/accesorios/transporte/">Transporte y protección</a> (1)</dd>
 <dt>Herramientas</dt>
 <dt>Partes</dt>
  <dd><a href="/partes/cubiertas/">Cubiertas</a> (2)</dd>
  <dd><a href="/partes/asientos/">Asientos</a> (5)</dd>
  <dd><a href="/partes/grips/">Puños / grips</a> (1)</dd>
 <dt>Articulos de indumentaria</dt>
  <dd><a href="/indumentaria/jerseys/">Jerseys / Remeras</a> (1)</dd>
  <dd><a href="/indumentaria/cascos/">Cascos</a> (3)</dd>
 <dt>Suplementos</dt>
 <dt>Repuestos</dt>
 <dt>Herramientas</dt>
 <dt>Anti pinchaduras</dt>
</dl>
+2  A: 
$('dt').filter(function(){
                     return !($(this).next().is('dd'));
               }).remove();

See it in action here: http://jsbin.com/isute


This can also work, but is weird, and will not select the last <dt>, so I've added anothe selector:

$('dt + dt').prev().add('dt:last-child').remove();

That is: select all <dt>s that are after another <dt>, select the prev dt, and add the last.


Another option:

var good = $('dd').prev('dt');
$('dt').not(good).remove();

not can take an array, so this works. This can also be written as $('dt').not($('dd').prev('dt')).remove();, but is very ugly.

Kobi
I should add - originally I did `$('dt + :not(dd)').prev()` , so the dt:last-child made more sense - it is last, or it has something that isn't a dd after it.
Kobi
A: 

Try this:

$('dl>dt').each(function() {
    if ($(this).next("dd").length <= 0){
        $(this).remove();
    }
});
James Wiseman
This removes all dts that don’t *contain* a dd. That is, probably all of them. -1
Daniel Cassidy
Fair comment. Have edited accordingly.
James Wiseman
Your first selector is `dl>dt` - you begin with an empty set, there's no hierarchy here :P . See the link I have on my answer? add `/edit` to the end and play with it, you'll see what I mean (that's http://jsbin.com/isute/edit ).
Kobi
Reverted my downvote.
Daniel Cassidy
+2  A: 

Try something like this...

$('dt').each(function() {
    if($(this).next('dd').length == 0){
       $(this.remove();
    }
});
belugabob
A: 

This will work for hidden <dd> as well:

var $dl = $('dl'); // hook this up to your DL

$dl.find('dt').each(function() {
  var $dt = $(this), $next = $dt.nextAll(':visible').slice(0,1);
  // the next visible element is a dt OR there isn't another visible element.
  if ($next.slice(0,1).is('dt') || $next.length == 0)
  {
    $dt.hide();
  } else {
    $dt.show();
  }
});      
gnarf