452

I have the following:

if (referrer.indexOf("Ral") == -1) { ... }

What I like to do is to make Ral case insensitive, so that it can be RAl, rAl, etc. and still match.

Is there a way to say that Ral has to be case-insensitive?

Alexander Abakumov
  • 10,817
  • 10
  • 71
  • 111
Nate Pet
  • 38,422
  • 114
  • 251
  • 393
  • 3
    I think the case insensitive regex is the more elegant solution but everyone should keep in mind the pitfalls of creating a `RegExp` directly from user input. For example a user could enter `*` and an error would be thrown in the `RegExp` constructor. The accepted solution does not have this problem. – pllee Feb 12 '14 at 19:36

14 Answers14

644

Add .toUpperCase() after referrer. This method turns the string into an upper case string. Then, use .indexOf() using RAL instead of Ral.

if (referrer.toUpperCase().indexOf("RAL") === -1) { 

The same can also be achieved using a Regular Expression (especially useful when you want to test against dynamic patterns):

if (!/Ral/i.test(referrer)) {
   //    ^i = Ignore case flag for RegExp
Andrew
  • 3,330
  • 1
  • 33
  • 53
Rob W
  • 315,396
  • 71
  • 752
  • 644
  • 17
    The latter method is more correct; the former will fail for the Turkish I and any other such problematic uppercase/lowercase pairs: http://www.i18nguy.com/unicode/turkish-i18n.html – Domenic Jan 24 '12 at 20:44
  • 28
    For Turkish, it would be better to use `toLocaleLowerCase()` ([ref](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toLocaleLowerCase)) – Mottie Aug 13 '12 at 14:19
  • 2
    the latter doesn't answer the question, it only says if it is there, not get the index of the match. Either the question title is wrong, or the question. – Maslow Aug 30 '13 at 15:09
  • 10
    @Maslow The question's example was about testing case insensivity. If you want to get the index, use the [String's `.search`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search) method: `var index = referrer.search(/Ral/i);` – Rob W Aug 30 '13 at 15:11
  • 7
    The added complication of the dynamic Regular Expression approach is that if the search string, e.g. "Ral", contained Regular Expression special characters, such as $.*? etc., you'd have problems, so you would need to escape the special characters, see Mike Samuel's answer on this post: [endsWith in JavaScript](http://stackoverflow.com/questions/280634/endswith-in-javascript) – zachelrath Jan 13 '14 at 18:26
  • 3
    As pointed out by others elsewhere, it's better to use toUpperCase(). See http://msdn.microsoft.com/en-us/library/bb386042.aspx – Nateowami Sep 28 '14 at 13:20
  • Or you can simply do like this: `if(referrer.toLowerCase().indexOf("Ral".toLowerCase()) === -1) { ` – Mr world wide Dec 07 '17 at 07:48
  • I got `tolowercase is not a function` error (when I used referrer value from input field). This fixed: `if (referrer.toString().toLowerCase().indexOf("ral") === -1) {` – Pradeep Kumar Prabaharan Jan 02 '21 at 14:17
98

Another options is to use the search method as follow:

if (referrer.search(new RegExp("Ral", "i")) == -1) { ...

It looks more elegant then converting the whole string to lower case and it may be more efficient.
With toLowerCase() the code have two pass over the string, one pass is on the entire string to convert it to lower case and another is to look for the desired index.
With RegExp the code have one pass over the string which it looks to match the desired index.

Therefore, on long strings I recommend to use the RegExp version (I guess that on short strings this efficiency comes on the account of creating the RegExp object though)

Kfir Erez
  • 2,672
  • 16
  • 17
  • 2
    This is also quite a bit faster based on my tests: http://jsperf.com/case-insensitive-indexof – Ilan Biala May 23 '15 at 16:25
  • 6
    As of 2018.10.24, toLowerCase wins by a large margin in Chrome. toLowerCase (95,914,378 - ±0.89% - fastest), regex indexOf (269,307 - ±0.87% 100% slower) – nixkuroi Oct 24 '18 at 16:30
21

From ES2016 you can also use slightly better / easier / more elegant method (case-sensitive):

if (referrer.includes("Ral")) { ... }

or (case-insensitive):

if (referrer.toLowerCase().includes(someString.toLowerCase())) { ... }

Here is some comparison of .indexOf() and .includes(): https://dev.to/adroitcoder/includes-vs-indexof-in-javascript

thSoft
  • 19,314
  • 5
  • 82
  • 97
21

Use a RegExp:

if (!/ral/i.test(referrer)) {
    ...
}

Or, use .toLowerCase():

if (referrer.toLowerCase().indexOf("ral") == -1)
gilly3
  • 78,870
  • 23
  • 132
  • 169
  • 1
    +1, this could potentially be more correct by avoiding the "Turkish I problem" and other such pitfalls: http://www.i18nguy.com/unicode/turkish-i18n.html – Domenic Jan 24 '12 at 20:43
10

There are a couple of approaches here.

If you want to perform a case-insensitive check for just this instance, do something like the following.

if (referrer.toLowerCase().indexOf("Ral".toLowerCase()) == -1) {
    ...

Alternatively, if you're performing this check regularly, you can add a new indexOf()-like method to String, but make it case insensitive.

String.prototype.indexOfInsensitive = function (s, b) {
    return this.toLowerCase().indexOf(s.toLowerCase(), b);
}

// Then invoke it
if (referrer.indexOfInsensitive("Ral") == -1) { ...
cheeken
  • 30,439
  • 4
  • 30
  • 41
  • 1
    For modern browsers which support [`defineProperty`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty), I suggest `Object.defineProperty(String.prototype, 'indexOfInsensitive', {value: function(s,b){return this.toLowerCase().indexOf((s+'').toLowerCase(),b);}});`. Two updates: Explicit string conversion using `(s+'')`, and non-enumerable in a loop (`for(var i in '') ... ` does not show `indexOfInsensitive`. – Rob W Jan 24 '12 at 20:52
7

You can try this

str = "Wow its so COOL"
searchStr = "CoOl"

console.log(str.toLowerCase().includes(searchStr.toLowerCase()))
5
if (referrer.toUpperCase().indexOf("RAL") == -1) { ...
Kendall Frey
  • 39,334
  • 18
  • 104
  • 142
  • @Domenic: With all due respect to the Turkish culture, Turkey should *consider* a spelling reform to simplify this aspect. China has had a number of [simplification reforms](https://en.wikipedia.org/wiki/Chinese_Character_Simplification_Scheme), and Turkey has less than 10% China's population, and a much simpler alphabet. It can be done. – Dan Dascalescu May 13 '19 at 02:56
3

It's 2016, and there's no clear way of how to do this? I was hoping for some copypasta. I'll have a go.

Design notes: I wanted to minimize memory usage, and therefore improve speed - so there is no copying/mutating of strings. I assume V8 (and other engines) can optimise this function.

//TODO: Performance testing
String.prototype.naturalIndexOf = function(needle) {
    //TODO: guard conditions here
    
    var haystack = this; //You can replace `haystack` for `this` below but I wan't to make the algorithm more readable for the answer
    var needleIndex = 0;
    var foundAt = 0;
    for (var haystackIndex = 0; haystackIndex < haystack.length; haystackIndex++) {
        var needleCode = needle.charCodeAt(needleIndex);
        if (needleCode >= 65 && needleCode <= 90) needleCode += 32; //ToLower. I could have made this a function, but hopefully inline is faster and terser
        var haystackCode = haystack.charCodeAt(haystackIndex);
        if (haystackCode >= 65 && haystackCode <= 90) haystackCode += 32; //ToLower. I could have made this a function, but hopefully inline is faster and terser
        
        //TODO: code to detect unicode characters and fallback to toLowerCase - when > 128?
        //if (needleCode > 128 || haystackCode > 128) return haystack.toLocaleLowerCase().indexOf(needle.toLocaleLowerCase();
        if (haystackCode !== needleCode)
        {
            foundAt = haystackIndex;
            needleIndex = 0; //Start again
        }
        else
            needleIndex++;
            
        if (needleIndex == needle.length)
            return foundAt;
    }
    
    return -1;
}

My reason for the name:

  • Should have IndexOf in the name
  • Don't add a suffix word - IndexOf refers to the following parameter. So prefix something instead.
  • Don't use "caseInsensitive" prefix would be sooooo long
  • "natural" is a good candidate, because default case sensitive comparisons are not natural to humans in the first place.

Why not...:

  • toLowerCase() - potential repeated calls to toLowerCase on the same string.
  • RegExp - awkward to search with variable. Even the RegExp object is awkward having to escape characters
Todd
  • 14,946
  • 6
  • 42
  • 56
  • 4
    @RolandIllig Ouch. My answer doesn't accommodate other cultures, that's a drawback. I would welcome any insight into broadening support for more cultures, the world is a better place with collaborators. – Todd Apr 10 '18 at 13:19
3

Example for any language:

'My name is Хведор'.toLocaleLowerCase().includes('ХвЕдОр'.toLocaleLowerCase())
alex_1948511
  • 2,529
  • 2
  • 17
  • 19
1

To do a better search use the following code,

var myFav   = "javascript";
var theList = "VB.NET, C#, PHP, Python, JavaScript, and Ruby";

// Check for matches with the plain vanilla indexOf() method:
alert( theList.indexOf( myFav ) );

// Now check for matches in lower-cased strings:
alert( theList.toLowerCase().indexOf( myFav.toLowerCase() ) );

In the first alert(), JavaScript returned "-1" - in other words, indexOf() did not find a match: this is simply because "JavaScript" is in lowercase in the first string, and properly capitalized in the second. To perform case-insensitive searches with indexOf(), you can make both strings either uppercase or lowercase. This means that, as in the second alert(), JavaScript will only check for the occurrence of the string you are looking for, capitalization ignored.

Reference, http://freewebdesigntutorials.com/javaScriptTutorials/jsStringObject/indexOfMethod.htm

Diganta Kumar
  • 3,491
  • 2
  • 24
  • 29
1

If referrer is an array, you can use findIndex()

 if(referrer.findIndex(item => 'ral' === item.toLowerCase()) == -1) {...}
A-Sharabiani
  • 13,270
  • 12
  • 87
  • 109
0

Here's my take:

Script:

var originalText = $("#textContainer").html()
$("#search").on('keyup', function () {
  $("#textContainer").html(originalText)
  var text = $("#textContainer").html()
  var val = $("#search").val()
  if(val=="") return;
  var matches = text.split(val)
  for(var i=0;i<matches.length-1;i++) {
    var ind =  matches[i].indexOf(val)
    var len = val.length
      matches[i] = matches[i] + "<span class='selected'>" + val + "</span>"
  }
  $("#textContainer").html(matches.join(""))

HTML:

<input type="text" id="search">
<div id="textContainer">
lorem ipsum is simply dummy text of the printing and typesetting industry. lorem ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of letraset sheets containing lorem ipsum passages, and more recently with desktop publishing software like Aldus pagemaker including versions of lorem ipsum.</div>

Codepen

Michael Seltenreich
  • 2,376
  • 1
  • 21
  • 47
0

Here are the options as per ES6 in decreasing order of performance

Includes

if (referrer.toLowerCase().includes("Ral".toLowerCase())) { ... }

IndexOf (this sometimes gives similar or better results than Includes)

if (referrer.toLowerCase().indexOf("Ral".toLowerCase()) !== -1) { ... }

Match

if (referrer.match(new RegExp("Ral", 'i'))) { ... }

Benchmark results: https://jsben.ch/IBbnl

VeeK
  • 1,207
  • 12
  • 33
0

It is better~!

if (~referrer.toUpperCase().indexOf("RAL")) { 
    console.log("includes")
}

enter image description here

seunggabi
  • 1,302
  • 7
  • 11