Search code examples
jquerysearchfiltercontainsjquery-filter

How to do a case insensitive search for text within elements using jQuery


I have the following basic layout:

<div id="container">
    <div id="div-a">
        <ul id="ul-1">
            <li id="li-1-1" class="li"></li>
            <li id="li-1-2" class="li"></li>
        </ul>
    </div>
    <div id="div-b">
        <ul id="ul-2">
            <li id="li-2-2" class="li"></li>
        </ul>
    </div>
    <div id="div-c">
        <ul id="ul-3">
            <li id="li-3-1" class="li"></li>
            <li id="li-3-2" class="li"></li>
            <li id="li-3-3" class="li"></li>
            <li id="li-3-4" class="li"></li>
        </ul>
    </div>
</div>

What I'm trying to do is, when an input field gets typed into, it initiates a search of the <li> elements. It does a case insensitive search on all text contained within the <li> elements. The <li> element will contain html such as images links paragraphs etc. When a match is found it returns the <li> ids e.g. li-1-1,li-2-1 etc (whatever is best practice). All this is happening while I type. I plan to get the id's and clone the <li>. But that shouldn't be important at this stage.

So far I have the following:

$('#my-input').keyup(function(e) {
    e.stopImmediatePropagation();
    var keycode = ( e.keyCode ? e.keyCode : e.which );
    if( keycode == 13 ) {
        //Do something
    } else {
        if( $('#my-input').val().length >= 3 ) {

            //code goes here
        }
    }
)}

What is the best way to go about this. I have looked at contains, filter, looping over all .li elements in various ways etc and had no luck so far. Any help would be much appreciated.


Solution

  • How about this?

    The html part is changed for testing purpose:

    <input id="my-input"/>
    <div id="container">
        <div id="div-a">
            <ul id="ul-1">
                <li id="li-1-1" class="li"><p>This is something wonderful</p></li>
                <li id="li-1-2" class="li"><span>Try is  out</span></li>
            </ul>
        </div>
        <div id="div-b">
            <ul id="ul-2">
                <li id="li-2-2" class="li"><a href="javascript: void(0)">This needs to be selected</a></li>
            </ul>
        </div>
        <div id="div-c">
            <ul id="ul-3">
                <li id="li-3-1" class="li">No that wonderful</li>
                <li id="li-3-2" class="li">How is this?</li>
                <li id="li-3-3" class="li">Need to match</li>
                <li id="li-3-4" class="li">No need to match?</li>
            </ul>
        </div>
    </div>
    

    The jQuery/JavaScript

    $("document").ready(function() {

    $('#my-input').keyup(function(e) {
        e.stopImmediatePropagation();
        var keycode = (e.keyCode ? e.keyCode : e.which);
        if (keycode == 13) {
            //Do something
        } else {
            var matchText = $('#my-input').val();
            if (matchText.length >= 3) {
                var selectedLists = new Array();
                var flagArray = new Array();
                var i = 0;
                $(matchText.split(/\s+/)).each(function() {
                    var textToMatch = $(this)[0];
                    if (textToMatch && textToMatch != "") {
                        $("li").each(function() {
                            if ($(this).html().match(eval("/" + textToMatch + "/ig"))) {
                                if (!flagArray[$(this).attr("id")]) {
                                    selectedLists[i++] = $(this).attr("id"); //For your implementation, I suggest that you store the object, rather than the id so that you can clone it without an iteration
                                    flagArray[$(this).attr("id")] = true;
                                }
                            }
                        });
                    }
                });
                if (selectedLists.length > 0) {
                    alert(selectedLists);
                }
            }
        }
    });
    

    });