为了避免混淆,下面详细解释了我想要完成的任务:在整个(外部)网站(不包括标签)的文本中搜索字符串,然后更改这些实例的样式(例如颜色)(如果找到) 。
那么这正是你应该做的:)
首先,构建一个递归函数来遍历 DOM 并获取所有文本节点:
function findTextNodes(node, ret) {
var c = node.childNodes, i, l = c.length;
for( i=0; i<l; i++) {
switch(c[i].nodeType) {
case 1: // element node
findTextNodes(c[i], ret);
break;
case 3: // text node
ret.push(c[i]);
break;
}
}
}
var textNodes = [];
findTextNodes(document.body, textNodes);
现在您已经拥有了文档中所有文本节点的数组,您可以开始在它们中搜索您的目标。
function searchTextNodes(nodes, search) {
var results = [], l = nodes.length, i,
regex = new RegExp(search,'i'), match,
span;
for( i=0; i<l; i++) {
while( (match = nodes[i].nodeValue.search(regex)) > -1) {
nodes[i] = nodes[i].splitText(match);
span = document.createElement('span');
span.classList.add('highlight');
nodes[i].parentNode.insertBefore(span, nodes[i]);
nodes[i].splitText(search.length);
span.appendChild(nodes[i]);
nodes[i] = span.nextSibling;
}
}
}
searchTextNodes(textNodes, fooInputTxt.value);
而且……就是这样!为了获得额外的积分,以下是“撤消”搜索的方法:
function undoSearch(root) {
var nodes = root.querySelectorAll("span.highlight"),
l = nodes.length, i;
for( i=0; i<l; i++) {
nodes[i].parentNode.replaceChild(nodes[i].firstChild, nodes[i]);
}
root.normalize();
}
undoSearch(document.body);
JSFiddle 上的演示 https://jsfiddle.net/35L5seL9/1/