简体   繁体   English

使用javascript替换网页上的多个文本字符串

[英]Replacing multiple strings of text on webpage using javascript

I want to make a google chrome extension that replaces many different strings of text on a webpage to exhibit different words on client side. 我想制作一个谷歌浏览器扩展程序,取代网页上的许多不同文本字符串,以在客户端展示不同的单词。 I came accros with this example below. 我来自以下这个例子。

But I failed after trying a lot to change it to handle different words to replace. 但是在尝试了很多改变它以处理不同的词来替换之后我失败了。 I can only handle one at a time. 我一次只能处理一个。

ie: I want to change all 'pink' words to 'blue', all 'cat' words to 'dog' and all 'boy' words to 'girl'. 即:我想将所有'粉红色'单词改为'蓝色',将所有'cat'单词改为'dog',将所有'boy'单词改为'girl'。 All at once. 一次全部。

How could I accomplish that? 我怎么能做到这一点? When I tinkered with this sample code all the times I would end only changing one of the words. 当我一直修改这个示例代码时,我只会改变其中一个单词。 In some cases, only on its first occurence. 在某些情况下,仅在其第一次出现时。

Thanks in advance. 提前致谢。 I could not an answer to this question anywhere. 我无法在任何地方回答这个问题。 Sorry if it looks noobish. 对不起,如果看起来很无趣。

 var elements = document.getElementsByTagName('*'); for (var i = 0; i < elements.length; i++) { var element = elements[i]; for (var j = 0; j < element.childNodes.length; j++) { var node = element.childNodes[j]; if (node.nodeType === 3) { var text = node.nodeValue; var replacedText = text.replace(/pink/gi, 'blue'); if (replacedText !== text) { element.replaceChild(document.createTextNode(replacedText), node); } } } } 

The wildcard is "too wild" I think you will need to use '*:not(script):not(link) ... ' 通配符“太疯狂”我想你需要使用'*:not(script):not(link)...'

Or maybe something like: var elements = document.getElementsByTagName('body')[0].querySelectorAll('*'); 或者类似于: var elements = document.getElementsByTagName('body')[0].querySelectorAll('*');

var elements = document.getElementsByTagName('body')[0].querySelectorAll('*:not(script)');
[].forEach.call(elements,function(elem){
    elem.textContent = elem.textContent ?  elem.textContent.replace(/pink/igm,'blue') : elem.innerText;
});

There are a few key things to note here: 这里有几个关键的事情需要注意:

  1. You're already grabbing every element on the page with your wildcard getElementsByTagName search. 您已经使用通配符getElementsByTagName搜索抓取页面上的每个元素。 Therefore, you don't have to traverse the tree down to the child nodes, as you've already captured them in the initial search and they'll come up later in the iterations. 因此,您不必将树遍历到子节点,因为您已经在初始搜索中捕获它们,并且它们将在迭代中稍后出现。

  2. You don't have to replace a string, compare it to the original contents, then replace the node. 您不必替换字符串,将其与原始内容进行比较,然后替换节点。 You can just directly replace the inner text of any node. 您可以直接替换任何节点的内部文本。

  3. Square brackets in regular expressions indicate "classes" of characters to match. 正则表达式中的方括号表示要匹配的字符的“类”。 That means, without special characters, it will match any character inside the brackets, not all the characters, and order doesn't matter. 这意味着,没有特殊字符,它将匹配括号内的任何字符,而不是所有字符,并且顺序无关紧要。 In other words, /[one]/ will match o, n, or e, it won't match the string "one". 换句话说, /[one]/将匹配o,n或e,它将与字符串“one”不匹配。 So no square brackets needed. 所以不需要方括号。

