52

If I have an HTML element <input type="submit" value="Search" /> a css selector needs to be case-sensitive:

input[value='Search'] matches

input[value='search'] does not match

I need a solution where the case-insensitive approach works too. I am using Selenium 2 and Jquery, so answers for both are welcome.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Alp
  • 29,274
  • 27
  • 120
  • 198
  • 1
    Possibly duplicate question? http://stackoverflow.com/questions/3967869/writing-jquery-selector-case-insensitive-version – Tass Apr 15 '11 at 00:41

4 Answers4

82

CSS4 (CSS Selector Level 4) adds support for it:

input[value='search' i]

It's the "i" at the end which does the trick.

Broader adoption started mid-2016: Chrome (since v49), Firefox (from v47?), Opera and some others have it. IE not and Edge since it uses Blink. See “Can I use”...

Robert Siemer
  • 32,405
  • 11
  • 84
  • 94
  • 2
    @Miscreant: See http://stackoverflow.com/questions/27506735/what-does-i-mean-in-a-css-attribute-selector/28050505#28050505 for how to get it working in your browser. – BoltClock Aug 14 '15 at 15:06
  • Chrome added support for this in version 49.0 (released in March 2016). Firefox will add support in version 47.0 (scheduled to be released in June 2016). Source: https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors#Browser_compatibility – Miscreant Mar 03 '16 at 22:11
  • I can confirm it working with plain Chromium Version 49.0.2623.108. – Robert Siemer May 17 '16 at 13:46
40

It now exists in CSS4, see this answer.

Otherwise, for jQuery, you can use...

$(':input[name]').filter(function() {
   return this.value.toLowerCase() == 'search';
});

jsFiddle.

You could also make a custom selector...

$.expr[':'].valueCaseInsensitive = function(node, stackIndex, properties){
     return node.value.toLowerCase() == properties[3];
};

var searchInputs = $(':input:valueCaseInsensitive("Search")');

jsFiddle.

The custom selector is a bit of overkill if doing this once, but if you need to use it many times in your application, it may be a good idea.

Update

Is it possible to have that kind of custom selector for any attribute?

Sure, check out the following example. It's a little convoluted (syntax such as :input[value:toLowerCase="search"] may have been more intuitive), but it works :)

$.expr[':'].attrCaseInsensitive = function(node, stackIndex, properties){
    var args = properties[3].split(',').map(function(arg) {
        return arg.replace(/^\s*["']|["']\s*$/g, '');  
    });
    return $(node).attr(args[0]).toLowerCase() == args[1];
};

var searchInputs = $('input:attrCaseInsensitive(value, "search")');

jsFiddle.

You could probably use eval() to make that string an array, but I find doing it this way more comfortable (and you won't accidentally execute any code you place in your selector).

Instead, I am splitting the string on , delimiter, and then stripping whitespace, ' and " either side of each array member. Note that a , inside a quote won't be treated literally. There is no reason one should be required literally, but you could always code against this possibility. I'll leave that up to you. :)

I don't think map() has the best browser support, so you can explictly iterate over the args array or augment the Array object.

Community
  • 1
  • 1
alex
  • 479,566
  • 201
  • 878
  • 984
  • the custom selector looks exactly like what i need. can you explain what properties[3] is? – Alp Apr 15 '11 at 00:47
  • 1
    @Alp `properties[3]` is the string passed as an argument to the custom selector (the other indexes are assorted meta data). – alex Apr 15 '11 at 00:48
  • @alex is it possible to have that kind of custom selector for any attribute? so that all attributes like name, value, class and so on are case-insensitive? – Alp Apr 15 '11 at 00:52
  • @Alp Yes, but it gets a little messy. Let me make an update :) – alex Apr 15 '11 at 00:53
  • A better return statement is return typeof $(node).attr(args[0]) !== 'undefined' && $(node).attr(args[0]).toLowerCase() == args[1].toLowerCase(); – HamedH May 30 '18 at 10:10
  • @Could be, but I wouldn't use a `typeof` there as it's not necessary. – alex May 30 '18 at 11:26
9
input[value='Search'] matches
input[value='search' i] Also matches in latest browsers

Support: version : Chrome >= 49.0, Firefox (Gecko) >= 47.0, Safari >= 9

ankit
  • 125
  • 1
  • 3
1

You can't do it with selectors alone, try:

$('input').filter(function() {
    return $(this).attr('value').toLowerCase() == 'search';
});
Khez
  • 10,172
  • 2
  • 31
  • 51
  • 1
    You may as well use `val()` there. Also, it appears they want an exact match, not an `indexOf()`. :) – alex Apr 15 '11 at 00:46
  • Very true, but I used `attr()` to show you can use it for other attributes as well. Updated to exact match. – Khez Apr 15 '11 at 00:48