4

I have a function that replaces text smilies etc. with image emoticons

How can I make this case-INsensitive? I have tried using "gi" and "ig" at the replacer, but it does'nt seem to make a difference

var emots = {
    ':)' : 'smile',
    ':-)' : 'smile',
    ';)' : 'wink',
    ';-)' : 'wink',
    ':(' : 'downer',
    ':-(' : 'downer',
    ':D' : 'happy',
    ':-D' : 'happy',
    '(smoke)' : 'smoke',
    '(y)' : 'thumbsup',
    '(b)' : 'beer',
    '(c)' : 'coffee',
    '(cool)' : 'cool',
    '(hehe)' : 'tooth',
    '(haha)' : 'tooth',
    '(lol)' : 'tooth',
    '(pacman)' : 'pacman',
    '(hmm)' : 'sarcastic',
    '(woot)' : 'woot',
    '(pirate)' : 'pirate',
    '(wtf)' : 'wtf'
};

function smile(str){
    var out = str;
        for(k in emots){
            out = out.replace(k,'<img src="/emoticons/'+emots[k]+'.gif" title="'+k+'" />','g');
        }
    return out;
};
mowgli
  • 2,796
  • 3
  • 31
  • 68

3 Answers3

2

Change:

out = out.replace(k,'<img src="/emoticons/'+emots[k]+'.gif" title="'+k+'" />','g');

To:

out = out.replace(new RegExp(k.replace(/[-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), 'ig'), '<img src="/emoticons/'+emots[k]+'.gif" title="'+k+'" />');

Regex escaping function taken from this answer Escape string for use in Javascript regex

Community
  • 1
  • 1
Paul
  • 139,544
  • 27
  • 275
  • 264
  • That inside for(k in emots){) ? – mowgli May 29 '12 at 19:22
  • @mowgli Yes, that's right. It's just taking the flags out of your replace function and converting them into flags for a regex. `escapeRegExp` escapes all special regex characters, although you really only need to escape `(` and `)` with your inputs, it's better to escape everything in case you add new emoticons that use other characters like `:]` or something later on. – Paul May 29 '12 at 19:29
  • Ok ;) But Im thinking... is'nt it wrong to create a function inside a loop? It will be created (or checked and not re-created, I dunno) for each letter I guess – mowgli May 29 '12 at 19:33
  • @mowgli Yes, sorry. Only the one line is in the loop. I didn't make that clear. The function just needs to be in the same scope. Right after your loop would be a good place, or you can get rid of the function altogether. Just replace `escapeRegExp(k)` with `k.replace(/[-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")` – Paul May 29 '12 at 19:36
1

This is a bit trickier than it appears on the surface. Following is a complete solution. It uses only one regex search on the target string, for simplicity and efficiency.

Note that, because it's case insensitive (e.g., (hehe) and (HeHe) are treated the same), :-d is also treated the same as :-D.

var emots = {
    ':)' : 'smile',
    ':-)' : 'smile'
    // Add the rest of your emoticons...
};

// Build the regex that will be used for searches
var emotSearch = [];
for (var p in emots) {
    if (emots.hasOwnProperty(p)) {
        emotSearch.push(p.replace(/[-[{()*+?.\\^$|]/g, '\\$&'));
        if (p !== p.toLowerCase()) {
            emots[p.toLowerCase()] = emots[p];
        }
    }
}
emotSearch = RegExp(emotSearch.join('|'), 'gi');

function smile(str) {
    return str.replace(emotSearch, function ($0) {
        var emot = $0.toLowerCase();
        if (emot in emots) {
            return '<img src="/emoticons/' + emots[emot] + '.gif" title="' + $0 + '" />';
        }
        return $0;
    });
}
slevithan
  • 1,394
  • 13
  • 20
  • Wow a lot of code.. Did not try it. The other shorter answer was perfect. And simple is good ;) – mowgli May 29 '12 at 19:42
  • So be it. Just so you're aware, though, the other answer you're referring to requires a separate search-and-replace for every property of emots, which is significantly less efficient and will become slower as you add more emoticons to search for. It also uses a needlessly verbose regex for escaping regex metacharacters. – slevithan May 29 '12 at 19:56
-2

Or just use .toLowerCase() on the input before you run the check?

Chris Disley
  • 1,286
  • 17
  • 30