Replace all occurrences of string following an array with javascript - javascript

I have a string like:
const content = 'Lorem ipsum dolor {image} sit amet, consectetur adipiscing elit {image}. Sed quis varius erat. Pellentesque in {image} magna feugiat mi imperdiet suscipit. Pellentesque eget lobortis justo. {image} Sed id pretium purus.'
And an array like:
const images = ['https://images.website.com/61ea8cc09233173e0ff27b1b.jpg','https://images.website.com/61ea8cc39233173e0ff27b24.jpg','https://images.website.com/61ea8cc59233173e0ff27b2d.jpg','https://images.website.com/61ea8cc89233173e0ff27b36.jpg']
And I would like to replace first {image} with images[0], second {image} with images[1], , third {image} with images[2]...

This script can be used for this purpose
let s="{image} b {image} c {image}"
let images=['image1','image2','image3']
images.forEach(img=>{s=s.replace('{image}',img)})
console.log(s)

It really depends on what you are trying to do. The simplest approach would be the following. For a more robust approach though, for instance, if you aren't just replacing '{image}' or if the array possibly doesn't have the same number of parameters as the replacements in the strings, etc, you will probably want to use RegEx.
var content = 'Lorem ipsum dolor {image} sit amet, consectetur adipiscing elit {image}. Sed quis varius erat. Pellentesque in {image} magna feugiat mi imperdiet suscipit. Pellentesque eget lobortis justo. {image} Sed id pretium purus.';
const images = ['https://images.website.com/61ea8cc09233173e0ff27b1b.jpg','https://images.website.com/61ea8cc39233173e0ff27b24.jpg','https://images.website.com/61ea8cc59233173e0ff27b2d.jpg','https://images.website.com/61ea8cc89233173e0ff27b36.jpg'];
for (var i = 0, l = images.length; i < l; i++) {
content = content.replace('{image}', images[i]);
}
console.log(content);

You can do as follow:
const content = 'Lorem ipsum dolor {image} sit amet, consectetur adipiscing elit {image}. Sed quis varius erat. Pellentesque in {image} magna feugiat mi imperdiet suscipit. Pellentesque eget lobortis justo. {image} Sed id pretium purus.'
const images = ['https://images.website.com/61ea8cc09233173e0ff27b1b.jpg','https://images.website.com/61ea8cc39233173e0ff27b24.jpg','https://images.website.com/61ea8cc59233173e0ff27b2d.jpg','https://images.website.com/61ea8cc89233173e0ff27b36.jpg']
let result = content
images.forEach((img) => {
result = result.replace('{image}', img)
})
console.log(result);

Use a template literal:
const content = `Lorem ipsum dolor ${image[0]} sit amet, consectetur adipiscing elit ${image[1]}. Sed quis varius erat. Pellentesque in ${image[2]} magna feugiat mi imperdiet suscipit. Pellentesque eget lobortis justo. ${image[3]} Sed id pretium purus.`
Note the use of backticks around the string instead of quotes.

function replaceWithImages(str, images) {
const images_ = [...images].reverse();
return str.replace(/{image}/g, () => images_.pop() || '');
}
The benefit of doing it this way is that you only need to create one new copy of str

Related

Why document.querySelector fails to find class name in Javascript

