我有一个简短的脚本,该脚本在innerHTML中查找具有特定文本的特定类,然后使用replaceWith替换整个元素。当只有一段特定的文本时,这种方法非常有用,但是我有几项要查找和替换。
下面的HTML代码得到了简化。基本上,还有另一个脚本可以找到特定的术语,并在这些术语首次出现时添加带有定义的弹出窗口。我想省略一些术语,但是不可能修改其他脚本。我提出的第一个解决方案涉及找到弹出窗口类,查看其innerHTML是否具有一致的开始(它将始终以term开头,紧随其后是span标签),然后将整个元素替换为term作为普通文本(“ term” )。
let glossaryTerms = document.getElementsByClassName('popup');
for (let x = 0; x < glossaryTerms.length; x++) {
let term = glossaryTerms[x];
let content = term.innerHTML.trim();
if (content.includes('term\<span')) {
term.replaceWith('term');
}
}
<p>Sample text for this example. Then there's a word with a definition popup <a href="#" class="popup #text">term<span class="popupBody">This is the definition text that appears in the popup eventually...</span></a>.</p>
该脚本可以正常工作,但是我可能要打几个字。
例如: 苹果 香蕉 仙人掌
以此类推。
这里的任何建议都将不胜感激。我想知道这些术语是否可以存储在JSON文件中,例如,但是我不知道从哪里开始。
答案 0 :(得分:1)
提取第一个文本(在第一个子元素之前)的方法是:
node.childNodes[0].nodeValue.trim();
...,这将把span
节点视为 second 节点,前提是前面有文本。
还有第二个问题:getElementsByClassName
返回的集合是一个 live 集合,即,当用纯文本替换那些弹出节点时,实际上减小了该集合的大小。所以第二个元素突然变成第一个(索引0),但是循环增加了索引,所以您跳过一个节点。
一种解决方案是使用非实时替代项querySelectorAll
:
let terms = new Set(["apple", "pear"]); // Only do something for these terms
for (let node of document.querySelectorAll('.popup')) {
let term = node.childNodes[0].nodeValue.trim();
if (terms.has(term)) node.replaceWith(term);
}
<p>Sample text for this example. Then there's a word with a definition popup
<a href="#" class="popup #text">apple<span class="popupBody">
This is the definition text that appears in the popup eventually...</span></a>.</p>
<p>Sample text for this example. Then there's a word with a definition popup
<a href="#" class="popup #text">pear<span class="popupBody">
This is the definition text that appears in the popup eventually...</span></a>.</p>