Search code examples
javascriptreplacereplaceall

Javascript: replace all in string issue


I can't figure out how to do a replace all in Javascript.

I'm in a particular situation because I have a replacement map like this:

  :)   ->  <img src="smile.png" title=":) ">
  :(   ->  <img src="sad.png" title=":(">
  >:(  ->  <img src="angry.png" title=">:(">

I'm currently looping on this map, and for each entry, i use string.replace(from, to). The problem is that I cannot replace, for example, >:( because the :( is already replaced by the second entry. And if I reverse the map, then the :( in the title attribute will be replaced causing a real mess.

Hope you understood my situation. I need something like the PHP str_replace with array arguments, that do multiple replacement in one hit.

If it can help, I'm using Mootools.


Solution

  • I'd use analogue of php's preg_replace_callback with regex escaping.

    var putSmiles = (function(){
      // init part
      var smilesMap = {
        ':)': "smile",
        ':(': "sad",
        '>:(': "angry"
      }
      if (!('escape' in RegExp)) {
        RegExp.escape = function(str) {
          return str.replace(/./g, function(m){
            // IE (at least 8) doesn't support .substr(-4), hence MOAR regexes!
            return "\\u" + ("0000" + m.charCodeAt(0).toString(16)).match(/.{4}$/)[0];
          });
        }
      }
      var a = [];
      for (var s in smilesMap) a.push(RegExp.escape(s));
      // sort in such way, if b is substring of a, b should follow a.
      a.sort(function(a,b){ return -a.indexOf(b) }); 
      var re = new RegExp(a.join('|'), 'g');
      // actual function 
      return (function(text) {
        return text.replace(re, function(m){
          return '<img src="' + smilesMap[ m ] + '.png" title="' + m + '">';
        });
      })
    })();