Multi-list Filter

by HugeHugh

HTML

Filter <input type="text" id="article-filter">
<ul id="article-list">
    <li><h2>Troops</h2>
    <ul>
        <li><a href="#">Archer</a></li>
        <li><a href="#">Wizard</a></li>
        <li><a href="#">Barbarian</a></li>
        <li><a href="#">Dragon</a></li>
    </ul></li>
    <li><h2>Spells</h2>
    <ul>
        <li><a href="#">Lightning</a></li>
        <li><a href="#">Heal</a></li>
        <li><a href="#">Rage</a></li>
        <li><a href="#">Freeze</a></li>
    </ul></li>
    <li><h2>Defenses</h2>
    <ul>
        <li><a href="#">Mortar</a></li>
        <li><a href="#">Inferno</a></li>
        <li><a href="#">X-bow</a></li>
        <li><a href="#">Cannon</a></li>
    </ul></li>
</ul>
<div id="no-search-results">No search results</div>

CSS

body { font-family: sans-serif }
input { padding: 10px }
#no-search-results { display: none; color: #999; font-style: italic }

JavaScript

function hideShow(condition) {
    return condition ? 'hide' : 'show'
}
$('#article-filter').on('keyup', function() {
    var txt = $(this).val().toLowerCase();    
    $('ul#article-list > li').each(function() {
        var allItems = $('ul li', this);
        var visibleItems = allItems.filter(function(index, elem) {
            return $(elem).text().toLowerCase().indexOf(txt) !== -1;                
        });
        visibleItems.show();
        allItems.not(visibleItems).hide();
        $(this)[hideShow(visibleItems.length === 0)]();
    });
    $('#no-search-results')[hideShow($('ul#article-list li:visible').length > 0)]();
});