我希望在加载页面后突出显示HTML页面中的特定单词。我不想使用哑巴:
document.innerHTML = document.innerHTML.replace(.....);
我想遍历每个DOM节点,找出包含文本的节点并修改那些单独节点的innerHTML。这就是我想出的:
function highlightSearchTerms(sword) {
$$('body').map(Element.extend).first().descendants().each(function (el) {
if (el.nodeType == Node.ELEMENT_NODE && el.tagName != 'TD') {
//$A(el.childNodes).each(function (onlyChild) {
//if (onlyChild.nodeType == Node.TEXT_NODE) {
//console.log(onlyChild);
el.innerHTML = el.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
//}
//});
}
});
//document.body.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
}
它现在正常工作,但它非常低效,并且几乎不比上面的单行更好,因为它可能会在同一文本上多次替换。 (嗯......,还是不?)
如果您取消注释评论的内容并将el.innerHTML.replace
更改为onlyChild.textContent.replace
,它几乎可以像它需要的那样工作,但修改textContent不会创建新的span作为元素,而是添加HTML内容为文本。
我的问题/要求是找到一种方法,它突出显示文档中逐字遍历的单词。
答案 0 :(得分:1)
这很快就干净了:
function highlightSearchTerms(sword) {
$$('body').map(Element.extend).first().descendants().each(function (el) {
if (el.nodeType == Node.ELEMENT_NODE && el.tagName != 'TEXTAREA' && el.tagName != 'INPUT' && el.tagName != 'SCRIPT') {
$A(el.childNodes).each(function (onlyChild) {
var pos = onlyChild.textContent.indexOf(sword);
if (onlyChild.nodeType == Node.TEXT_NODE && pos >= 0) {
//console.log(onlyChild);
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = onlyChild.splitText(pos);
var endbit = middlebit.splitText(sword.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
//onlyChild. = el.innerHTML.replace(new RegExp('('+sword+')', 'gi'), '<span class="highlight">$1</span>');
}
});
}
});
}
但我很难理解它究竟是如何运作的。这似乎是神奇的界限:
middlebit.parentNode.replaceChild(spannode, middlebit);
答案 1 :(得分:1)
前一段时间我将一个从jQuery转换为PrototypeJS:
Element.addMethods({
highlight: function(element, term, className) {
function innerHighlight(element, term, className) {
className = className || 'highlight';
term = (term || '').toUpperCase();
var skip = 0;
if ($(element).nodeType == 3) {
var pos = element.data.toUpperCase().indexOf(term);
if (pos >= 0) {
var middlebit = element.splitText(pos),
endbit = middlebit.splitText(term.length),
middleclone = middlebit.cloneNode(true),
spannode = document.createElement('span');
spannode.className = 'highlight';
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (element.nodeType == 1 && element.childNodes && !/(script|style)/i.test(element.tagName)) {
for (var i = 0; i < element.childNodes.length; ++i)
i += innerHighlight(element.childNodes[i], term);
}
return skip;
}
innerHighlight(element, term, className);
return element;
},
removeHighlight: function(element, term, className) {
className = className || 'highlight';
$(element).select("span."+className).each(function(e) {
e.parentNode.replaceChild(e.firstChild, e);
});
return element;
}
});
您可以在每个元素上使用它:
$("someElementId").highlight("foo", "bar");
,并使用您选择的className。您也可以删除突出显示。
答案 2 :(得分:1)
如果您使用Fabien发布的原型版,请务必添加className 作为innerHighlight调用的参数:
i += innerHighlight(element.childNodes[i], term)
需要
i += innerHighlight(element.childNodes[i], term, className)
如果您关心高光的自定义classNames。
答案 3 :(得分:0)
抓取$(document.body)并进行搜索/替换并在术语周围换行,然后一次性交换整个$(document.body)。将它视为一个大字符串,忘记DOM。这样您只需更新DOM一次。它应该很快。
答案 4 :(得分:0)
我找到了一个可以做你想要的脚本(看起来非常快),它并不特定于任何库,所以你可能想要修改它:
http://www.nsftools.com/misc/SearchAndHighlight.htm
您在上面提供的方法(虽然已注释掉)在替换可能位于html元素中的项目时会遇到问题。即“搜索和替换可能会突出”“事物”,而这不是你想要的。
这是一个基于Jquery的高亮剧本:
看起来难以转换为原型。