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.
Since its inception, CSS has been a weird language from the case perspective, it is case-insensitive by definition, but in reality it is more of a "hybrid": properties and values are case-insensitive, while selectors are (mostly) case-sensitive.
The CSS Attribute Selector is used to select an element with some specific attribute or attribute value. It is an excellent way to style the HTML elements by grouping them based on some specific attributes and the attribute selector will select those elements with similar attributes.
To use this selector, add a pipe character (|) before the equals sign. For example, li[data-years|="1900"] will select list items with a data-years value of “1900-2000”, but not the list item with a data-years value of “1800-1900”. Value ends with: attribute value ends with the selected term.
Attribute names for HTML elements must exactly match the names of the attributes given in the HTML elements section of this document; that is, attribute names are case-sensitive.
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”...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With