I need a little help with some regex I have. Basically I have a shout box that only shows text. I would like to replace urls with links and image urls with the image. I've got the basics working, it just when I try to name a link that I have problems, well if there is more than one link... check out the demo.
Named link format {name}:url should become name. The problem I am having is with shout #5 where the regex doesn't split the two urls properly.
HTML
<ul>
<li>Shout #1 and a link to google: http://www.google.com</li>
<li>Shout #2 with an image: http://i201.photobucket.com/albums/aa236/Mottie1/SMRT.jpg</li>
<li>Shout #3 with two links: http://www.google.com and http://www.yahoo.com</li>
<li>Shout #4 with named link: {google}:http://www.google.com</li>
<li>Shout #5 with two named links: {google}:http://www.google.com and {yahoo}:http://www.yahoo.com and {google}:http://www.google.com</li>
</ul>
Script
var rex1 = /(\{(.+)\}:)?(http\:\/\/[\w\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?(?:[\w])+)/g,
rex2 = /(http\:\/\/[\w\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?(?:[\w])+\.(?:jpg|png|gif|jpeg|bmp))/g;
$('ul li').each(function(i){
var shout = $(this);
shout.html(function(i,h){
var p = h.split(rex1),
img = h.match(rex2),
typ = (p[2] !== '') ? '$2' : 'link';
if (img !== null) {
shout.addClass('shoutWithImage')
typ = '<img src="' + img + '" alt="" />';
}
return h.replace(rex1, typ);
});
});
Update: I figured it out thanks to Brad helping me with the regex. In case anyone needs it, here is the updated demo and code (Now works in IE!!):
var rex1 = /(\{(.+?)\}:)?(http:\/\/[\w\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?(?:[\w])+)/g,
rex2 = /(http:\/\/[\w\-\.]+\.[a-zA-Z]{2,3}(?:\/\S*)?(?:[\w])+\.(?:jpg|png|gif|jpeg|bmp))/g;
$('ul li').each(function(i) {
var shout = $(this);
shout.html(function(i, h) {
var txt, url = h.split(' '),
img = h.match(rex2);
if (img !== null) {
shout.addClass('shoutWithImage');
$.each(img, function(i, image) {
h = h.replace(image, '<img src="' + image + '" alt="" />');
});
} else {
$.each(url, function(i, u) {
if (rex1.test(u)) {
txt = u.split(':')[0] || ' ';
if (txt.indexOf('{') >= 0) {
u = u.replace(txt + ':', '');
txt = txt.replace(/[\{\}]/g, '');
} else {
txt = '';
}
url[i] = '' + ((txt == '') ? 'link' : txt) + '';
}
});
h = url.join(' ');
}
return h;
});
});
(\{(.+?)\}:)
you need the ? to make the regex become "ungreedy" and not just find the next brace.
EDIT
However, if you remove the {yahoo}: the second link becomes null too (seems to populate the anchor tag, just no attribute within). This almost seems to be a victim of using a split instead of a replace. I would almost recommend doing a once-over looking for links first, then go back around looking for images (I don't see any harm in off-linking directly to the image, unless that's not a desired result?)
Related
What I want to happen is to have different URLs be provided based of what the array function result is.
Basically, if collectTags is equal to "church" or "concert" it links to A.com else it links to B.com.
Here's the code I currently have:
caption : function( instance, item ) {
var caption, link, collectTags, tags;
caption = $(this).data('caption');
link = 'Download image';
collectTags = $(this).parent().attr("class").split(' ');
tags = $.map(collectTags,function(it){ if(collectTags === "church"){ return ''+ it +''} else{return ''+ it +''};});
return (caption ? caption + '<br />' : '') + link + '<br/>' + tags.slice(1);
}
I'm not sure that I can do it right, but I'll give it a try. Your problem is that you access collectTags again. That is an array, not a string, so you comparing it to a string will always be false. And never to use string concatination that will make your code harder to read & mess.
{
caption: function (instance, item) {
var caption, link, collectTags, tags;
function format(tpl, binding) {
if (typeof binding != 'function') return format(tpl, function (_, name) {
return binding[name];
});
return tpl.replace(/\$(\w+)/g, binding);
}
caption = $(this).data('caption');
link = format('Download image', item);
collectTags = $(this).parent().attr("class").split(' ');
function createTag(it) {
return format("<a href='$site/$it'>$it</a>", {
site: (it == 'church' || it == 'concert') ? 'A.com' : 'B.com',
it: it
});
}
tags = $.map(collectTags, createTag);
return [].concat(caption ? [caption, link] : link).concat(tags).join('<br/>');
}
}
I am developing a website that works in two languages. I need to change URL to include the selected language.
What I exactly need is:
Pick the current URL
Check if the URL contains any language code
Append the code if not exist or change the code to the selected one if exists
For example, there is an URL for English (default):
http://localhost:11767/Home/resultMain?model=1&&type=1
When a user selects Spanish (es) it should be:
http://localhost:11767/es/Home/resultMain?model=1&&type=1
You can parse the URL with the help of an a element then replace the part you want and re-build the URL :
function addReplaceLangCode(url, langCode) {
var a = document.createElement('a');
a.href = document.getElementById('url').value; // or document.location.href;
var paths = a.pathname.split('/');
paths.shift();
if(paths[0].length == 2) {
paths[0] = langCode;
}else{
paths.unshift(langCode);
}
return a.protocol + '//' +
a.host + '/' + paths.join('/') +
(a.search != '' ? a.search : '') +
(a.hash != '' ? a.hash : '');
}
function onClickReplace() {
document.getElementById('result').innerHTML = addReplaceLangCode( document.location.href, 'es');
}
URL : <input type="text" id="url" style="width:400px" value="http://localhost:11767/Home/resultMain?model=1&&type=1"><input type="button" value="Replace" onclick="onClickReplace()"><br />
Result: <span id="result"></span>
I don't know if it is exactly this, what you want. But JavaScript can obtain URL using object "location". Especially location.pathname is useful for you. You can apply reg-exp on location.pathname to check if URL contain /es/ and if yes, then translate website by proper Ajax requests to your backend.
But generally I recommending to use routing of your backend. The best solution in my opinion - use http headers to inform server about preferred language.
https://www.w3.org/International/questions/qa-accept-lang-locales
Based on #Bulnet Vural's answer above, I wrote the following code because I needed to toggle the language path in and out of the url.
var getOtherLanguageLocation = function (currentUrl, languagePath) {
// based on https://stackoverflow.com/a/42176588/1378980
var anchorTag = document.createElement('a');
anchorTag.href = currentUrl;
var paths = anchorTag.pathname.split("/");
// remove all the empty items so we don't get double slash when joining later.
var paths = paths.filter(function (e) { return e !== '' })
// the language will be at index 1 of the paths
if (paths.length > 0 && paths[0].toLowerCase() == languagePath) {
// remove the language prefix
paths.splice(0, 1);
} else {
// add the language prefix
paths.unshift(languagePath);
}
return anchorTag.protocol + '//' +
anchorTag.host + '/' + paths.join('/') +
anchorTag.search + anchorTag.hash;
};
Below given was my javaScript code.
Condition is, If I give a word like hello. the image for a hello should be displayed or if I give facebook, the image for that has to be displayed likewise for many words, the mentioned image has to be displayed.. But here in my code condition gets failed after first time and image is not displaying for the second word.
Help me with the alternate code for the above mentioned problem
var anu = document.getElementById("display");
var a= document.getElementById("final_span").textContent;
console.log(linebreak(interim_transcript));
if(a.search("hello") || a.search("facebook")){
if(linebreak(interim_transcript) == "hello"){
anu.innerHTML="<img src=hello.jpg>";
}
else if(linebreak(interim_transcript) == "facebook"){
anu.innerHTML="<img src=facebook.jpg>";
}
else if(linebreak(interim_transcript) == "hi"){
anu.innerHTML="<img src=hi.jpg>";
}
else if(linebreak(interim_transcript) == "doll"){
anu.innerHTML="<img src=doll.jpg>";
}
If the value returned by linebreak and image name are same you can use
anu.innerHTML = '<img src="' + linebreak(interim_transcript) + '">';
Otherwise you can use a object where you can specify the image name
var obj = {
hello: "hello.jpg",
facebook: 'facebook.jpg',
hi: 'hi.jpg'
}
var anu = document.getElementById("display");
var a = document.getElementById("final_span").textContent;
if (a.search("hello") || a.search("facebook")) {
var lb = linebreak(interim_transcript);
if (obj[lb]) {
anu.innerHTML = '<img src="' + obj[lb] + '">';
}
}
I'm attempting to duplicate the original img tag's functionality in custom img tag that will be added to the pagedown converter.
e.g I'm copy the original behavior:
![image_url][1] [1]: http://lolink.com gives <img src="http://lolink.com">
into a custom one:
?[image_url][1] [1]: http://lolink.com gives <img class="lol" src="http://lolink.com">
Looking at the docs the only way to do this is through using the preblockgamut hook and then adding another "block level structure." I attempted doing this and got an Uncaught Error: Recursive call to converter.makeHtml
here's the code of me messing around with it:
converter.hooks.chain("preBlockGamut", function (text, dosomething) {
return text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, function (whole, inner) {
return "<img src=" + dosomething(inner) + ">";
});
});
I'm not very experienced with hooks and everything so what would I do to fix it? Thanks.
UPDATE: found out that _DoImages runs after prespangamut, will use that instead of preblockgamut
Figured it out! The solution is very clunky and involves editing the source code because I am very bad at regex and the _DoImage() function uses a lot of internal functions only in the source.
solution:
All edits will be made to the markdown.converter file.
do a ctrl+f for the _DoImage function, you will find that it is named in two places, one in the RunSpanGamut and one defining the function. The solution is simple, copy over the DoImage function and related stuff to a new one in order to mimic the original function and edit it to taste.
next to DoImage function add:
function _DoPotatoImages(text) {
text = text.replace(/(\?\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writePotatoImageTag);
text = text.replace(/(\?\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writePotatoImageTag);
return text;
}
function writePotatoImageTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
var whole_match = m1;
var alt_text = m2;
var link_id = m3.toLowerCase();
var url = m4;
var title = m7;
if (!title) title = "";
if (url == "") {
if (link_id == "") {
link_id = alt_text.toLowerCase().replace(/ ?\n/g, " ");
}
url = "#" + link_id;
if (g_urls.get(link_id) != undefined) {
url = g_urls.get(link_id);
if (g_titles.get(link_id) != undefined) {
title = g_titles.get(link_id);
}
}
else {
return whole_match;
}
}
alt_text = escapeCharacters(attributeEncode(alt_text), "*_[]()");
url = escapeCharacters(url, "*_");
var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\"";
title = attributeEncode(title);
title = escapeCharacters(title, "*_");
result += " title=\"" + title + "\"";
result += " class=\"p\" />";
return result;
}
if you look at the difference between the new _DoPotatoImages() function and the original _DoImages(), you will notice I edited the regex to have an escaped question mark \? instead of the normal exclamation mark !
Also notice how the writePotatoImageTag calls g_urls and g_titles which are some of the internal functions that are called.
After that, add your text = _DoPotatoImages(text); to runSpanGamut function (MAKE SURE YOU ADD IT BEFORE THE text = _DoAnchors(text); LINE BECAUSE THAT FUNCTION WILL OVERRIDE IMAGE TAGS) and now you should be able to write ?[image desc](url) along with ![image desc](url)
done.
The full line (not only the regex) in Markdown.Converter.js goes like this:
text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
so check the function writeImageTag. There you can see how the regex matching text is replaced with a full img tag.
You can change the almost-last line before its return from
result += " />";
to
result += ' class="lol" />';
Thanks for the edit to the main post.
I see what you mean now.
It is a bit weird how it uses empty capture groups to specify tags, but if it works, it works.
It looks like you would need to add on an extra () onto the regex string, then specify m8 as a new extra variable to be passed into the function, and then specify it as class = m8; like the other variables at the top of the function.
Then where it says var result =, instead of class =\"p\" you would just put class + title=\"" + .......
I have a <div id="bread"></div> and I am trying to display breadcrumbs where one of the string contains Tab3 ».
Its like Tab1 > Tab2 > Tab3 » > Tab4 except that > is an arrow-right.png image.
I want to remove » or » from Tab3 ».
I want to search if the selected tab has » or » in it and if it does then I want to replace it with "" so that Tab3 » becomes Tab3.
I've tried the following but it doesn't seem to work.
$("document").ready(function() {
var crumbs = $("a.selected");
jQuery.each(crumbs, function() {
if(this != crumbs.get([0])) {
$("#bread").append(" ");
}
$("#bread").append("<img src='<c:url value="/resources/images/arrow-right.png" />' />" + " ");
var crumb = $(this).html();
var slicedCrumb;
if(crumb.indexOf(' » ') != -1) {
slicedCrumb = $(this).html().replace(' » ', '');
$("#bread").append(slicedCrumb);
}
else {
$("#bread").append(crumb);
}
});
});
I also tried to use » at the place of » but that din't seem to work either.
$("document").ready(function() {
var crumbs = $("a.selected");
jQuery.each(crumbs, function() {
if(this != crumbs.get([0])) {
$("#bread").append(" ");
}
$("#bread").append("<img src='<c:url value="/resources/images/arrow-right.png" />' />" + " ");
var crumb = $(this).html();
var slicedCrumb;
if(crumb.indexOf(' » ') != -1) {
slicedCrumb = $(this).html().replace(' » ', '');
$("#bread").append(slicedCrumb);
}
else {
$("#bread").append(crumb);
}
});
});
I've spent quite sometime reading other posts on the given subject but somehow I am not able to get it working. Could someone help me understand what am I missing here? I am using jquery-1.5.js to run this code. Do I need to use the newer version of jquery or any other library as well to get it working?
slicedCrumb = $(this).html().replace(/\»/g, '');
The important part is escaping the » character. Also I added the global (g) flag so that if there are multiple instances that match the regex, they will all be removed.
Here is a demo: http://jsfiddle.net/YXXZs/1/
UPDATE
If you want to check if a character exists before trying to replace it then you can use .match():
var text = $(this).html();
if (text.search(/\»/) > -1) {
slicedCrumb = text.replace(/\»/g, '');
}
Here is a demo: http://jsfiddle.net/YXXZs/4/
Docs for .match(): https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/match
Try using
slicedCrumb = $(this).html().replace('/[&]raquo[;]/ ', '');