Sergei Basharov
Sergei Basharov

Reputation: 53850

Show headers only for collections that are not empty

I have a couple of lists like this:

<ul>
<li class="list-header">Header</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>

By some rules I hide and show <li> items so sometimes the list has visible <li> and sometimes it has no visible <li> elements at all except the one with list-header class, so <li class="list-header"> is still there. I want to hide that header if there are no <li> visible elements in it under header. Though I want the <ul> still to be visible. How do I do that?

Upvotes: 3

Views: 184

Answers (4)

thecodeparadox
thecodeparadox

Reputation: 87073

try this:

$("ul li:not('.list-header')").each(function(index, val) {
    if ($(this).text() == '') {
        $(this).hide();
    }
});
if (! ($('ul').has("li:visible:not('.list-header')").length)) {
    $('li.list-header').hide();
}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074445

There is no lh element in HTML. References: HTML5, HTML4.01, HTML 3.2. (You've removed the lh from the question.)

Instead, use an li with a class you style as you see fit (or if you're targeting recent-enough browses, no class required; just style li:nth-child(1) or li:first-child), and just don't hide that li (which will keep the ul visible):

<ul>
<li class='header'>Header</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>

Update: I may have misunderstood. If you want to hide the header but keep the ul visible in some way:

A ul with no visible li elements will typically be invisible because it won't have any dimensions. You can override that with CSS, styling the ul to have a specific size (live example):

CSS:

ul.foo {
  width: 5em;
  height: 5em;
  background-color: #eee;
  border: 1px solid #aaa;
}

HTML:

<p><code>ul</code> with no visible children:</p>
<ul class='foo'>
  <li style="display: none">This is hidden</li>
</ul>
<p><code>ul</code> with a visible child:</p>
<ul class='foo'>
  <li>Visible child, note that it wraps</li>
</ul>

And of course you can apply that via jQuery rather than with a static CSS rule:

$("ul.foo").css({
  width: "5em",
  height: "5em",
  backgroundColor: "#eee",
  border: "1px solid #aaa"
});

...so you could do that when you're hiding all of the ul's elements, and undo it when showing at least one of them. After making a change:

var ul = $(/*...selector for the relevant list...*/);
if (ul.find('li:visible')[0]) {
    // There's at least one visible `li` child
    ul.css({/*...styles for when the list is not empty...*/});
}
else {
    // There are no visible `li` children
    ul.css({/*...styles for when the list is empty...*/});
}

...or better yet, add/remove a class.

Upvotes: 0

jensgram
jensgram

Reputation: 31508

What you could do (demo):

$('ul').each(function() {
    $ul = $(this);
    $ul.find('.list-header').toggle($ul.has('li:not(.list-header):visible').length != 0);
});

Basically, what the above does is toggling the .list-header (I've wrapped it in the .each() in order to demo different lists) depending on whether the list .has() :visible li elements that are :not(.list-header).

UPDATE
Now it works. Sorry.

Upvotes: 1

Niklas
Niklas

Reputation: 30002

You could use the :visible and :not selectors to see if there are any elements present when you change the visibility. This example toggles the visibility when clicking the elements, and hides the header if there are no elements present:

$('li:not(".list-header")').click(function(){
    $(this).toggle(10,function(){
       var l = $(this).parent().children('li:visible:not(".list-header")').length  
       if (l>0) $(this).parent().children('li.list-header').show();
        else $(this).parent().children('li.list-header').hide();

     });
});

working example: http://jsfiddle.net/LDG4J/4/

Upvotes: 0

Related Questions