I need to write a script that reads an HTML file in which there are multiple images declared. The thing is the call to the image is simple and I need to add several instructions. From this code :
<img src="myImage1.jpg" class="image_document">
<img src="myImage2.jpg" class="image_document">
I have to get this :
<a onclick="bloquedefilementchapitres();" href="articles/myImage1.jpg" class="fancybox" rel="images"><img src="articles/myImage1.jpg" class="image_document"></a>
<a onclick="bloquedefilementchapitres();" href="articles/myImage2.jpg" class="fancybox" rel="images"><img src="articles/myImage2.jpg" class="image_document"></a>
So, I tried to use regex to perform this thinking that every image could be detected by regex. Then, every filename could be stored in an array so that I would be able to use the filename to write the link.
Here is what I did :
var recherche_images,
urls = [],
str = theHTMLcode,
rex = /<img[^>]+src="?([^"\s]+)"/g;
while (recherche_images = rex.exec(str)) {
urls.push(recherche_images[1]);
}
for (var v = 0; v < urls.length; v++) {
str = str.replace(/<img src=\"/, '<a onclick=\"bloquedefilementchapitres();\" href=\"articles/' + urls[v] + '\" class=\"fancybox\" rel=\"images-' + idunite + '\"><img src=\"articles/');
}
str = str.replace(/image_document\">/g, 'image_document\"></a>');
If the HTML document only contains one image, it works. If two images are declared, the program loops on the first image and ignores the second image.
Is there any way to tell to the replace function to start at a certain point in the string? Is there any better way to perform this?
There are better ways to achieve this as noted in the comments to your question.
Regarding your code:
There is an issue with the for loop in your code - v++ is executed twice - one in the for loop increment condition and once in the body.
Another issue is the way the .replace() method has been used. Without the \g flag in the regex, the replace() method will just find and replace the first occurrence. Check documentation and this SO question for more details.
Check the code below which uses the /g operator in the regex to find all img matches in the string and each match is passed to a function which returns the replacement string.
What you need is something like this:
var recherche_images,
urls = [],
str = '<img src="myImage1.jpg" class="image_document"><img src="myImage2.jpg" class="image_document">',
rex = /<img[^>]+src="?([^"\s]+)"/g;
while (recherche_images = rex.exec(str)) {
urls.push(recherche_images[1]);
console.log(recherche_images[1]);
}
var idunite = 'test"';
var v = -1;
str = str.replace(/<img src=\"/g, function(mtch) {
v++;
return '<a onclick=\"bloquedefilementchapitres();\" href=\"articles/' + urls[v] + '\" class=\"fancybox\" rel=\"images-' + idunite + '\"><img src=\"articles/';
});
str = str.replace(/image_document\">/g, 'image_document\"></a>');
console.log(str);
JSFiddle.
Pure JS solution:
var x = document.getElementsByClassName('image_document');
for (var i = 0; i < x.length; i++) {
var obj = x[i];
var n = document.createElement('a');
n.href = "articles/" + obj.attributes.src.value;
obj.src = "articles/" + obj.attributes.src.value;
n.className = "fancybox";
n.rel = "images";
n.innerHTML = obj.outerHTML;
n.addEventListener('click', bloquedefilementchapitres);
console.log(n);
obj.parentNode.replaceChild(n, obj);
}
<img src="myImage1.jpg" class="image_document">
<img src="myImage2.jpg" class="image_document">
It seems like you can do this with a single global replace:
For example if your HTML string is in a variable called s then it would be:
s.replace(/<img src="([^\"]+)" class="image_document">/g,
"<a onclick=\"bloquedefilementchapitres();\" href=\"articles/$1\" class=\"fancybox\" rel=\"images\"><img src=\"articles/$1\" class=\"image_document\"></a>");
That seems to work for me ok in the console for a string with one or many img tags. Apologies if I'm missing additional complexity/requirements.
Related
I have string that is stored in a variable in this form :
var c = "<p>Let's try with single inputs : *[]*</p>"
I can easily split and convert the *[]* into <span> using this method [a]:
var res = c.split("*[]*");
if(res.length > 1){
var strContent = res[0];
var inptSoal = ' <span id="content-input" class="al question mb-0">[ ]</span> ';
strContent += inptSoal;
strContent += res[1];
c = strContent;
} return c;
But now, let's say that i have this form of string [b] :
var c = "<p>Let's try with 2 inputs : *[Input 1]* and *[Input 2]*</p>"
How can i split (and convert) every *[ and ]* (that has strings inside of it) into HTML <span> element? Thanks in advance
EDIT
To make it clearer, using the method i write above ([a]) it will return this in my website :
What i want to do is to return the same result if the condition is like the second form ([b]) i mentioned above. How can i achieve this?
SOLVED ✅
Every answers here solved my problem. The first answer here was Ofek's answer. It works well, what i need to do to achieve the result i want is only to change the "<span>" + input + "</span>" inside the replace() function into :
"<span id='content-input' class='al question mb-0'>" + input + "</span>" to make the span element has the CSS Style like my screenshot above.
Other two answers, sid's answer and Rahul Kumar's answer also works well. But i prefer to choose Rahul Kumar's answer for its simplicity.
Thanks in advance to everyone that answered my questions!
Use regex to match the pattern and pass it to String.replace() method to replace the matched pattern in your string with new string <span>$1</span>. Here $1 indicates the captured group which is a content inside brackets *[...]*.
str = "<p>Let's try with 2 inputs : *[Input 1]* and *[Input 2]*</p>"
const regex = /\*\[(.*?)\]\*/g;
const finalStr = str.replace(regex, "<span>$1</span>");
console.log(finalStr);
You can use this method:
function replaceWithInput(str, replacer) {
var arr = str.split("*[");
for (var i = 1; i < arr.length; i++) {
var index = arr[i].indexOf("]*");
arr[i] = replacer(arr[i].slice(0, index)) + arr[i].slice(index + 2);
}
return arr.join("");
}
you use it like so:
function replace(input) {
return "<span>" + input + "</span>"
}
replaceWithInput("<p>Let's try with 2 inputs : *[Input 1]* and *[Input 2]*</p>", replace);
Using Regex you could do,
let c = "<p>Let's try with 2 inputs : *[Input 1]* and *[Input 2]*</p>";
let newC = c.replace(/\*([[])/g, '<span>');
let newC2 = newC.replace(/\]([*])/g, '</span>');
console.log(newC2);
I swear i tried figuring this out myself all day, but my regex-foo is just not that good.
I'm trying to create a small parser function to convert strings with urls to html coded and tags
I know how complex a regex can be trying to figure out which urls to covert to what from a big string, so what I did is simply prefix the string to covert with a flag to tell the parser how to format it, and post fix it with the ";" char to tell the parser where that particular URL ends. This way the parser has lesser guest work to do resulting in easier to regex-match and faster for execution. I really dont need a generalize match and replace all.
So my formatting is as follows, where "X" is the url string:
For URLs it will be url=X;
For IMAGES it will be img=X;
so anything in between my prefix and post fix must be converted accordingly..
So for example, for images in my document, the string could be:
click this image img=http://example.com/image1.jpg;
and i need that converted to
click this image <a href="http://example.com/image1.jpg" target="_blank">
<img class="img img-responsive" src="http://example.com/image1.jpg"/></a>
I am able to do this easily in PHP buy preg_match() function
preg_match('/\img=(.+?)\;/i', $item_des, $matches)
here's the code block:
I decided to push this routine to the browser instead of the backend (PHP) so i need similar or better JS solution.
Hoping anyone can help here, thanks!
try code below:
var str = "click this image img=http://example.com/image1.jpg;image2 img=http://example.com/image2.jpg;"
var phrases = str.split(';');
var totalRes = '';
phrases.forEach(function(str){
totalRes += processPhrase(str);
});
console.log(totalRes);
function processPhrase(str) {
var img = str.split('img=')
var res = '';
if (img.length > 1) { //img=X
var url = img[1].replace(';', '');
res = img[0] + "<a href='" + url + "' target='_blank'><img src='" + url + "'/></a>";
} else {
var url = str.split('url=');
//Do for url=X here
}
console.info(res);
return res;
}
You can use this regexp /(img|url)=(.+?);/g:
(img|url) : the type, should be grouped so we will know what to do with the value
= : literal "="
(.+?) : a number of characters (use the non-greedy ? so it will match as fewer as possible)
; : literal ";"
Read more about non-greedy regexps here.
Example:
var str = "click this image img=http://i.imgur.com/3wY30O4.jpg?a=123&b=456; and check this URL url=http://google.com/;. Bye!";
// executer is an object that has functions that apply the changes for each type (you can modify the functions for your need)
var executer = {
"url": function(e) {
return '<a target="_blank" href="' + e + '">' + e + '</a>';
},
"img": function(e) {
return '<a target="_blank" href="' + e + '"><img src="' + e + '"/></a>';
}
}
var res = str.replace(/(img|url)=(.+?);/g, function(m, type, value) {
return executer[type](value); // executer[type] will be either executer.url or executer.img, then we pass the value to that function and return its returned value
});
console.log(res);
I managed to write this regular expression for getting the inner html from a td tag,
<td[^>]*>(.*?)<\/td>
It is working fine. Except, neglecting the td tag in the matching. I just want to get the innerHTML, not the outerHTML. you can find a demo for my problem here.
Can anyone help me to get text in between the td tag?
P.S I am manipulating a string here not a html element.
Use DOM even for parsing HTML strings. HTML can be too tricky for a regex to stay effecient.
var s = 'this is a nice day<table><tr><td>aaaa <b>bold</b></td></tr><tr><td>bbbb</td></tr></table> here.';
var doc = document.createDocumentFragment();
var wrapper = document.createElement('myelt');
wrapper.innerHTML = s;
doc.appendChild( wrapper );
arr = [];
var n,walk=document.createTreeWalker(doc,NodeFilter.SHOW_ALL,null,false);
while(n=walk.nextNode())
{
if (n.nodeName.toUpperCase() === "TD") {
arr.push(n.innerHTML);
}
}
// See it works:
console.log(arr); // or...
for (var r = 0; r < arr.length; r++) {
document.getElementById("r").innerHTML += arr[r] + "<br/>";
}
<div id="r"/>
You've actually already have the regex needed. It's just your confusing matches with captures. Your regex matches the outer HTML, but it captures the inner. Just do a match and get the first capture group. Check it out in this fiddle.
Here's the code
var s = '<table cellspacing="0px;" cellpadding="8px;"><tr><td align="right" style="padding-right:8px;line-height:18px;vertical-align:top;"><b>Import job summary</b></td><td align="left" style="max-width:300px;line-height:18px;vertical-align:top;"> 5 entries were imported successfully. 0 entries failed to import. </td></tr></table>',
re = /<td[^>]*>(.*?)<\/td>/g,
m = s.match(re),
inner = ['No match'];
if (m.length>0) {
// You have a capture
inner = m;
}
document.write( 'Inner is:<br>' + inner.join('<br>') );
Regards
I am trying to accomplish a task that would be very simple if there was a way to replace one simple string with another.
I have an HTML source of a page as a string. It contains several internal anchors such as
<a href="#about">, <a href="#contact">, <a href="#top">, <a href="#bottom">, <a href="#who-we-are">, etc.
All of the anchors are stored in an array (['about','contact'],...), and I need to remove every occurance of a string like
href="#whatever"
(where whatever is each time something different) so that the result is
<a>
What I'd do with simple search and replace would be to iterate through my array and replace each occurance of
'href="'+anchorname+'"'
with an empty string. But after many attempts with string.replace() I still have't found the way to accomplish this.
In other words (posted also in the comments):
A much simpler way to put my question would be this:
Suppose my string contains the following three strings
<a href="#contact"> <a href="#what"> <a href="#more">
How to I use Javascript to replace them (but NOT any tag with the same pattern) with <a> ?
All of the anchors are stored in an array (['about','contact'],...), and I need to remove every occurance of a string like href="#whatever" (where whatever is each time something different) so that the result is
for this you could do something like this:
var tets_array = $("a[href^='#']"); // select all a tags having href attr starting with #
Then take the array and modify with what you want.
I don't know if I understand the question but you can try this :
var index = myArray.indexOf('whatever');
myArray[index] = "whatever2"
One specific statement would be as follows:
var mystring = '<a href="#thistag"> <a href="#thattag">';
var repstring = mystring;
var myarray = ['thistag', 'theothertag'];
for (var i = 0; i < myarray.length; i++) {
var reptag = myarray[i];
repstring = repstring.replace('a href="#' + reptag + '"', 'a');
}
Then repstring contains the final string. Note the alternating single and double quote characters which ensure that the double-quotes are in their usual place as part of the HTML text. Obviously you can change reptag (i.e., the content of myarray) to include the # character, at which point you would alter the mystring.replace(...) line to match.
If I understand you correctly then you can replace all of those using regular expressions.
var tagString = '<a href="#contact"> <a href="#what"> <a href="#more">';
// Find every occurrence which starts with '#' and ends with '"'
var regEx = new RegExp('#.*?"', 'g');
// Replace those occurrences with '"' to remove them
tagString = tagString.replace(regEx, '"');
EDIT:
To replace specific tags in an array, you can do the following:
var tags = ['<a href="#a">', '<a href="#b">', '<a href="#c">'];
var tagsToReplace = ['a', 'c'];
for (var i = 0, len = tags.length; i < len; i++) {
var matches = tags[i].match(/#.*"/);
if (matches === null) {
continue;
}
var anchor = matches[0].substr(1).replace('"', ''); // Get only the anchor
if (tagsToReplace.indexOf(anchor) !== -1) {
tags[i] = tags[i].replace('#' + anchor, 'replaced');
}
}
Thanks for all of the suggestions. I tried various variations of them and noticed that some worked in Firefox but not in chrome, which led me to this thread
Why doesn't the javascript replace global flag work in Chrome or IE, and how to I work around it?
Which led me to the solution:
for (var i=0; i < myTags.length ; i++)
{
var find = 'href="#' + myTags[i] + '"';
var regex = new RegExp(find, 'gi');
MyWholeString = MyWholeString.replace(regex, '');
}
I have a URL say
dummy URL
http://www.google.com/?v=as12&&src=test&img=test
Now I want to remove the &src=test& part alone.I know we can use indexof but somehow I could not get the idea of getting the next ampersand(&) and removing that part alone.
Any help.The new URL should look like
http://www.google.com/?v=as12&img=test
What about using this?:
http://jsfiddle.net/RMaNd/8/
var mystring = "http://www.google.com/?v=as12&&src=test&img=test";
mystring = mystring.replace(/&src=.+&/, ""); // Didn't realize it isn't necessary to escape "&"
alert(mystring);
This assumes that "any" character will come after the "=" and before the next "&", but you can always change the . to a character set if you know what it could be - using [ ]
This also assumes that there will be at least 1 character after the "=" but before the "&" - because of the +. But you can change that to * if you think the string could be "src=&img=test"
UPDATE:
Using split might be the correct choice for this problem, but only if the position of src=whatever is still after "&&" but unknown...for example, if it were "&&img=test&src=test". So as long as the "&&" is always there to separate the static part from the part you want to update, you can use something like this:
http://jsfiddle.net/Y7LdG/
var mystring1 = "http://www.google.com/?v=as12&&src=test&img=test";
var mystring2 = "http://www.google.com/?v=as12&&img=test&src=test";
var final1 = removeSrcPair(mystring1);
alert(final1);
var final2 = removeSrcPair(mystring2);
alert(final2);
function replaceSrc(str) {
return str.replace(/src=.*/g, "");
}
function removeSrcPair(orig) {
var the_split = orig.split("&&");
var split_second = the_split[1].split("&");
for (var i = split_second.length-1; i >= 0; i--) {
split_second[i] = replaceSrc(split_second[i]);
if (split_second[i] === "") {
split_second.splice(i, 1);
}
}
var joined = split_second.join("&");
return the_split[0] + "&" + joined;
}
This still assumes a few things - the main split is "&&"...the key is "src", then comes "=", then 0 or more characters...and of course, the key/value pairs are separated by "&". If your problem isn't this broad, then my first answer seems fine. If "src=test" won't always come first after "&&", you'd need to use a more "complex" Regex or this split method.
Something like:
url = "http://www.google.com/?v=as12&&src=test&img=test"
firstPart = url.split('&&')[0];
lastPart = url.split('&&')[1];
lastPart = lastPart.split('&')[1];
newUrl = firstPart+'&'+lastPart;
document.write(newUrl);
Details: Use the split method.
Solution Edited: I changed the below to test that the last query string exists
var url = "http://www.google.com/?v=as12&&src=test&img=test";
var newUrl;
var splitString = url.split('&');
if (splitString.length > 3)
{
newURL = splitString[0] + "&" + splitString[3];
}
else
{
newURL = splitString[0];
}