I have some HTML in my DOM and I want to replace some strings in it, but only if that was not already replaced or that is not a TAG.
All that is based on an Array that contains the string I want to find and the new string I want this to be replace with.
Work in progress: https://jsfiddle.net/u2Lyaab1/23/
UPDATE: The HTML markup is just for simplicity written with ULs in the sample code, BUT it can contain different tags, event different nesting levels
Basically the desiredReplcement
works nice (except that it looks in tags too), but I want that to happen on the DOM, not the new string because I want to maintain any other HTML markup in the DOM.
SNIPPET:
var list = [{
original: 'This is',
new: 'New this is'
},
{
original: 'A list',
new: 'New A list'
},
{
original: 'And I want',
new: 'New And I want'
},
{
original: 'To wrap',
new: 'New To wrap'
},
{
original: 'li',
new: 'bold'
},
{
original: 'This',
new: 'New This'
},
{
original: 'strong',
new: 'bold'
}, {
original: 'This is another random tag',
new: 'This is another random tag that should be bold'
}
];
var div = $('.wrap');
var htmlString = div.html();
var index = 0;
list.forEach(function(item, index) {
console.log(index + ' Should replace: "' + item.original + '" with "' + item.new + '"');
//I know that there is something here, but not sure what
index = htmlString.indexOf(item.original);
var expressionLength = index + item.original.length;
var substring = htmlString.substring(index, expressionLength);
var desiredReplcement = substring.replace(item.original, '<strong>' + item.new + '</strong>');
console.log('index', index);
console.log('substring', substring);
console.log('desiredReplcement', desiredReplcement);
//Current implementation in replace looks in the full div, but I just want to replace in the substring mathced above;
var replacement = '<strong>' + item.new + '</strong>';
var newHTML = div.html().replace(item.original, replacement);
div.html(newHTML);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<ul>
<li>This is</li>
<li>A list</li>
<li>And I want</li>
<li>This should not be bold</li>
<li>To wrap</li>
<li>This</li>
<li>strong</li>
<li>li</li>
</ul>
<span><p><em>This is another random tag</em></p></span>
</div>
Your div
variable is referencing <div class="wrap">...</div>
, therefore your htmlString
value is a group of html tags instead of string.
That is the main reason your code is not working as expected.
And therefore I rewrote your implementation.
var list = [
{
original: 'This is',
new: 'New this is'
},
{
original: 'A list',
new: 'New A list'
},
{
original: 'And I want',
new: 'New And I want'
},
{
original: 'To wrap',
new: 'New To wrap'
},
{
original: 'li',
new: 'bold'
},
{
original: 'This',
new: 'New This'
},
{
original: 'strong',
new: 'bold'
}
];
var div = document.getElementsByClassName('wrap')[0].getElementsByTagName('li'); // Getting all <li> elements within <div class="wrap">
Array.prototype.forEach.call(div, function(li, x){ // Borrowing Array's forEach method to be used on HTMLCollection
list.forEach(function(value, i){ // Looping through list
if (value.original === li.innerHTML) // if list[i]['original'] === li[x].innerHTML
li.innerHTML = '<strong>' + value.new + '</strong>';
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<ul>
<li>This is</li>
<li>A list</li>
<li>And I want</li>
<li>This should not be bold</li>
<li>To wrap</li>
<li>This</li>
<li>strong</li>
<li>li</li>
</ul>
</div>
I don't think that jQuery is necessary here.
First, you want to retrieve your container, which in your case will be the .wrap
div.
var container = document.querySelector('.wrap');
Then you want to create a recursive function that will loop through an array to search and replace the data provided.
function replacement(containers, data){
if(!data || !data.length)
return;
for(let i=0; i<containers.length; i++){
var container = containers[i];
// Trigger the recursion on the childrens of the current container
if(container.children.length)
replacement(container.children, data);
// Perform the replacement on the actual container
for(let j=0; j<data.length; j++){
var index = container.textContent.indexOf(data[j].original);
// Data not found
if(index === -1)
continue;
// Remove the data from the list
var replace = data.splice(j, 1)[0];
container.innerHTML = container.innerHTML.replace(replace.original, '<strong>' + replace.new + '</strong>');
// Lower the j by 1 since the data array length has been updated
j--;
// Only want to perform one rule
break;
}
}
}
Demo: https://jsfiddle.net/u2Lyaab1/25/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With