66

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.

Phil
  • 1,288
  • 1
  • 10
  • 19
Nerudo
  • 902
  • 1
  • 7
  • 11
  • It is not a issue (if you meant that it returns the first div) and for your information you write an input like this: `` – noob Jan 05 '12 at 17:32
  • 4
    possible duplicate of http://stackoverflow.com/questions/187537/is-there-a-case-insensitive-jquery-contains-selector and http://stackoverflow.com/questions/2196641/how-do-i-make-jquery-contains-case-insensitive – qiao Jan 05 '12 at 17:34
  • Possible duplicate of http://stackoverflow.com/q/2196641/1114171 – T I Jan 05 '12 at 17:34

4 Answers4

163

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>
Highway of Life
  • 22,803
  • 16
  • 52
  • 80
  • 4
    I think you should create a separate selector for this rather then overriding the default one. – Stefan Jan 05 '12 at 18:10
  • you get my last upvote (though I'd recommend naming it containsInsensitive so you don't go overwriting built-in stuff) – Adam Rackis Jan 05 '12 at 18:21
  • won't m be a string with all of `:contains(foo)` that you'd have to strip that out manually? Do the jQuery docs explain this function anywhere? – Adam Rackis Jan 05 '12 at 18:31
  • Never mind - I guess it passes an array - the link I was looking at was full of crap. Really neat solution. But *is* this documented anywhere? *exactly* how the function to expr works ? – Adam Rackis Jan 05 '12 at 18:34
  • @Stefan I edited/added an option for either creating your own selector or overriding the default. Thanks! – Highway of Life Jan 05 '12 at 18:50
  • Old post, but holy *crap* this is nice. Thanks, man. Wish I had found this a month ago. – Will Jun 13 '13 at 06:20
  • 8
    just in case anyone has trouble with what is `a,i,m` in `function(a,i,m)` like me.. refer this http://jquery-howto.blogspot.in/2009/06/jquery-custom-selectors-with-parameters.html – Abdul Hameed Apr 04 '17 at 09:48
  • 2
    Thanks for the link, @AbdulHameed! Now I get why the m[3]. – Chris Walker Aug 06 '19 at 20:23
  • @AbdulHameed: The link is broken. Can you please add descriptive comments, thank you. – Marshal Nov 05 '20 at 12:59
25

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

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
11

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;
  }
});
Stefan
  • 5,644
  • 4
  • 24
  • 31
1

I don't believe there is a way to do this with a raw selector. The contains selector is case sensitive and there doesn't appear to be a case insensitive version. I think the best approach is to use a filter that manually queries the object

var filt = function (unused) {
  $(this).text().toLowerCase().indexOf(txtSearch.toLowerCase()) !== -1;
};
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    If you like to settle for core functions out of the box only... otherwise, extending jQuery with another non-case-sensitive selector seems pretty nice! – OG Sean Oct 07 '19 at 18:55