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.
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 + '">';
});
})
})();
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, "\\$&");
}
Related
I have following code to create html links in a plain text. This works fine but the link should not contain .png or .jpg
Any suggestions in adapting the regexp?
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,#?^=%&:\/~+#-]*[\w#?^=%&\/~+#-])?/gi;
return function(text, target) {
var replace = text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>');
return replace
};
You can add anchors and a look-ahead with alternatives to add the restriction:
var urlPattern = /^(?!.*(?:png|jpg)$)(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,#?^=%&:\/~+#-]*[\w#?^=%&\/~+#-])?$/gi;
function repl (text, target) {
var replace = text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>');
return replace;
};
alert(repl("http://some.site.com/new/1.gif", "_blank"));
alert(repl("http://some.site.com/new/1.png", "_blank"));
The crucial part here is ^(?!.*(?:png|jpg)$): it makes the check start at the beginning of a string, and makes sure there is no png nor jpg at the end.
If you pass longer strings with URLs inside, you can use the following regex that assumes you have no spaces in your URLs:
var urlPattern = /(?!\S*(?:png|jpg)(?:$|\s))(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,#?^=%&:\/~+#-]*[\w#?^=%&\/~+#-])?/gi;
I would like to find a performant and elegant solution to this problem :
I need to replace a substring of a string, case insensitively, by a function of what have been replaced.
Example :
var highlight = function(inputString, filterString) {
var regex = new RegExp(filterString, 'gi');
return inputString.replace(regex, '<b>' + filterString + '</b>');
};
highlight('The input', 't');
If your run this in your browser console, you'll get :
"<b>t</b>he inpu<b>t</b>"
My problem is that I'd like to keep the original case of the replaced string. Therefore, the expected result would be :
"<b>T</b>he inpu<b>t</b>"
Any idea ?
Edit: Answer by #georg:
return inputString.replace(regex, '<b>$&</b>');
Just use $& in the replacement, which means "what has been found":
var highlight = function(inputString, filterString) {
var regex = new RegExp(filterString, 'gi');
return inputString.replace(regex, '<b>$&</b>');
};
x = highlight('The input', 't');
document.write("<pre>" + JSON.stringify(x,0,3));
Other $... magic constructs, for the reference:
MDN
$& contains the string matched by the last pattern match.
Please refer
https://msdn.microsoft.com/en-us/library/ie/3k9c4a32%28v=vs.94%29.aspx
for more details.
I have a variable which contains a string expression. This expression have the pattern:
propery_expression operator value
proeprty_expression can look like:
World
World/Name
City/Name
I want to find text after /, and If it exists, and replace with custom text. How can I do this?
With a regex, for example this one :
yourString.replace(/\/\S+/, '/the new stuff...');
In the console :
> var cityName = 'Djakarta';
> var line = 'World/Name Something SomethingElse';
> line.replace(/\/\S+/, '/' + cityName);
"World/Djakarta Something SomethingElse"
You can use this to do complex search and replace operations. Details on Mozilla's documentation
You could try this
var the_string = "City/Name";
var word = "New";
var result = the_string.substring(0, the_string.lastIndexOf('/') + 1);
alert(result + word);
You can try this:
var str = 'World';
alert(rep(str));
function rep(str)
{
if(str.indexOf('/')>-1)//present
{
alert(str.substring(str.lastIndexOf('/') + 1,str.length));
var res = str.replace(str.substring(str.lastIndexOf('/') + 1,str.length),'custom_word');
return res;
}
else{
alert(' / not present');
return str;
}
}
DEMO
Note: If text present after / then it replace it with "custom_word".
In addition to Mathias's answer, you could use RegEx together with a function, like so:
var myString;
.
.
.
myString.replace(/\/(\S+)/g, function (found, value) {
// found == "City/NewYork"
// value == "NewYork"
return found + "Altered";
}
This, for example, will change every "x/y" with "x/yAltered"
function assert() {
document.write.apply(document, arguments);
}
var testLink = "google.com";
function makeIntoLink(link) {
if (link.match(/^[a-zA-Z0-9]+(.com)/)) {
link.replace(link, "<a href=\"http://www." + link+ "\">" + link + "<\/a>");
}
return link;
}
assert(makeIntoLink(testLink));
It writes it down but not in link form. Just "google.com" without the link. What could've gone wrong?
A function like link.replace doesn't actually replace stuff inside the string, it actually returns a NEW string with the replacements made. For example:
function replaceText() {
var searchText = ".com";
var link = "google.com";
var newLink = link.replace(searchText, ".co.uk");
alert(link); // Output = "google.com"
alert(newLink); // Output = "google.co.uk"
}
In your situation though, you don't need to use string.replace(...) at all, instead you can just do this:
function makeIntoLink(link) {
if (link.match(/^[a-zA-Z0-9]+(.com)/)) {
//link.replace(link, "<a href=\"http://www." + link+ "\">" + link + "<\/a>"); <-- OLD
link = "<a href=\"http://www." + link+ "\">" + link + "<\/a>"; // <-- NEW
}
return link;
}
link.replace doesn't change the text in-situ, it makes a new string. Trying changing the line from link.replace(link... to link = link.replace(link...
replace returns a version of the string with the replacement made; the string is not replaced in-situ. So link = link.replace... rather than simply link.replace.
As the others have said, replace doesn't change the variable, it just returns a new one. But in this case, you don't really want to replace something, you just want to concatenate some stuff around it.
IMO, you don't need the replace function for that:
function makeIntoLink(link) {
if (link.match(/^[a-zA-Z0-9]+(.com)/)) {
link = '' + link + '';
}
return link;
}
(I've also removed your \" escapes by using different quote characters for the JS string literal and the HTML attributes. This makes it a mite less hard to read, IMHO).
I have an array with:
emoticons = {
':-)' : 'smile1.gif',
':)' : 'smile2.gif',
':D' : 'smile3.gif'
}
then i have a variabile with the text.
var text = 'this is a simple test :)';
and a variable with the url of the website
var url = "http://www.domain.com/";
How to write a function that replace the symbols with their images?
The <img> tag result should be:
<img src="http://www.domain.com/simple2.gif" />
(I have to concatenate the url varible to the name of the image).
THank you very much!
Another approach:
function replaceEmoticons(text) {
var emoticons = {
':-)' : 'smile1.gif',
':)' : 'smile2.gif',
':D' : 'smile3.gif'
}, url = "http://www.domain.com/";
// a simple regex to match the characters used in the emoticons
return text.replace(/[:\-)D]+/g, function (match) {
return typeof emoticons[match] != 'undefined' ?
'<img src="'+url+emoticons[match]+'"/>' :
match;
});
}
replaceEmoticons('this is a simple test :)');
// "this is a simple test <img src="http://www.domain.com/smile2.gif"/>"
Edit: #pepkin88 made a really good suggestion, build the regular expression based on the property names of the emoticons object.
It can be easily done, but we have to escape meta-characters if we want this to work properly.
The escaped patterns are stored on an array, that is later used to build the regular expression using the RegExp constructor, by basically joining all the patterns separated with the | metacharacter.
function replaceEmoticons(text) {
var emoticons = {
':-)' : 'smile1.gif',
':)' : 'smile2.gif',
':D' : 'smile3.gif',
':-|' : 'smile4.gif'
}, url = "http://www.domain.com/", patterns = [],
metachars = /[[\]{}()*+?.\\|^$\-,&#\s]/g;
// build a regex pattern for each defined property
for (var i in emoticons) {
if (emoticons.hasOwnProperty(i)){ // escape metacharacters
patterns.push('('+i.replace(metachars, "\\$&")+')');
}
}
// build the regular expression and replace
return text.replace(new RegExp(patterns.join('|'),'g'), function (match) {
return typeof emoticons[match] != 'undefined' ?
'<img src="'+url+emoticons[match]+'"/>' :
match;
});
}
replaceEmoticons('this is a simple test :-) :-| :D :)');
for ( smile in emoticons )
{
text = text.replace(smile, '<img src="' + url + emoticons[smile] + '" />');
}
Using a regex with an array of find replace elements works well.
var emotes = [
[':\\\)', 'happy.png'],
[':\\\(', 'sad.png']
];
function applyEmotesFormat(body){
for(var i = 0; i < emotes.length; i++){
body = body.replace(new RegExp(emotes[i][0], 'gi'), '<img src="emotes/' + emotes[i][1] + '">');
}
return body;
}