使用javascript

时间:2019-01-07 20:12:50

标签: javascript

我想制作一个Google chrome扩展程序,以替换网页上许多不同的文本字符串,以在客户端显示不同的单词。我在下面的这个例子中很赞。

但是我尝试了很多更改以处理不同的单词来替换后失败了。我一次只能处理一个。

即:我想将所有“粉红色”改为“蓝色”,所有“猫”改为“狗”,所有“男孩”改为“女孩”。一次全部。

我该怎么做?当我一直修改此示例代码时,我只需要更改其中一个单词就可以结束。在某些情况下,仅在首次出现时。

先谢谢了。我无法在任何地方回答这个问题。对不起,如果它看起来不愉快。

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);
            }
        }
    }
}

4 个答案:

答案 0 :(得分:1)

通配符“太野了”,我认为您需要使用'*:not(script):not(link)...'

或者类似: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;
});

答案 1 :(得分:1)

这里要注意一些关键事项:

  1. 您已经使用通配符getElementsByTagName搜索抓取了页面上的每个元素。因此,您不必遍历树到子节点,因为您已经在初始搜索中捕获了它们,它们将在后续迭代中出现。

  2. 您不必替换字符串,可以将其与原始内容进行比较,然后替换节点。您可以直接替换任何节点的内部文本。

  3. 正则表达式中的方括号指示要匹配的字符的“类”。这意味着,没有特殊字符,它将匹配方括号内的任何字符,而不是 all 字符,并且顺序无关紧要。换句话说,/[one]/将匹配o,n或e,它将不匹配字符串“ one”。因此不需要方括号。

因此((不添加带有回调的方法-尽管您至少应该研究Array.forEach,因为它很有用!),您的代码简化为:

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

答案 2 :(得分:1)

为了简化多个字符串到其替换的映射,您可以为替换创建一个js对象和相应的函数。

经过修改,以提高@MihaiIorga中每个注释的可用性(现在您只需编辑matches即可添加新的替换词)。例如(为简单起见,在下面的代码段中仅选择<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>

答案 3 :(得分:0)

因此,有一个非常相似的问题posted here,尽管它完全替换了每个子节点的文本内容,而不是有选择地替换。我已经对其进行了修改,这是一种简化它的方法。首先,使用一个函数,以便隐藏一些复杂性。 ;)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 699, in runfile
    execfile(filename, namespace)
  File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 81, in execfile
    builtins.execfile(filename, *where)
  File "/home/shayez/Desktop/k.py", line 72, in <module>
    Print_Data()
  File "/home/shayez/Desktop/k.py", line 67, in Print_Data
    writer.writerows(rows)
ValueError: I/O operation on closed file
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;
}

需要注意的是,我告诉它用作根节点的内容,并更改其下的所有元素的文本。我将DOM节点,旧文本和新文本值作为参数传递。对于旧文本,我使用正则表达式。

这很困难,因为我正在使用递归(如果当前子节点不是文本节点,请使用该子节点作为父节点来调用该子节点上的函数)。令人困惑,但非常有效。

希望这会有所帮助!