Just getting started with document.querySelector in JavaScript. Why would
let result = document.querySelector('Lh') return a null. I have tried many permutations with a div as part of the search string but there must be something different about it in a div? Wildcard suggestions...
let result1 = document.querySelector('[class^="Lh(21px)"]')
let result2 = document.querySelector('[class^=".Lh(21px)"]')
let result3 = document.querySelector('[class^="Lh"]')
let result4 = document.querySelector('[class^=".Lh"]')
All return nulls.
<div class="" data-test="quote-mdl" data-yaft-module="tdv2-applet-summary">
<div class="Mb(25px) smartphone_Px(20px)">
<h3 class="Mb(5px)"><span>Summary</span></h3>
<div class="Lh(21px)">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed et magna magna. Praesent in condimentum quam. Phasellus dui ligula,
tincidunt porta fermentum nec. rhoncus id enim. Duis tempor, tellus at
fermentum consectetur, nisl ipsum placerat metus, sed aliquam turpis enim eget erat.
</div>
</div>
</div>
<div class="Lh(21px)">Lorem ipsum dolor ...
The name of your class is Lh(21px) and not Lh, if you want to match any class name that begins with Lh, use the solution provided in this answer:
let result1 = document.querySelector('[class^="Lh"]');
console.log(result1)
<div class="" data-test="quote-mdl" data-yaft-module="tdv2-applet-summary">
<div class="Mb(25px) smartphone_Px(20px)">
<h3 class="Mb(5px)"><span>Summary</span></h3>
<div class="Lh(21px)">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed et magna magna. Praesent in condimentum quam. Phasellus dui ligula,
tincidunt porta fermentum nec. rhoncus id enim. Duis tempor, tellus at
fermentum consectetur, nisl ipsum placerat metus, sed aliquam turpis enim eget erat.
</div>
</div>
</div>
According to MDN:
The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.
Lh is not a valid selector, because is not a tag but a classname. So you should change your code to this:
const divElement = document.querySelector(".Lh\\(21px\\)")
[EDIT]: Add the backslash if you are using the parenthesis

replace method with Regex - unexpected output logging match $& and Group $1

I have a regex I intend to use with the .replace method with the intention of extracting paragraphs from a string and pushing each one to an array.
I was struggling with my getValues function and when I logged both Match and Group1 to the console got some unexpected results.
Here's the code wip:
var mystring = 'Valid prater\nLorem ipsum dolor sit amet, consectetur adipiscing elit. \nProin volutpat facilisis imperdiet. \n Nunc porttito\nMorbi non eros nec arcu condimentum ultrices in ut nunc. \nMaecenas elit tellus, scelerisque ac auctor fermentum, bibendum. '
var paragraphs = [];
var obj = {};
var getValues = function(match,p1) {
console.log('Match: ' + match );
console.log('p1: ' + p1 );
// obj= {};
// obj['paragraph'] = p1;
// paragraphs.push(obj);
};
mystring.replace(/([^\\n][^\\]+)/g, getValues);
https://jsfiddle.net/7293mo7y/
Expected output:
Match: Valid prater
p1: Valid prater
Match: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
p1: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Match: Proin volutpat facilisis imperdiet.
p1: Proin volutpat facilisis imperdiet.
Match: Nunc porttito
p1: Nunc porttito
Match: Morbi non eros nec arcu condimentum ultrices in ut nunc.
p1: Morbi non eros nec arcu condimentum ultrices in ut nunc.
Match: Maecenas elit tellus, scelerisque ac auctor fermentum, bibendum.
p1: Maecenas elit tellus, scelerisque ac auctor fermentum, bibendum.
I'm expecting similar behaviour to this example
Actual output:
Match: Valid prater
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Proin volutpat facilisis imperdiet.
Nunc porttito
Morbi non eros nec arcu condimentum ultrices in ut nunc.
Maecenas elit tellus, scelerisque ac auctor fermentum, bibendum.
p1: Valid prater
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Proin volutpat facilisis imperdiet.
Nunc porttito
Morbi non eros nec arcu condimentum ultrices in ut nunc.
Maecenas elit tellus, scelerisque ac auctor fermentum, bibendum.
Could anyone explain why I'm not getting the expected output when logging match and p1 to the console?
Why is the behaviour different to this example?
What needs to change to get the expected output?
Thanks!
You can just take advantage of MULTILINE flag or m in your regex. That allows you to use anchors ^ and $ to match a full line in each match like this:
var mystring = 'Valid prater\nLorem ipsum dolor sit amet, consectetur adipiscing elit. \nProin volutpat facilisis imperdiet. \n Nunc porttito\nMorbi non eros nec arcu condimentum ultrices in ut nunc. \nMaecenas elit tellus, scelerisque ac auctor fermentum, bibendum. '
var paragraphs = [];
var obj = {};
var getValues = function(match,p1) {
console.log('Match: ' + match);
console.log('p1: ' + p1);
};
mystring.replace(/^(.*)$/mg, getValues);
Updated JS Fiddle

CSS Transitions not working inside parametrized functions

So I got the following code to create a simple fixed red box:
var red_box = document.createElement('div');
red_box.id = 'caixa_apresentacao_texto';
red_box.style.width = "40%";
red_box.style.overflow = "hidden";
red_box.style.backgroundColor = "white";
red_box.style.color = "black";
red_box.style.border = "5px double red";
/* Centralizing */
red_box.style.position = "fixed";
red_box.style.left = "50%";
red_box.style.marginLeft = "-20%"; //Por que a largura é 40%...
red_box.style.transition = "max-height 1s";
red_box.style.display = "none";
red_box.style.zIndex = "99999999999999";
red_box.style.marginTop = "50px";
red_box.style.maxHeight = "0px";
document.documentElement.insertBefore(red_box,document.body);
So, the idea is that, when I pass some text to this box, it enlarges slowly in order to display it. I get this behaviour with the following code:
var timerHeight;
function expandBox(text){
clearInterval(timerHeight);
/* if the box is empty...*/
if(document.querySelector("#red_box").style.maxHeight == "0px"){
document.querySelector("#red_box").style.display = "inline-block";
red_box.innerHTML = text;
/* Call a function that enlarge the maxHeight property , theorically with the transition letting it more beautiful */
var someText = "text";
timerHeight= setTimeout(enlargeBoxHeight(someText),1);
}
}
function enlargeBoxHeight(anyText){
document.querySelector("#red_box").style.maxHeight ="50px";
}
expandBox("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sollicitudin euismod metus, at blandit neque maximus ac. Integer fermentum nulla at nibh suscipit, a placerat est pretium. Morbi varius ornare enim, ac pulvinar elit aliquet in. Nullam non diam in nibh consectetur fringilla id nec enim. Mauris lacinia a augue ac consectetur. Etiam tempor et elit a dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum pulvinar pharetra. Aliquam erat volutpat. Aliquam non diam eget turpis tincidunt venenatis at in est. Duis laoreet nibh ultrices erat faucibus hendrerit.")
You can see the fiddle here.
So, I know that 50px is not a good height, but what matters here is that the transition is not working. You may have noticed that the var someText is useless here; but it does have the purpose to express my doubt. I've tried to take it off of the enlargeBoxHeight call. So the last part of the code now is:
...
timerHeight= setTimeout(enlargeBoxHeight,1);
}
}
function enlargeBoxHeight(){
document.querySelector("#red_box").style.maxHeight ="50px";
}
expandBox("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sollicitudin euismod metus, at blandit neque maximus ac. Integer fermentum nulla at nibh suscipit, a placerat est pretium. Morbi varius ornare enim, ac pulvinar elit aliquet in. Nullam non diam in nibh consectetur fringilla id nec enim. Mauris lacinia a augue ac consectetur. Etiam tempor et elit a dictum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum pulvinar pharetra. Aliquam erat volutpat. Aliquam non diam eget turpis tincidunt venenatis at in est. Duis laoreet nibh ultrices erat faucibus hendrerit.")
And the surprise: the transition works now. Why? What I am missing here?
When you do:
setTimeout(enlargeBoxHeight,1);
Without the parentheses (), you pass the function enlargeBoxHeight to the timeout, without calling it yet. The timeout will call it after 1ms. Which produced expected behavior + transition.
When you do:
timerHeight= setTimeout(enlargeBoxHeight(someText),1);
You pass the result of the function enlargeBoxHeight to the timeout. () part forces javascript to immediately call the function, and process everything before the timeout. So the transition does not work. After the 1ms, javascript handles the result (with is undefined or irrelevant).
If you want to pass a parameter to a timeout, do:
timerHeight= setTimeout(enlargeBoxHeight.bind(someText),1);
Which should work as expected.

Optimizing javascript (innerhtml, insert elements to textnodes)

