首页 > 解决方案 > 如何突出显示 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 方面的专家寻求帮助。谢谢!

标签: javascripthtmldom

解决方案


掸掉旧的 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(/&lt;/g, "<").replace(/&gt;/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>


推荐阅读