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;
}
Related
I am using this (http://coursesweb.net/javascript/convert-bbcode-html-javascript_cs) as my script for parsing BBCode. I have extended the BBCodes that it can process, however I am encountering a problem when a newline immediately follows an opening tag, e.g.
[code]
code....
[/code]
The problem does not occur if the code is 'inline'
[code]code....[/code]`
The regex being used to match what's inside these tags is (.*?) which I know does not match newlines. I have tried ([^\r\n]) to match newlines but this hasn't worked either.
I imagine it's a simple issue but I have little experience with regex so any help would be appreciated
EDIT: this is the full list of regex's I am using
var tokens = {
'URL' : '((?:(?:[a-z][a-z\\d+\\-.]*:\\/{2}(?:(?:[a-z0-9\\-._~\\!$&\'*+,;=:#|]+|%[\\dA-F]{2})+|[0-9.]+|\\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\\])(?::\\d*)?(?:\\/(?:[a-z0-9\\-._~\\!$&\'*+,;=:#|]+|%[\\dA-F]{2})*)*(?:\\?(?:[a-z0-9\\-._~\\!$&\'*+,;=:#\\/?|]+|%[\\dA-F]{2})*)?(?:#(?:[a-z0-9\\-._~\\!$&\'*+,;=:#\\/?|]+|%[\\dA-F]{2})*)?)|(?:www\\.(?:[a-z0-9\\-._~\\!$&\'*+,;=:#|]+|%[\\dA-F]{2})+(?::\\d*)?(?:\\/(?:[a-z0-9\\-._~\\!$&\'*+,;=:#|]+|%[\\dA-F]{2})*)*(?:\\?(?:[a-z0-9\\-._~\\!$&\'*+,;=:#\\/?|]+|%[\\dA-F]{2})*)?(?:#(?:[a-z0-9\\-._~\\!$&\'*+,;=:#\\/?|]+|%[\\dA-F]{2})*)?)))',
'LINK' : '([a-z0-9\-\./]+[^"\' ]*)',
'EMAIL' : '((?:[\\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+#(?:(?:(?:(?:(?:[a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(?:\\d{1,3}\.){3}\\d{1,3}(?:\:\\d{1,5})?))',
'TEXT' : '(.*?)',
'SIMPLETEXT' : '([a-zA-Z0-9-+.,_ ]+)',
'INTTEXT' : '([a-zA-Z0-9-+,_. ]+)',
'IDENTIFIER' : '([a-zA-Z0-9-_]+)',
'COLOR' : '([a-z]+|#[0-9abcdef]+)',
'NUMBER' : '([0-9]+)',
'ALL' : '([^\r\n])',
};
EDIT 2: Full JS for matching
var token_match = /{[A-Z_]+[0-9]*}/ig;
var _getRegEx = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
if (nrmatches <= 0) {
return new RegExp(preg_quote(str), 'g'); // no tokens so return the escaped string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
if (tokens[token]) {
// Escape everything before the token
replacement += preg_quote(str.substr(0, str.indexOf(matches[i]))) + tokens[token];
// Remove everything before the end of the token so it can be used
// with the next token. Doing this so that parts can be escaped
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += preg_quote(str);
return new RegExp(replacement, 'gi');
};
var _getTpls = function(str) {
var matches = str.match(token_match);
var nrmatches = matches.length;
var i = 0;
var replacement = '';
var positions = {};
var next_position = 0;
if (nrmatches <= 0) {
return str; // no tokens so return the string
}
for(; i < nrmatches; i += 1) {
// Remove {, } and numbers from the token so it can match the
// keys in tokens
var token = matches[i].replace(/[{}0-9]/g, '');
var position;
// figure out what $# to use ($1, $2)
if (positions[matches[i]]) {
position = positions[matches[i]];
} else {
// token doesn't have a position so increment the next position
// and record this token's position
next_position += 1;
position = next_position;
positions[matches[i]] = position;
}
if (tokens[token]) {
replacement += str.substr(0, str.indexOf(matches[i])) + '$' + position;
str = str.substr(str.indexOf(matches[i]) + matches[i].length);
}
}
replacement += str;
return replacement;
};
This does the trick for me: (updated this one too to avoid confusion)
\[code\]([\s\S]*?)\[\/code\]
See regexpal and enter the following:
[code]
code....
[/code]
[code]code.... [/code]
Update:
Fixed the regex to the following and this works in the Chrome Console for me:
/\[code\]([\s\S]*?)\[\/code\]/g.exec("[code]hello world \n[/code]")
JavaScript does not handle multi-line RegExp matches. Instead you have to use the [\s\S] trick described in this SO answer. Perhaps?
/\[code\][\s\S]*\[code\]/
Also RegExps probably isn't the best choice for parsing syntax. It's is extremely over complicated. I would suggest parsing the string and building an Abstract Syntax Tree then rendering the HTML from that.
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;
How do I pass a parameter to a javascript function with ' included
var name ="Lauren O'Donald";
var htmlAnch='<a onclick="javascript:selectEmployee(1100,"'+name+'");return false;"
href="javascript:void(0);">O'Donald, Lauren</a>';
$(document).append($(htmlAnch));
The javascript function is not executing since the name 'Lauren O'Donald' contains single quote.
How can I add a parameter with ' and prepare dynamic html to make it work?
Here is the dynamic code to generate
var rows = new StringBuffer();
$(data).each(function(index) {
rows.append(String.format('<tr><td><a href="No.aspx"
onclick="javascript:selectEmployee({3},\"{1} {2}\");return
false;">{0}</a></td></tr>',
String.format("{0}, {1}", this.Surname, this.FirstName),
this.Surname,
this.FirstName,
this.Id
));
});
You can escape quotes/characters by prepending \ to it:
var string = 'my string with "double quotes" and \'single quotes\'';
var string = "my string with 'single quotes' and \"double quotes\"";
// ^ ^
Using a dynamic string:
var foo = "bar with 'quotes'";
var string = 'my string with "double quotes" and ' + foo.replace(/'/g, "\\'");
//my string with "double quotes" and bar with \'quotes\'
You can escape it using \:
var htmlAnch='<a onclick="javascript:selectEmployee(1100,\'Lauren O\'Donald\');return false;"
href="javascript:void(0);">O\'Donald, Lauren</a>';
However as you've tagged this question with jQuery,a better solution is to hook up an event to the element and use data-* attributes to store the relevant information, which will avoid the use of ugly onX attributes. Try this:
var $htmlAnch = $('<a />' {
text: "O'Donald, Lauren" ,
data-id: 1100,
data-name: "Lauren O'Donald"
}).click(function(e) {
e.preventDefault();
selectEmployee($(this).data('id'), $(this).data('name'));
});
$(document).append($htmlAnch);
Write your own function to return a escaped string. Demo
Pass your string as argument to this function and you will get escaped string. You can also add more characters to blocklist if you want to escape some more characters
function remove_quotes(values1)
{
var values = values1.toString();
var str = "";
var blockList = ['"','\'','\\']; // This is the list of key words to be escaped
var flag = 0;
for(var i = 0;i<values.length;i++)
{
for(var j=0;j<blockList.length;j++)
{
if(values[i] == blockList[j])
{
flag = 1;
break;
}
}
if(flag == 0)
str += values[i];
else
{
str += '\\';
str += values[i];
flag = 0;
}
}
return str;
}
try something like this
var htmlAnch='<a onclick="javascript:selectEmployee(1100,\'Lauren O\'Donald\');return false;" href="javascript:void(0);">O\'Donald, Lauren</a>';
In .aspx file you can do like as below:
<a data-open="editTemplateOverrideModal" onClick="populateUp
dateModal('<%#Server.HtmlEncode(Convert.ToString(DataBinder.Eval(Container.DataItem, "Description")).**Replace("'", "\'")) %>')**">
I am trying to wrap any url that is in some text and turn it into a hyperlink... but I do not want to wrap a url that is already wrapped by a hyperlink.
For example:
Go To Twitter
here is a url http://anotherurl.com
The following code:
function replaceURLWithHTMLLinks(text) {
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp, "<a href='$1'>$1</a>");
}
Gives the following output:
#BIR
http://anotherurl.com
How can I modify the regex to exclude already hyperlinked urls?
Thanks
Answer:
The new method is:
function replaceURLWithHTMLLinks(text) {
var exp = /(?:^|[^"'])((ftp|http|https|file):\/\/[\S]+(\b|$))/gi
return text.replace(exp, " <a href='$1'>$1</a>");
}
The above code functions as required. I modified the regex from a link in the comments because it contained a bug where it would include the full stop, it now excludes any full stops that come after a full url.
Since javascript doesn't seem to support negative look-behind, you will have to trick it by using a replace function.
Capture the href (maybe you should also also consider src) :
function repl(text) {
var exp = /((href|src)=["']|)(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
return text.replace(exp, function() {
return arguments[1] ?
arguments[0] :
"" + arguments[3] + ""
});
}
See the demo
EDIT
A "better" version which will only replace links in actual text nodes:
function repl(node) {
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/i;
var nodes=node.childNodes;
for (var i=0, m=nodes.length; i<m; i++){
var n=nodes[i];
if (n.nodeType==n.TEXT_NODE) {
var g=n.textContent.match(exp);
while(g) {
var idx=n.textContent.indexOf(g[0]);
var pre=n.textContent.substring(0,idx);
var t=document.createTextNode(pre);
var a=document.createElement("a");
a.href=g[0];
a.innerText=g[0];
n.textContent = n.textContent.substring(idx+g[0].length);
n.parentElement.insertBefore(t,n);
n.parentElement.insertBefore(a,n);
g=n.textContent.match(exp);
}
}
else {
repl(n);
}
}
}
var r=repl(document.getElementById("t"))
See the demo
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, "\\$&");
}