javascript - 如何突出显示 HTML 元素中多次出现的单个单词?
问题描述
我正在开发一个基于 HTML/JS 的网络聊天应用程序。我想通过聊天窗口搜索特定单词的所有出现。当前实现此搜索的想法是,我将过滤聊天消息历史记录并扫描每条聊天消息。每条聊天消息都包含在指定的 HTML 元素中,如果聊天消息元素包含搜索词,我将操纵 DOM 以突出显示这个特定的搜索词。
所以到目前为止,我有一个虚拟实现,它遍历所有聊天消息并在每个聊天消息中搜索单词。但是,如果在单个聊天消息中多次出现该词,则搜索功能只能突出显示第一次出现。如何在单个聊天消息中突出显示(操作 DOM)所有此类单词的出现。
以下是我编写的当前代码片段:
_scrollChatMessageAndHighlightResult = async(searchText) => {
// perform DOM operations to find the text and highlight it
var usrmsgs = document.getElementsByClassName('usermessage');
if(usrmsgs.length > 0) {
// get the inner text
for( let usrmsg of usrmsgs) {
await console.log("User message is: ", usrmsg);
if(usrmsg.innerText.includes(searchText)) {
var individualWordsArray = usrmsg.innerText.match(/\b(\w|')+\b/gim); //regex to split the entire text into array of individual words
console.log("Individual Words array are: ", individualWordsArray);
usrmsg.innerHTML = usrmsg.innerHTML.replace(
searchText,
'<span class="highlight-search-text">' + searchText + '</span>'
);
individualWordsArray.map((word) => {
if(word.includes(searchText)) {
// my dummy logic t
word = '<span class="highlight-search-text">' + word + '</span>'
}
});
console.log("Individual words array are: ", individualWordsArray);
}
}
}
向 JS 和 HTML 方面的专家寻求帮助。谢谢!
解决方案
掸掉旧的 jsFiddle,也许它会给你一些想法:
runExamples();
/** highLighter CODE**/
function highLight(term, hlClass = "highlight", root = document.body) {
if (!term) {
throw TypeError('Highlighter needs a term to highlight anything');
}
term = term instanceof Array ? term.join("|") : term;
hlClass = hlClass || "highlight";
const highlighter = a => `<span class="${hlClass}">${a}</span>`;
const toHtml = node => node.innerHTML =
node.innerHTML.replace(/</g, "<").replace(/>/g, ">");
const children = root.childNodes;
for (let i = 0; i < children.length; i += 1) {
// recurse children if applicable
if (children[i].childNodes.length) {
highLight.call(null, term, hlClass, children[i]);
}
let node = children[i];
let re = RegExp(`(${term})`, "gi");
if (node.nodeType === Node.TEXT_NODE && re.test(node.data)) {
node.data = node.data.replace(re, highlighter);
toHtml(node.parentElement);
}
}
}
function runExamples() {
// highlight the words 'ante', set', 'vul' and 'lacus'
// within the first p of everything within div#example
highLight("ante,sit,vul,lacus".split(","), "highlight2", document.querySelector("#example p:first-child"));
// highlight the word 'magna' everywhere in the document, using class highlight2
highLight("magna", "highlight2");
// highlight the words 'dictum' or 'vestibulum' everywhere in the document
// but only in p elements, using class highlight3
highLight("dictum|vestibulum", "highlight3");
// highlight the word 'example' within h3 element
highLight("example", null, document.querySelector("h3"));
document.addEventListener("click", manual);
}
function manual(evt) {
const origin = evt.target;
if (origin.id.endsWith("Highlight")) {
console.clear();
const removeHighligts = () => document.querySelectorAll("[class^='highlight']")
.forEach(el => el.replaceWith(document.createTextNode(el.textContent)));
if (origin.id.startsWith("manual")) {
const inputValue = document.querySelector("input").value.trim();
if (inputValue) {
removeHighligts();
highLight(inputValue, document.querySelector("#highlighter").value);
}
}
if (origin.id.startsWith("remove")) {
removeHighligts();
}
if (origin.id.startsWith("example")) {
removeHighligts();
runExamples();
}
}
return true;
}
body {
font: 12px/15px normal verdana, arial;
margin: 2rem;
}
.highlight {
font-weight: bold;
background: #ffffc0;
}
.highlight2 {
background: orange;
font-style: italic;
}
.highlight3 {
background: red;
color: white;
}
.inline {
display: inline-block;
}
<h3>a Lorem Ipsum example</h3>
<div id="example">
<div id="lipsum">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas molestie, dolor at posuere egestas,
justo erat molestie ligula, non laoreet justo leo in risus. Aenean ac fermentum mauris. Nam fringilla
accumsan nunc, at egestas ante vulputate at. Aenean et arcu ut elit gravida ornare. Nam nec eros massa,
vel imperdiet lorem. Donec dictum, elit vitae commodo porttitor, urna risus fermentum mauris, sit amet
convallis elit tellus et ligula. <span data-x="demonstrate recursive">Cras nibh lacus</span>, blandit
eu imperdiet nec, aliquet vitae nibh. Aenean eleifend vestibulum tempor. Vivamus vitae erat quis elit
fringilla aliquam.
</p>
<p>
Vestibulum molestie erat quis tortor tincidunt fermentum. Mauris imperdiet cursus auctor. Quisque non
lacinia libero. Sed sed nisi massa, ut vestibulum metus. Nunc ac varius turpis. Pellentesque habitant morbi
tristique senectus et netus et malesuada fames ac turpis egestas. Quisque at tellus ligula.
Aliquam iaculis lacus eget massa tristique accumsan. Integer eu enim sapien, id pretium erat. Ut convallis
dictum lacus, eget mattis magna molestie ut. Proin pretium mattis nisl, a auctor velit aliquam eget.
</p>
<p>
<input type="text" placeholder="enter highlight term" value="sit|lorem|example">
<select id="highlighter">
<option value="highlight" selected>default</option>
<option value="highlight2">orange</option>
<option value="highlight3">red</option>
</select>
</p>
<p>
<button id="manualHighlight">highlight manually</button>
<button id="removeHighlight">remove all highlights</button>
<button id="exampleHighlight">run examples</button>
</p>
</div>
</div>
推荐阅读
- java - 将 1 个密码安全地存储在数据库中
- mongodb - Mongoose 防止基于 document.count() 的重复 ID 号
- browser - 使用 Applescript 控制多个浏览器
- java - BlockingQueue 的替代方案,用于解决生产者-消费者类型问题的线程间通信
- razor-pages - Blazor(Razor 组件)从父组件刷新子组件
- unity3d - Unity Editor 在播放模式下随机冻结
- html - 如何将 VBA 程序更改为从 Internet Explorer 运行到 Microsoft Edge?
- node.js - 使用 npm nock 对基本功能进行单元测试(主机名未定义)
- python-3.x - 读取多个 txt 并为每个使用原始文件中的名称创建 df
- python - 基于时间戳间隔的求和频率