我正在编写一个JavaScript脚本,它将遍历DOM
并将特定的关键字包装在<span>
标签中。我希望我的script
将出现的单词pan
包裹在<span>
中,以便可以使用<span style='color: red'
对其进行样式设置。我实际上并不想使用pan
这个词,我只是以它为例。
我已经在这里查看了许多类似的帖子,但是都没有解决我的问题。大多数都是核的,过于复杂和混乱的,或者是过于简化的,不能按照我的预期工作。
这是我到目前为止所写的内容:
<html>
<body>
<p>My <span style='font-weight: bold'>favorite</span> kitchen item is the pan.</p>
<p>A pan can also be used as a weapon.</p>
<script>
// walk the document body
function walk (node) {
// if text node
if (node.nodeType == 3) {
// will always be an element
const parent = node.parentNode;
// ignore script and style tags
const tagName = parent.tagName;
if (tagName !== 'SCRIPT' && tagName !== 'STYLE') {
// wrap occurrences of 'pan' in a red `<span>` tag
const span = '<span style="color: red">pan</span>';
parent.innerHTML = parent.innerHTML.replace (/pan/g, span)
}
}
node = node.firstChild;
while (node) {
walk (node);
node = node.nextSibling;
}
}
walk (document.body)
</script>
</body>
</html>
此代码通常会按预期运行。但是,在此示例中,事实并非如此。如果您要运行此代码,则将得到this。
我知道是什么原因造成的。但是,我不知道如何解决。
两个文本节点My
和kitchen item is the pan.
的父元素带有以下innerHTML
:My <span style="font-weight: bold">favorite</span> kitchen item is the pan.
<span>
中的“ pan”正在更换,并引起问题。
如果我使用parentNode.textContent
而不是parentNode.innerHTML
,它不会将其包装在<span>
标记中,而是将其插入为可见文本。
我知道可以通过将/pan/g
更改为/\bpan\b/g
来解决,但这只能解决我创建的示例。我需要仅将<span>
标签插入文本内容中,而无需插入标签名称或其他HTML。
我该怎么办?
答案 0 :(得分:2)
使用转义的搜索字符串搜索给定的htmlString
。这样做(使用适当的转义符)将有助于避免出现诸如匹配HTML标签(例如<s
pan >
)或子字符串(例如 Pan 多拉)。
/*
highlight(selector, string)
@ Params:
selector [String]: Same syntax as CSS/jQuery selector
string [String]: Seach string
*/
// A: Get the htmlString of the target's content
// B: Escape the search string
// C: Create a RegExp Object of the escaped search string
// D: Find and replace all matches with match wrapped in a <mark>
// E: Remove original HTML
// F: Insert new HTML
function highlight(selector, string) {
let dom = document.querySelector(selector);
let str = dom.innerHTML; //A
let esc = `(?!(?:[^<]+>|[^>]+<\\/a>))\\b(${string})\\b`; //B
let rgx = new RegExp(esc, "gi"); //C
let txt = str.replace(rgx, `<mark>$1</mark>`); //D
dom.innerHTML = ''; //E
dom.insertAdjacentHTML('beforeend', txt); //F
}
highlight('body', "pan");
<html>
<body>
<p>My <span style='font-weight: bold'>favorite</span> kitchen item is the pan.</p>
<p>A pan can also be used as a weapon.</p>
<p>Pan was the Greek god of the wild.</p>
<p>Eboli was breifly a pandemic threat.</p>
</body>
</html>