tkahn
tkahn

Reputation: 1417

How do I hide a parent li-element whose child ul-li elements are all hidden using jQuery?

I have a set of nested ul's that look like this:

<ul id="educationList">
    <li class="category"><p>Media production</p>
       <ul>
          <li class="education" style="display: block;">
             <a href="#">Real time 3D animation</a>
          </li>
          <li class="education" style="display: block;">
             <a href="#">Filming with Steadicam</a>
          </li>
          <li class="education" style="display: block;">
             <a href="#">Sound Effects</a>
          </li>
       </ul>
    </li>
</ul>

The top ul (educationList) holds a list of categories and each category has a sub list (ul) with the educations that sort under this category. A classic nested list structure. In the sample code above I have just one category - in the real code there are a lot of categories.

I have a jQuery filtering function that shows/hides li-elements that have the class "education" (sub list elements). Sometimes this filtering function hides all sub list elements, so the HTML looks like this:

<ul id="educationList">
    <li class="category"><p>Media production</p>
       <ul>
          <li class="education" style="display: none;">
             <a href="#">Real time 3D animation</a>
          </li>
          <li class="education" style="display: none;">
             <a href="#">Filming with Steadicam</a>
          </li>
          <li class="education" style="display: none;">
             <a href="#">Sound Effects</a>
          </li>
       </ul>
    </li>
</ul>

The difference is that all sub list elements now all have the inline style display: none. All of a sudden I have no real use for the parent li with the class "category" since there are no educations under this category.

Now I'm looking for a smart way to find all category list items that have no visible child education list items and simply hide the category list item. I will have to run this function every time that I do any filtering because the filtering will affect the child education list items - some that where visible will be hidden and some that where hidden will become visible again.

Also - I will have a lot of elements so it's an advantage if the code is not too resource hungry. Still, this is not the time to be picky. Any solution will do and I'll have to work on optimizing later.

Thanks in advance! /Thomas Kahn

Upvotes: 1

Views: 4557

Answers (4)

Amby
Amby

Reputation: 462

$("li.category").each(function(){
if($(this).find("li.education").css("display")=="none")
{
$(this).hide();
}
});

Upvotes: 0

Martin Jespersen
Martin Jespersen

Reputation: 26183

This is the simple and convenient jQuery solution that doesn't completely ignore resource usage:

$('li.category').each(function() {
  var $li = $(this);
  if(!$li.find('li:visible').length) {
    $li.hide();
  }
});

If you need performance optimization, you could do this instead, which doesn't have the overhead of the .each:

var categories = $('li.category');
for(var i=0,category;category = categories.eq(i);i++) {
  if(!category.find('li:visible').length) {
    category.hide();
  }
}

EDIT: fixed bug in optimized version

Upvotes: 4

Jamiec
Jamiec

Reputation: 136104

This should be as simple as:

$('li.category:not(:has(li:visible))').hide();

Live example: http://jsfiddle.net/wTKEQ/

If you run it as-is, then the category will be hidden. If you change one or more of the sub-items to display:block, nothing happens.

Upvotes: 5

Eugene msc
Eugene msc

Reputation: 380

$("li.category").each(function(){
   if($(this).find("li:visible").size() == 0)$(this).hide();
});

Upvotes: 2

Related Questions