So I'm making a firefox addon to highlight words and reg. expressions and I'm having some troubles optimizing it.
This was the 1st attempt:
function highlight (searchText, replacement) {
var walker = document.createTreeWalker(document.body);
while(walker.nextNode()){
if(walker.currentNode.nodeType === 3 && searchText.test(walker.currentNode.nodeValue)){
var html = walker.currentNode.data.replace(searchText, replacement);
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
wrap.innerHTML = html;
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
walker.currentNode.parentNode.replaceChild(frag,walker.currentNode);
}
}
}
But the walker.currentNode.parentNode.replaceChild(frag,walker.currentNode); line replaces the current node so the while(walker.nextNode()) stopped working.
I've solved it like this but i was looking for a cleaner solution:
function highlight (searchText, replacement) {
var walker = document.createTreeWalker(document.body);
var nextnode=true;
while(nextnode){
if(walker.currentNode.nodeType === 3 && searchText.test(walker.currentNode.nodeValue)){
//1~2 ms
var html = walker.currentNode.data.replace(searchText, replacement);
//~11-12 ms
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
//~11-12 ms
wrap.innerHTML = html;
//~36-37 ms
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
//73~74 ms
var nodeToReplace=walker.currentNode;
nextnode=walker.nextNode();
nodeToReplace.parentNode.replaceChild(frag,nodeToReplace);
//83~85 ms
}else{
nextnode=walker.nextNode();
}
}
}
Also I'm trying to improve performance so I've made some test to look for the slower parts of the code (I've tested using a 1.64 mb lorem ipsum) so here are my questions:
Is there a faster alternative for the wrap.innerHTML = html; that is adding 25 ms to the code?
I'm pretty sure that this can't be optimized while (wrap.firstChild) {frag.appendChild(wrap.firstChild);} but it adds 37 ms so suggestions are welcome.
Feel free to use this code the snippet is a working example of the code and shows how to use the it.
Edited to show latest changes, you may need to edit the excludes to be less restrictive.
var regexp = /lorem|amet/gi;
highlight (regexp,'<span style="Background-color:#33FF33">$&</span>');
function highlight (searchText, replacement) {
var excludes = 'html,head,style,title,link,script,noscript,object,iframe,canvas,applet';
var wrap = document.createElement('div');
var frag = document.createDocumentFragment();
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
var nextnode=true;
while(nextnode){
if(searchText.test(walker.currentNode.nodeValue)
&& (excludes + ',').indexOf(walker.currentNode.parentNode.nodeName.toLowerCase() + ',') === -1
){
var html = walker.currentNode.data.replace(searchText, replacement);
wrap.innerHTML = html;
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
var nodeToReplace=walker.currentNode;
nextnode=walker.nextNode();
nodeToReplace.parentNode.replaceChild(frag,nodeToReplace);
}else{
nextnode=walker.nextNode();
}
}
}
<h1>HTML Ipsum Presents</h1>
<p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris
placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.</p>
<h2>Header Level 2</h2>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer lorem adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis
elit sit amet quam. Vivamus pretium ornare est.</p>
</blockquote>
<h3>Header Level 3</h3>
<ul>
<li>Lorem ipsum dolor sit amet, consectetuer lorem adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ul>

Wrap unwrapped parts of HTML string with Javascript

I have string in variable (Javascript/jQuery) containing content like this:
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>
Pellentesque aliquet luctus lobortis.
<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>
massa iaculis leo, nec auctor
how i can wrap all unwrapped content in p tags?
So that string looks like:
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>
<p>Pellentesque aliquet luctus lobortis.</p>
<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>
<p>massa iaculis leo, nec auctor</p>
Thank you!
Something like
var str = 'your string';
var div = $('<div />', {html: str});
div.contents().filter(function() {
return this.nodeType === 3;
}).wrap('<p />');
var new_str = div.html();
FIDDLE
Using a new jQuery object to parse the string as HTML, and then filtering out unwrapped textnodes, and wrapping them with paragraphs, and outputting the changed HTML as the new string.
Here's a jQuery-free way to do it using only string methods (no DOM required.)
var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>Pellentesque aliquet luctus lobortis.<p>Morbi a faucibus magna. Donec lacinia, leo eget</p>massa iaculis leo, nec auctor",
unwrapped = text.split(/<p>\b[^>]*<\/p>/g), //regex to split on all p wrapped text
i;
for (i=0; i < unwrapped.length; i++) {
text = text.replace(unwrapped[i], '<p>' + unwrapped[i] + '</p>');
};

Categories

Resources