Reputation: 103
The title pretty much explains it. I want to add a user defined word or phrase (for example: 'greatest') after every appearance of a specific word (for example: 'the') in JavaScript. So every time 'the' appears in the text of the HTML (blah blah blah the blah blah) the JavaScript will inject 'greatest' (blah blah blah the greatest blah blah). I was trying to figure this out using regular expressions but have come up short of adding it directly into the HTML.
Upvotes: 1
Views: 314
Reputation: 26161
To do this job dynamically, one way is inventing our own String.prototype.affix()
method. This new method will do what you want and if the last argument is true
it affixes the provided string to affix (second argument) to the end and if false
to the front of the searched piece of sub-string (first argument). I've assigned true
as a default value to the last parameter.
String.prototype.affix = function(s,a,b = true){
var r = new RegExp(s,"g");
return b ? this.replace(r,"$&" + " " + a)
: this.replace(r,a + " " + "$&");
}
console.log("this is the book and the author is him".affix("the", "greatest",true));
Upvotes: 0
Reputation: 42054
My proposal is to use TreeWalker to search for all text nodes in the body:
function replaceTextInPage(el, txtMatch, txtToReplace) {
txtToReplace = (txtToReplace.length > 0) ? ' ' + txtToReplace : '';
var walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);
while (n = walk.nextNode()) {
if (n.textContent.trim().length > 0) {
n.textContent = n.textContent.replace(new RegExp(txtMatch, "gi"), txtMatch + txtToReplace);
}
}
}
window.onload = function () {
document.getElementById('btn').addEventListener('click', function() {
replaceTextInPage(document.body, document.getElementById('txtToFind').value, document.getElementById('txtToAdd').value)
}, false);
}
<button id="btn">Replace string</button><br/>
Text to search: <input id="txtToFind" type="text" value="the"><br/>
Text to add at the end: <input id="txtToAdd" type="text" value="greatest"><br/>
<div style="width: 100%;height: 100px;">It seems to only remove <span style="color: red;">the</span> first occurrence of abc in <span style="color: red;">the</span> string above. How can I replace all occurrences of it?</div>
Upvotes: 1
Reputation: 25634
Indeed, Regex is perfect to do that. You can use the String.replace() function to replace the text:
someString.replace(/\b(the)\b/ig, "$1 greatest");
Here, \b
represent word boundaries (spaces, periods, etc.) and will avoid replacing "other" with "othe greatest r", the parenthesis around "the" allow you to select it (to use it in the replacement, by using $1
). Then, i
and g
are flags to make your regex case-Insensitive and Global (look for multiple occurrences).
But that's not where most of the work needs to be done. Replacing the text of an element might interfere with the actual HTML. To avoid that, you can apply a function recursively to only target text nodes:
document.getElementById('btn').addEventListener('click', function() {
doReplace(/\b(the)\b/ig, "$1 greatest", document.body);
this.style.visibility = 'hidden';
});
function doReplace(search, replacement, element) {
if (element.nodeType == 3) { // if the element is a text node, replace the content
element.nodeValue = element.nodeValue.replace(search, replacement);
} else { // otherwise, apply this function to all children
var children = element.childNodes;
for (var i = 0; i < children.length; i++) {
doReplace(search, replacement, children[i]);
}
}
}
<button id="btn">Add "greatest"!</button>
<h1>The pie was cold</h1>
<p>I was at the restaurant the other day, and the waiter took my order. The problem? My pie was cold!</p>
Upvotes: 0
Reputation: 5858
Here is some code that will do what you want. Notice that it doesn't change "The orange" since it's case sensative. Notice also that it doesn't change the alerted "the orange" because that exists in a script element.
function getTextNodesThatContain(text) {
var textNodes = $(document).find(":not(iframe, script, style)")
.contents().filter(
function() {
return this.nodeType == 3
&& this.textContent.indexOf(text) > -1;
});
return textNodes;
};
$(document).ready(function() {
getTextNodesThatContain("the").each(function(ind, item) {
item.nodeValue = item.nodeValue.replace("the", "the greatest");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This is the apple.
<div> this is the orange. </div>
<script>
function alertme() {
alert("the orange");
}
</script>
<a href="javascript:alertme()">The orange</a>
Upvotes: 1