So (without adding methods with callbacks -- though you should look into Array.forEach at least, as it's useful!), your code simplifies to just: 所以(没有添加Array.forEach方法 - 尽管你应该至少研究一下Array.forEach ,因为它很有用!),你的代码简化为:

elements = document.getElementsByTagName("*");
for (var i = 0; i < elements.length; i++) {
    elements[i].innerText = elements[i].innerText.replace(/pink/gi, "blue");
}

In order to simplify mapping of multiple strings to their replacements, you could create a js object and corresponding function for your replacements. 为了简化多个字符串到其替换的映射,您可以为替换创建一个js对象和相应的函数。

Edited for improved usability per comment from @MihaiIorga (now you only have to edit matches to add new replacement words). 编辑以改善@MihaiIorga评论的可用性(现在您只需编辑matches以添加新的替换词)。 For example (only selecting <div> tags in the snippet below for simplicity but you can modify to select all elements, certain tags, etc): 例如(为简单起见,仅在下面的代码段中选择<div>标签,但您可以修改以选择所有元素,某些标签等):

 const matches = {pink: 'blue', cat: 'dog', boy: 'girl'}; const replaces = Object.keys(matches).join('|'); const replacer = s => matches[s]; const elems = document.getElementsByTagName('div'); for (let elem of elems) { let s = elem.textContent; elem.textContent = s.replace(new RegExp(replaces, 'gi'), replacer); } 
 <div>pink horse</div> <div>green cat</div> <div>purple boy moon</div> <div>boy pink cat</div> 

So there is a very similar question posted here , though it completely replaces the text content of each child node, rather than replacing selectively. 所以这里发布了一个非常相似的问题,尽管它完全取代了每个子节点的文本内容,而不是有选择地替换。 I've modified it, here's a possible way to streamline it. 我修改了它,这是一种简化它的可行方法。 First, use a function, so you're hiding away some of the complexity. 首先,使用一个函数,所以你隐藏了一些复杂性。 ;) ;)

 let doc = document.querySelector("article"), pinkBtn = document.querySelector("#pink-btn"), pinkBoyBtn=document.querySelector("#pink-boy-btn"), pinkBoyDogBtn=document.querySelector("#pink-boy-dog-btn"); pinkBtn.addEventListener("click", function(){ replaceTextNodes(doc, /pink/gi, "blue"); }); pinkBoyBtn.addEventListener("click", function(){ replaceTextNodes(doc, /pink/gi, "blue"); replaceTextNodes(doc, /boy/gi, "girl"); }) pinkBoyDogBtn.addEventListener("click", function(){ replaceTextNodes(doc, /pink/gi, "blue"); replaceTextNodes(doc, /boy/gi, "girl"); replaceTextNodes(doc, /dog/gi, "cat"); }) function replaceTextNodes(node, oldText, newText) { node.childNodes.forEach(function(el) { if (el.nodeType === 3) { // If this is a text node, replace the text if (el.nodeValue.trim() !== "") { // Ignore this node it it an empty text node el.nodeValue = el.nodeValue.replace(oldText, newText); } } else { // Else recurse on this node replaceTextNodes(el, oldText, newText); } }); } 
 article { border: 1px solid blue; padding: 2px; } section{ border: 1px dotted red; padding: 2px; } 
 <article> <h1>This is a pink page</h1> <section id="home"> Pink pink dog cat cow chicken boy </section> <section id="about"> this is a story about a pink dog named Clyde. </section> <section id="projects"> And more on the Clyde story. He has a boy. </section> </article> <button id="pink-btn">'pink'-&gt;'blue'</button> | <button id="pink-boy-btn">'pink'-&gt;'blue', 'boy'-&gt;'girl'</button> | <button id="pink-boy-dog-btn">'pink'-&gt;'blue', 'boy'-&gt;'girl', 'dog'-&gt;'cat'</button> 

Thing to note, I tell it what to use as the root node, and to change all the text of the elements below that. 请注意,我告诉它使用什么作为根节点,并更改下面的元素的所有文本。 I pass as parameters a DOM node, the old text, and the new text value. 我将DOM节点,旧文本和新文本值作为参数传递。 For old text, I use a regex. 对于旧文本,我使用正则表达式。

This is tricky, as I'm using recursion (if the current child node isn't a text node, recall my function on that child node, using it as the parent). 棘手,因为我正在使用递归(如果当前子节点不是文本节点,请在该子节点上调用我的函数,将其用作父节点)。 Confusing, but very efficient. 令人困惑,但效率很高。

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM