Reputation: 17010
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.
Upvotes: 4
Views: 413
Reputation: 14304
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 + '">';
});
})
})();
Upvotes: 4
Reputation: 303381
var map = {
":)" : '<img src="smile.png" title=":)">',
":(" : '<img src="sad.png" title=":(">',
">:(" : '<img src="angry.png" title=">:(">',
};
str.replace( />:\(|:\(|:\)/g, function(found){
return map[found];
});
By using a regex that matches all three at once you are guaranteed not to mis-hit on the alternative; using the function form of replace
allows you to determine what the replacement string is dynamically.
Edit: to dynamically escape any 'special' characters in a literal string to be used in a regex:
RegExp.escape = function(text) {
return text.replace(/[.?*^$()|{}\-\[\]\\]/g, "\\$&");
}
Upvotes: 1