I recently encountered a feature while working on a project: highlighting keywords on a web page. I thought it was a simple operation that could be accomplished with an innerHTML replace, but I encountered many problems. This article records these problems and the final perfect solution, hoping to help friends who have the same experience. If you are only interested in the results, ignore the process and skip to the results. Common practice: regular replacement Idea: To highlight elements, you need to extract the keywords and wrap them with tags, and then adjust the style of the tags. Use innerHTML or outHTML instead of innerText or outText. const regex = new RegExp(keyword,"g") element.innerHTML = element.innerHTML.replace(regex,"<b class="a">"+keyword+"</b>") element.classList.add("highlight") The hidden dangers of doing this are as follows: ()\ div <div id="parent"> <div class="test">test</div> </div> The keyword parent node element uses class to perform background coloring, which pollutes the original DOM to a certain extent and may affect the re-positioning of the element. (As a plugin, it is hoped that the original DOM will be changed as little as possible) Regular optimization 1: only process elements within tags var formatKeyword = text.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') // Escape special characters contained in keyword, such as /. var finder = new RegExp(">.*?"++".*?<") // Extract the text in the tag to avoid misoperation of class, id, etc. element.innerHTML = element.innerHTML.replace(finder,function(matched){ return matched.replace(text,"<br>"+text+</br>) }) // Replace keywords in the extracted tag text This can solve most of the problems, but the problem that still exists is that as long as there are symbols like < in the tag attributes, the matching rules will be broken and regular extraction content will be incorrect. HTML5 dataset can customize any content, so these special characters are unavoidable. <div dataset="p>d">Replace</div> Regular optimization 2: Clear possible affected labels <div id="keyword">keyword</div> =》Replace the closing tag with a variable [replaced1] keyword [replaced2] // id="keyword" in the closing tag will not be processed =》 [replaced1]<b>keyword</b>[replaced2] =》Replace the temporary variable replaced with the original tag <div id="keyword"><b>keyword</b></div>
Most importantly, this method cannot correctly extract tags when the tag value contains <> symbols. In short, after many attempts, regular expressions have not been able to effectively handle various situations. Then I changed my mindset and processed it through nodes instead of strings. element.childNodes can most effectively clean up the noise information within the tag. [Perfect solution] Processing through DOM nodes <div id="parent"> keyword 1 <span id="child"> keyword 2 </span> </div> Get all child nodes through parent.childNodes. The child node can be replaced by However, keyword 1 is a text node, and you can only modify the text content, but cannot add HTML, and you cannot control its style independently. And text nodes cannot be converted into ordinary nodes, which is the most annoying thing. Finally, here comes the focus of this article. Because of this function, I got to know text nodes seriously for the first time. From here, Text is discovered, and highlighting is achieved by cutting text nodes and replacing them. Source code and restore highlight see source code const reg = new RegExp(keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')) highlight = function (node,reg){ if (node.nodeType == 3) { //Only process text nodes const match = node.data.match(new RegExp(reg)); if (match) { const highlightEl = document.createElement("b"); highlightEl.dataset.highlight="y" const wordNode = node.splitText(match.index) wordNode.splitText(match[0].length); // Cut into the first keyword and the last three Text nodes const wordNew = document.createTextNode(wordNode.data); highlightEl.appendChild(wordNew);//Highlight node is constructed successfully wordNode.parentNode.replaceChild(highlightEl, wordNode);//Replace the text node} } else if (node.nodeType == 1 && node.dataset.highlight!="y" ) { for (var i = 0; i < node.childNodes.length; i++) { highlight(node.childNodes[i], reg); i++ } } } Summarize The above is the perfect solution for highlighting keywords in HTML that I introduced to you. I hope it will be helpful to you. If you have any questions, please leave me a message and I will reply to you in time. I would also like to thank everyone for their support of the 123WORDPRESS.COM website! |
<<: Deeply understand the current status of HTML5 development in mobile development
>>: Summarize the commonly used nth-child selectors
Selector Grouping Suppose you want both the h2 el...
Table of contents 1. Rendering 2. Bind data and a...
This article example shares the specific code of ...
Method 1: <input id= "File1" type= &q...
Introduction This article records how to mount a ...
Unicode is a character encoding scheme developed ...
Table of contents Function call optimization Func...
Today I designed a dynamic window style for publis...
1. Create a new user: 1. Execute SQL statement to...
Create a project directory mkdir php Create the f...
BackUpMysql.sh script #!/bin/bash PATH=/bin:/sbin...
Table of contents Small but beautiful Keep it sim...
It mainly shows how to configure X-Frame-Options,...
Adding the attribute selected = "selected&quo...
Table of contents Preface Using websocket Constru...