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
Table of contents Conditional compilation Page La...
0. Why do we need remote development? When develo...
Table of contents 1. Auxiliary functions 2. Examp...
Enable the service when you need it, and disable ...
After the previous two chapters, do you have a ne...
Table of contents One-way data flow explanation V...
Hexadecimal code table of various colors [Part 1] ...
Table of contents 1 Introduction to the new opera...
Table of contents APIs used Simple Example person...
This article shares the MySQL installation and co...
1. Error details Once when manually performing a ...
Table of contents Method 1: Call the function dir...
Code: <input type="text" class="...
Automatic backup of MySQL database using shell sc...
Problem description: Error message: Caused by: co...