Filtering a list as you type with jQuery

The solution given by Nikolas combined with the one of Marek rise an error if the input text is empty.
The solution below corrects that and works for lists surrounded by an 'a' tag.

The function is also designed to filter elements with words having their first letter uppercased (as for example with names). The filtering is thus ordered. If you type 'An' or 'an' then you will get all the elements in the list starting by those letters (e.g. Anthony will match but Fanny no).

function filter (element,what) {
    var value = $(element).val();
    value = value.toLowerCase().replace(/\b[a-z]/g, function(letter) {
        return letter.toUpperCase();
    });

    if (value == '') {
        $(what+' > a > li').show();
    }
    else {
        $(what + ' > a > li:not(:contains(' + value + '))').hide();
        $(what + ' > a > li:contains(' + value + ')').show();
    }
};

Below is a sample HTML code that works with the script:

<input type="text" onkeyup="filter(this,'theList')" />
<ul id="theList">
    <li><a href="">Tyrone Schlecht</a></li>
    <li><a href="">Javier Ress</a></li>
    <li><a href="">Carlene Tomes</a></li>
    <li><a href="">Neil Aigner</a></li>
    <li><a href="">Nita Schreffler</a></li>
    <li><a href="">Clinton Knuckles</a></li>
    <li><a href="">Eve Kellett</a></li>
    <li><a href="">Jamie Kaspar</a></li>
    <li><a href="">Emilia Hooton</a></li>
    <li><a href="">Kenya Sidney</a></li>
</ul>

Assuming that your ul has an id of theList, the following would be one way of doing it.

<input type="text" onkeyup="filter(this)" />

<script language="javascript" type="text/javascript">
    function filter(element) {
        var value = $(element).val();

        $("#theList > li").each(function() {
            if ($(this).text().search(value) > -1) {
                $(this).show();
            }
            else {
                $(this).hide();
            }
        });
    }
</script>

If you don't wish to have case-sensitive filter then add .toLowerCase() to these lines like so:

var value = $(element).val().toLowerCase();
if ($(this).text().toLowerCase().search(value) > -1)

Alternatively for a more concise version based on what Marek Tihkan posted you could replace the each() loop with the following. Not sure whether this would perform better or worse.

$('#theList > li:not(:contains(' + value + '))').hide(); 
$('#theList > li:contains(' + value + ')').show();

Tags:

Ajax

Jquery