jQuery :contains() selector uppercase and lower case issue

My html looks like this

<input id="txt" value=""></input>

<div class="link-item">jK</div>
<div class="link-item">JFOO</div>

my js

$('#txt').keyup(function(){

    var txtsearch = $('#txt').val();
    var filt = $("div.link-item:contains('" + txtsearch +"')");

    $("div.link-item").css("display", "none")
        .filter(filt)
        .css("display", "block");

});

I'm looking to filter content dynamically on the client side. When I type a capital j, it only returns the second div whereas I want to get all div that contain j whether upper or lower case.


Solution 1:

You can change the .contains filter to be case insensitive or create your own selector.

jQuery.expr[':'].icontains = function(a, i, m) {
  return jQuery(a).text().toUpperCase()
      .indexOf(m[3].toUpperCase()) >= 0;
};

This creates a new selector: icontains (or you could name it insensitive-contains, or whatever suits your fancy). It's usage would be the same as contains: $('div:icontains("Stack")'); would match:

<div>stack</div>
<div>Stack</div>
<div>StAcKOverflow</div>

Or override the existing .contains filter:

jQuery.expr[':'].contains = function(a, i, m) {
  return jQuery(a).text().toUpperCase()
      .indexOf(m[3].toUpperCase()) >= 0;
};

With this in place,

$("div:contains('John')");

would select all three of these elements:

<div>john</div>
<div>John</div>
<div>hey hey JOHN hey hey</div>

Solution 2:

Why not use the filter function, and pass in a function that uses a case insensitive regex?

var filteredDivs = $("div.link-item").filter(function() {
    var reg = new RegExp(txtsearch, "i");
    return reg.test($(this).text());
});

DEMO

Solution 3:

Here is my contribution, hope it helps :)

$('#txt').keyup(function() {
    var query = $(this).val();
    $("div.link-item")
        .hide()
        .filter(':contains("' + query + '")')
        .show();
});

The :contains() selector is case sensitive.

The matching text can appear directly within the selected element, in any of that element's descendants, or a combination thereof. As with attribute value selectors, text inside the parentheses of :contains() can be written as bare words or surrounded by quotation marks. The text must have matching case to be selected.

Also created a demo if someone would like to try it out.

UPDATE

Sorry, must have misread your question.

Found this jQuery expression at http://bugs.jquery.com/ticket/278 to create a new selector that is case insensitive and I updated my demo.

$.extend($.expr[':'], {
  'containsi': function(elem, i, match, array) {
    return (elem.textContent || elem.innerText || '').toLowerCase()
        .indexOf((match[3] || "").toLowerCase()) >= 0;
  }
});