【问题标题】:How to highlight text using javascript如何使用javascript突出显示文本
【发布时间】:2012-01-28 11:43:11
【问题描述】:

有人可以帮助我使用可以突出显示网页上文本的 javascript 函数吗? 并且要求是 - 仅突出显示一次,而不是像我们在搜索时那样突出显示所有出现的文本。

【问题讨论】:

  • 如果您发布函数的代码,我们将能够提供帮助。如果您要求我们为您创建这样的功能……那不太可能。你必须自己做一些事情。开始做某事,遇到困难就回来。
  • 是的,我已经阅读了如何提问并且我自己做了一些事情,但我被卡住了,这就是我问的原因。我在 Android 上工作,对 javasript 知之甚少,这就是为什么我不能自己做。早些时候,我使用了不同的 javascript 来完成这项工作,但并非没有某些限制。问这个问题时我可能没有用正确的词,对此我很抱歉,但请不要想别的。
  • 您可能会对这个插件感兴趣:github.com/julmot/jmHighlight。它可以单独或作为一个术语突出显示关键字,可以突出显示与您的自定义元素和类名的匹配,还可以搜索变音符号。最重要的是,它允许您过滤搜索匹配项的上下文。
  • 按照正则表达式方式结帐...stackoverflow.com/a/45519242/2792959
  • 我在这里准备了一篇文章,exhesham.com/2017/11/20/…

标签: javascript highlighting


【解决方案1】:

我认为这段代码更好,因为突出显示所有重复的字符

function highlight(text) {
  var inputText = document.getElementById("inputText");
  var innerHTML = inputText.innerHTML;
  var index = innerHTML.indexOf(text);
  if (index >= 0) { 
     inputText.innerHTML=innerHTML.split(text).join('<span class="highlight">'+text+'</span>');
  }
}
.highlight {
  background-color: yellow;
}
<button onclick="highlight('fox')">Highlight</button>

<div id="inputText">
  The fox went over the fence fox fox fox wen fox
</div>

【讨论】:

    【解决方案2】:

    如果您还希望它在页面加载时突出显示,有一种新方法。

    只需添加#:~:text=Highlight%20These

    尝试在新标签中访问此链接

    https://stackoverflow.com/questions/38588721#:~:text=Highlight%20a%20text

    突出显示“突出显示文本”文本。

    另外,目前仅支持 Chrome(感谢 GitGitBoom)。

    【讨论】:

    【解决方案3】:

    关于控制论:谢谢,下面的功能有效。但是有一个问题,因为它也替换了标签内的单词。如果要突出显示的单词是目标,下面是一个示例:

    <a <mark>target</mark>="_blank" href="Its not OK to highlight <mark>target</mark> here">Its OK to highlight the words <mark>target</mark>s here</a>
    

    我们如何防止这种情况发生?

    function highlight_words(word) {
        const page = document.body.innerHTML;
        document.body.innerHTML = page.replace(new RegExp(word, "gi"), (match) => `<mark>${match}</mark>`);
    }
    

    【讨论】:

      【解决方案4】:

      如果您将任何文本包围在标记标签内,浏览器会自动以这种醒目的黄色突出显示该文本。 详情请见:https://dev.to/comscience/highlight-searched-text-on-a-page-with-just-javascript-17b3

       <h1>
        Searching and Marking
      </h1>
      
      <input type="text" id="search"/>
      <button onClick="search(id)" id="button">
      Highlight
      </button>
      
      <p id="text">
      What exactly is this Worker thread module, and why do we need it? In this post, we will talk about the historical reasons concurrency is implemented in JavaScript and Node.js, the problems we might find, current solutions, and the future of parallel processing with Worker threads.
      
      Living in a single-threaded world
      JavaScript was conceived as a single-threaded programming language that ran in a browser. Being single-threaded means that only one set of instructions is executed at any time in the same process (the browser, in this case, or just the current tab in modern browsers).
      
      This made things easier for implementation and for developers using the language. JavaScript was initially a language only useful for adding some interaction to webpages, form validations, and so on — nothing that required the complexity of multithreading.
      </p>
      

      现在 JS 代码将如下所示

      function search(e) {
          let searched = document.getElementById("search").value.trim();
        if (searched !== "") {
          let text = document.getElementById("text").innerHTML;
          let re = new RegExp(searched,"g"); // search for all instances
              let newText = text.replace(re, `<mark>${searched}</mark>`);
              document.getElementById("text").innerHTML = newText;
        }
      }
      

      【讨论】:

        【解决方案5】:

        只需将您的话传递到以下函数

        function highlight_words(word) {
            const page = document.body.innerHTML;
            document.body.innerHTML = page.replace(new RegExp(word, "gi"), (match) => `<mark>${match}</mark>`);
        }
        

        用法

        highlight_words("hello")
        

        这将突出显示页面上单词的所有实例。

        【讨论】:

          【解决方案6】:

          我想分享更多关于scroll text fragment的用法

          语法:#:~:text=[prefix-,]textStart[,textEnd][,-suffix]

          如果您想在一个 URL (&amp;text=) 中突出显示多个文本片段

          Example Demo link
          #:~:text=javascript&amp;text=highlight&amp;text=Ankit How to highlight text using javascript

          查看更多:https://web.dev/text-fragments/#textstart

          【讨论】:

            【解决方案7】:

            这里提供的解决方案非常糟糕。

            1. 您不能使用正则表达式,因为这样会在 html 标记中搜索/突出显示。
            2. 您不能使用正则表达式,因为它不适用于 UTF*(任何非拉丁/英文字符)。
            3. 你不能只做一个innerHTML.replace,因为当字符有一个特殊的HTML符号时,这不起作用,例如。 &amp;amp; for &, &amp;lt; for &gt; for >, &amp;auml; for ä, &amp;ouml; for ö &amp;uuml; for ü &amp;szlig; for ß,等等。

            你需要做什么:

            遍历 HTML 文档,查找所有文本节点,获取 textContent,使用 indexOf 获取突出显示文本的位置(如果不区分大小写,则使用可选的 toLowerCase),附加所有内容在indexoftextNode 之前,将匹配的文本附加一个突出显示范围,并在文本节点的其余部分重复(突出显示字符串可能在textContent 字符串中出现多次)。

            下面是代码:

            var InstantSearch = {
            
                "highlight": function (container, highlightText)
                {
                    var internalHighlighter = function (options)
                    {
            
                        var id = {
                            container: "container",
                            tokens: "tokens",
                            all: "all",
                            token: "token",
                            className: "className",
                            sensitiveSearch: "sensitiveSearch"
                        },
                        tokens = options[id.tokens],
                        allClassName = options[id.all][id.className],
                        allSensitiveSearch = options[id.all][id.sensitiveSearch];
            
            
                        function checkAndReplace(node, tokenArr, classNameAll, sensitiveSearchAll)
                        {
                            var nodeVal = node.nodeValue, parentNode = node.parentNode,
                                i, j, curToken, myToken, myClassName, mySensitiveSearch,
                                finalClassName, finalSensitiveSearch,
                                foundIndex, begin, matched, end,
                                textNode, span, isFirst;
            
                            for (i = 0, j = tokenArr.length; i < j; i++)
                            {
                                curToken = tokenArr[i];
                                myToken = curToken[id.token];
                                myClassName = curToken[id.className];
                                mySensitiveSearch = curToken[id.sensitiveSearch];
            
                                finalClassName = (classNameAll ? myClassName + " " + classNameAll : myClassName);
            
                                finalSensitiveSearch = (typeof sensitiveSearchAll !== "undefined" ? sensitiveSearchAll : mySensitiveSearch);
            
                                isFirst = true;
                                while (true)
                                {
                                    if (finalSensitiveSearch)
                                        foundIndex = nodeVal.indexOf(myToken);
                                    else
                                        foundIndex = nodeVal.toLowerCase().indexOf(myToken.toLowerCase());
            
                                    if (foundIndex < 0)
                                    {
                                        if (isFirst)
                                            break;
            
                                        if (nodeVal)
                                        {
                                            textNode = document.createTextNode(nodeVal);
                                            parentNode.insertBefore(textNode, node);
                                        } // End if (nodeVal)
            
                                        parentNode.removeChild(node);
                                        break;
                                    } // End if (foundIndex < 0)
            
                                    isFirst = false;
            
            
                                    begin = nodeVal.substring(0, foundIndex);
                                    matched = nodeVal.substr(foundIndex, myToken.length);
            
                                    if (begin)
                                    {
                                        textNode = document.createTextNode(begin);
                                        parentNode.insertBefore(textNode, node);
                                    } // End if (begin)
            
                                    span = document.createElement("span");
                                    span.className += finalClassName;
                                    span.appendChild(document.createTextNode(matched));
                                    parentNode.insertBefore(span, node);
            
                                    nodeVal = nodeVal.substring(foundIndex + myToken.length);
                                } // Whend
            
                            } // Next i 
                        }; // End Function checkAndReplace 
            
                        function iterator(p)
                        {
                            if (p === null) return;
            
                            var children = Array.prototype.slice.call(p.childNodes), i, cur;
            
                            if (children.length)
                            {
                                for (i = 0; i < children.length; i++)
                                {
                                    cur = children[i];
                                    if (cur.nodeType === 3)
                                    {
                                        checkAndReplace(cur, tokens, allClassName, allSensitiveSearch);
                                    }
                                    else if (cur.nodeType === 1)
                                    {
                                        iterator(cur);
                                    }
                                }
                            }
                        }; // End Function iterator
            
                        iterator(options[id.container]);
                    } // End Function highlighter
                    ;
            
            
                    internalHighlighter(
                        {
                            container: container
                            , all:
                                {
                                    className: "highlighter"
                                }
                            , tokens: [
                                {
                                    token: highlightText
                                    , className: "highlight"
                                    , sensitiveSearch: false
                                }
                            ]
                        }
                    ); // End Call internalHighlighter 
            
                } // End Function highlight
            
            };
            

            那么你可以这样使用它:

            function TestTextHighlighting(highlightText)
            {
                var container = document.getElementById("testDocument");
                InstantSearch.highlight(container, highlightText);
            }
            

            这是一个 HTML 文档示例

            <!DOCTYPE html>
            <html>
                <head>
                    <title>Example of Text Highlight</title>
                    <style type="text/css" media="screen">
                        .highlight{ background: #D3E18A;}
                        .light{ background-color: yellow;}
                    </style>
                </head>
                <body>
                    <div id="testDocument">
                        This is a test
                        <span> This is another test</span>
                        äöüÄÖÜäöüÄÖÜ
                        <span>Test123&auml;&ouml;&uuml;&Auml;&Ouml;&Uuml;</span>
                    </div>
                </body>
            </html>
            

            顺便说一句,如果你在数据库中搜索LIKE
            例如WHERE textField LIKE CONCAT('%', @query, '%') [你不应该这样做,你应该使用全文搜索或 Lucene],然后你可以用 \ 转义每个字符并添加 SQL-escape-statement,这样你会找到 LIKE- 的特殊字符表达式。

            例如

            WHERE textField LIKE CONCAT('%', @query, '%') ESCAPE '\'
            

            而@query 的值不是'%completed%' 而是'%\c\o\m\p\l\e\t\e\d%'

            (经过测试,可与 SQL-Server 和 PostgreSQL 以及所有其他支持 ESCAPE 的 RDBMS 系统一起使用)


            修改后的打字稿版本:

            namespace SearchTools 
            {
            
            
                export interface IToken
                {
                    token: string;
                    className: string;
                    sensitiveSearch: boolean;
                }
            
            
                export class InstantSearch 
                {
            
                    protected m_container: Node;
                    protected m_defaultClassName: string;
                    protected m_defaultCaseSensitivity: boolean;
                    protected m_highlightTokens: IToken[];
            
            
                    constructor(container: Node, tokens: IToken[], defaultClassName?: string, defaultCaseSensitivity?: boolean)
                    {
                        this.iterator = this.iterator.bind(this);
                        this.checkAndReplace = this.checkAndReplace.bind(this);
                        this.highlight = this.highlight.bind(this);
                        this.highlightNode = this.highlightNode.bind(this);    
            
                        this.m_container = container;
                        this.m_defaultClassName = defaultClassName || "highlight";
                        this.m_defaultCaseSensitivity = defaultCaseSensitivity || false;
                        this.m_highlightTokens = tokens || [{
                            token: "test",
                            className: this.m_defaultClassName,
                            sensitiveSearch: this.m_defaultCaseSensitivity
                        }];
                    }
            
            
                    protected checkAndReplace(node: Node)
                    {
                        let nodeVal: string = node.nodeValue;
                        let parentNode: Node = node.parentNode;
                        let textNode: Text = null;
            
                        for (let i = 0, j = this.m_highlightTokens.length; i < j; i++)
                        {
                            let curToken: IToken = this.m_highlightTokens[i];
                            let textToHighlight: string = curToken.token;
                            let highlightClassName: string = curToken.className || this.m_defaultClassName;
                            let caseSensitive: boolean = curToken.sensitiveSearch || this.m_defaultCaseSensitivity;
            
                            let isFirst: boolean = true;
                            while (true)
                            {
                                let foundIndex: number = caseSensitive ?
                                    nodeVal.indexOf(textToHighlight)
                                    : nodeVal.toLowerCase().indexOf(textToHighlight.toLowerCase());
            
                                if (foundIndex < 0)
                                {
                                    if (isFirst)
                                        break;
            
                                    if (nodeVal)
                                    {
                                        textNode = document.createTextNode(nodeVal);
                                        parentNode.insertBefore(textNode, node);
                                    } // End if (nodeVal)
            
                                    parentNode.removeChild(node);
                                    break;
                                } // End if (foundIndex < 0)
            
                                isFirst = false;
            
            
                                let begin: string = nodeVal.substring(0, foundIndex);
                                let matched: string = nodeVal.substr(foundIndex, textToHighlight.length);
            
                                if (begin)
                                {
                                    textNode = document.createTextNode(begin);
                                    parentNode.insertBefore(textNode, node);
                                } // End if (begin)
            
                                let span: HTMLSpanElement = document.createElement("span");
            
                                if (!span.classList.contains(highlightClassName))
                                    span.classList.add(highlightClassName);
            
                                span.appendChild(document.createTextNode(matched));
                                parentNode.insertBefore(span, node);
            
                                nodeVal = nodeVal.substring(foundIndex + textToHighlight.length);
                            } // Whend
            
                        } // Next i 
            
                    } // End Sub checkAndReplace 
            
            
                    protected iterator(p: Node)
                    {
                        if (p == null)
                            return;
            
                        let children: Node[] = Array.prototype.slice.call(p.childNodes);
            
                        if (children.length)
                        {
                            for (let i = 0; i < children.length; i++)
                            {
                                let cur: Node = children[i];
            
                                // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
                                if (cur.nodeType === Node.TEXT_NODE) 
                                {
                                    this.checkAndReplace(cur);
                                }
                                else if (cur.nodeType === Node.ELEMENT_NODE) 
                                {
                                    this.iterator(cur);
                                }
                            } // Next i 
            
                        } // End if (children.length) 
            
                    } // End Sub iterator
            
            
                    public highlightNode(n:Node)
                    {
                        this.iterator(n);
                    } // End Sub highlight 
            
            
                    public highlight()
                    {
                        this.iterator(this.m_container);
                    } // End Sub highlight 
            
            
                } // End Class InstantSearch 
            
            
            } // End Namespace SearchTools 
            

            用法:

            let searchText = document.getElementById("txtSearchText");
            let searchContainer = document.body; // document.getElementById("someTable");
            let highlighter = new SearchTools.InstantSearch(searchContainer, [
                {
                    token: "this is the text to highlight" // searchText.value,
                    className: "highlight", // this is the individual highlight class
                    sensitiveSearch: false
                }
            ]);
            
            
            // highlighter.highlight(); // this would highlight in the entire table
            // foreach tr - for each td2 
            highlighter.highlightNode(td2); // this highlights in the second column of table
            

            【讨论】:

            • 很好的答案.. 该方法看起来有点矫枉过正,但简洁!肯定会对使用该方法进行速度测试感兴趣,因为在我的情况下,结果是延迟加载到 DOM 中的(因为 可以 有数千个结果),好奇这种方法是否会增加高延迟延迟加载。
            • 抱歉,您的论点都不是真的。 1. 你绝对可以使用正则表达式,你不应该在 HTML 值中搜索,而是在元素的文本值中搜索。 2. 你完全可以使用带有变音符号的正则表达式,如mark.js 中实现的那样。 3. HTML 符号会被转换成浏览器 DOM 中的实际字符,所以你也绝对使用它们!
            • @julmot; To 1:这意味着您需要遍历每个元素,这正是我所做的。除非你不关心丢失格式,在这种情况下你可以在 document.body.innerText 中搜索,这会很慢。 3. 不在 DOM 中,而是在文本元素的 innerText 或 textContent 属性中。这再次意味着您需要遍历文本元素;不能用正则表达式 AFAIK 完成。 2:不知道mark.js,但我会避免做jQuery.each的一切,因为那太慢了。
            • @StefanSteiger 1. 然后你应该更正你的决策关系,因为它说我们根本无法使用 RegExp 进行搜索,这不是真的 2. 它不使用 jQuery.each .什么让你有那个想法? 3. 这不是真的,至少在 Firefox 中是这样。 &amp;auml; 例如即使使用innerHTML,也会转换为实际字符。
            • 嗨@StefanSteiger 实际上,我正在使用您的解决方案。这个很完美。但是有一些问题,例如,如果我有一个 P ,其中有两个跨度,一个跨度有 Diploma MSBTE 之类的数据,第二个跨度有数据 2012 。现在,如果我要突出显示的字符串是 Diploma MSBTE 2012 ,那么我检查了这整个字符串不起作用,如果要匹配的所有内容都存在于一个跨度中,那么它可以工作,但是如果文本内容在 diff 标签中然后这是行不通的。你能谈谈这个吗?
            【解决方案8】:

            快进到 2019 年,Web API 现在原生支持突出显示文本:

            const selection = document.getSelection();
            selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
            

            你可以走了! anchorNode 是选择开始节点,focusNode 是选择结束节点。而且,如果它们是文本节点,offset 是各个节点中开始和结束字符的索引。这是documentation

            他们甚至有一个live demo

            【讨论】:

            • 哦,这太棒了。只需像这样使用它: selection.setBaseAndExtent(desiredNode, 0, desiredNode, 1);突出显示您需要的唯一节点。它适用于古腾堡
            • 不错,但仍主要标记为实验性。
            【解决方案9】:
            function stylizeHighlightedString() {
            
                var text = window.getSelection();
            
                // For diagnostics
                var start = text.anchorOffset;
                var end = text.focusOffset - text.anchorOffset;
            
                range = window.getSelection().getRangeAt(0);
            
                var selectionContents = range.extractContents();
                var span = document.createElement("span");
            
                span.appendChild(selectionContents);
            
                span.style.backgroundColor = "yellow";
                span.style.color = "black";
            
                range.insertNode(span);
            }
            

            【讨论】:

            • Mohit,欢迎来到 SO。代码的一些描述会很好!
            • 是否应该有一种方法可以在不创建另一个节点的情况下选择文本?
            • @user191433 问题不仅在于选择文本,还在于应用样式。为此,您需要一个节点。
            • 提醒/提示 JavaScript span.style.backgroundColor = "yellow"; 转换为 CSS style="background-color: yellow;" ——骆驼大写法和虚线表示法之间的细微差别一开始让我大吃一惊。
            • P.S. Mohit 在stackoverflow.com/questions/7991474/… 的回答是此代码的更精简的变体。 (例如,此处省略仅用于诊断/不起作用的开始和结束变量。)
            【解决方案10】:

            您可以使用 jquery highlight effect

            但是如果你对原始的 javascript 代码感兴趣,看看我得到了什么 只需将粘贴复制到 HTML 中,打开文件并单击“突出显示” - 这应该突出显示“狐狸”一词。性能方面,我认为这适用于小文本和单次重复(如您指定)

            function highlight(text) {
              var inputText = document.getElementById("inputText");
              var innerHTML = inputText.innerHTML;
              var index = innerHTML.indexOf(text);
              if (index >= 0) { 
               innerHTML = innerHTML.substring(0,index) + "<span class='highlight'>" + innerHTML.substring(index,index+text.length) + "</span>" + innerHTML.substring(index + text.length);
               inputText.innerHTML = innerHTML;
              }
            }
            .highlight {
              background-color: yellow;
            }
            <button onclick="highlight('fox')">Highlight</button>
            
            <div id="inputText">
              The fox went over the fence
            </div>

            编辑:

            使用replace

            我看到这个答案获得了一些人气,我想我可以补充一下。 您也可以轻松使用替换

            "the fox jumped over the fence".replace(/fox/,"&lt;span&gt;fox&lt;/span&gt;");

            或者对于多次出现(与问题无关,但在 cmets 中被询问),您只需在替换正则表达式上添加 global

            "the fox jumped over the other fox".replace(/fox/g,"&lt;span&gt;fox&lt;/span&gt;");

            希望这对感兴趣的评论者有所帮助。

            将 HTML 替换为整个网页

            要替换整个网页的 HTML,您应该参考文档正文的innerHTML

            document.body.innerHTML

            【讨论】:

            • 非常感谢您的回复,但您能告诉我如何在javascript本身中指定颜色
            • 您可以将"&lt;span class='highlight'&gt;" 替换为"&lt;span style='color: " + color + ";'&gt;",颜色应该类似于var color = "#ff0000";
            • 如果我想突出显示整个页面上所有出现的单词怎么办?@guy mograbi
            • 使用简单的“替换”是一个坏主意。我在这里描述了原因:stackoverflow.com/a/32758672/3894981
            • 这不是一个好主意,因为这将尝试突出显示 HTML 标记/属性/等。例如,在以下情况下会发生什么:&lt;img src="fox.jpg" /&gt; 你会得到无效的 HTML,看起来像:&lt;img src="&lt;span class='highlight'&gt;fox&lt;/span&gt;.jpg" /&gt; 不好
            【解决方案11】:

            其他解决方案都不能真正满足我的需求,尽管 Stefan Steiger 的解决方案按我的预期工作,但我发现它有点过于冗长。

            以下是我的尝试:

            /**
             * Highlight keywords inside a DOM element
             * @param {string} elem Element to search for keywords in
             * @param {string[]} keywords Keywords to highlight
             * @param {boolean} caseSensitive Differenciate between capital and lowercase letters
             * @param {string} cls Class to apply to the highlighted keyword
             */
            function highlight(elem, keywords, caseSensitive = false, cls = 'highlight') {
              const flags = caseSensitive ? 'gi' : 'g';
              // Sort longer matches first to avoid
              // highlighting keywords within keywords.
              keywords.sort((a, b) => b.length - a.length);
              Array.from(elem.childNodes).forEach(child => {
                const keywordRegex = RegExp(keywords.join('|'), flags);
                if (child.nodeType !== 3) { // not a text node
                  highlight(child, keywords, caseSensitive, cls);
                } else if (keywordRegex.test(child.textContent)) {
                  const frag = document.createDocumentFragment();
                  let lastIdx = 0;
                  child.textContent.replace(keywordRegex, (match, idx) => {
                    const part = document.createTextNode(child.textContent.slice(lastIdx, idx));
                    const highlighted = document.createElement('span');
                    highlighted.textContent = match;
                    highlighted.classList.add(cls);
                    frag.appendChild(part);
                    frag.appendChild(highlighted);
                    lastIdx = idx + match.length;
                  });
                  const end = document.createTextNode(child.textContent.slice(lastIdx));
                  frag.appendChild(end);
                  child.parentNode.replaceChild(frag, child);
                }
              });
            }
            
            // Highlight all keywords found in the page
            highlight(document.body, ['lorem', 'amet', 'autem']);
            .highlight {
              background: lightpink;
            }
            <p>Hello world lorem ipsum dolor sit amet, consectetur adipisicing elit. Est vel accusantium totam, ipsum delectus et dignissimos mollitia!</p>
            <p>
              Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam, corporis.
              <small>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium autem voluptas perferendis dolores ducimus velit error voluptatem, qui rerum modi?</small>
            </p>

            如果您的关键字可能包含需要在正则表达式中转义的特殊字符,我还建议使用类似 escape-string-regexp 的内容:

            const keywordRegex = RegExp(keywords.map(escapeRegexp).join('|')), flags);
            

            【讨论】:

            • 这对我来说效果很好,但它也需要一种“取消标记”的方法'
            • 效果很好。谢谢。 @param {boolean} caseSensitive 正好相反
            【解决方案12】:

            这是我的正则表达式纯 JavaScript 解决方案:

            function highlight(text) {
                document.body.innerHTML = document.body.innerHTML.replace(
                    new RegExp(text + '(?!([^<]+)?<)', 'gi'),
                    '<b style="background-color:#ff0;font-size:100%">$&</b>'
                );
            }
            

            【讨论】:

            • 当我试图突出显示的文本块包含 HTML 标记时,这对我来说非常有效。
            • 您还可以调整函数以通过正则表达式管道符号接受多个单词,例如one|two|three
            • 如果文本结尾有&gt; 字符,它不会替换文本。使用(?!([^&lt;]+)?&lt;) 修改正则表达式以使其工作。
            • 按要求修改。
            • 完美!这对我来说是最好的
            【解决方案13】:

            我也想知道,你可以试试我在this 帖子上学到的东西。

            我用过:

            function highlightSelection() {
            			var userSelection = window.getSelection();
            			for(var i = 0; i < userSelection.rangeCount; i++) {
            				highlightRange(userSelection.getRangeAt(i));
            			}
            			
            		}
            			
            			function highlightRange(range) {
            			    var newNode = document.createElement("span");
            			    newNode.setAttribute(
            			       "style",
            			       "background-color: yellow; display: inline;"
            			    );
            			    range.surroundContents(newNode);
            			}
            <html>
            	<body contextmenu="mymenu">
            
            		<menu type="context" id="mymenu">
            			<menuitem label="Highlight Yellow" onclick="highlightSelection()" icon="/images/comment_icon.gif"></menuitem>
            		</menu>
            		<p>this is text, select and right click to high light me! if you can`t see the option, please use this<button onclick="highlightSelection()">button </button><p>

            你也可以在这里试试:http://henriquedonati.com/projects/Extension/extension.html

            xc

            【讨论】:

              【解决方案14】:

              为什么使用自制的高亮功能是个坏主意

              从头开始构建自己的突出显示功能可能不是一个好主意,因为您肯定会遇到其他人已经解决的问题。挑战:

              • 您需要删除带有 HTML 元素的文本节点以突出显示您的匹配项,而不会破坏 DOM 事件并一遍又一遍地触发 DOM 重新生成(例如 innerHTML 就是这种情况)
              • 如果要删除突出显示的元素,则必须删除 HTML 元素及其内容,还必须合并拆分的文本节点以进行进一步搜索。这是必要的,因为每个荧光笔插件都会在文本节点内搜索匹配项,如果您的关键字将被拆分为多个文本节点,它们将不会被找到。
              • 您还需要构建测试以确保您的插件在您没有考虑过的情况下工作。我说的是跨浏览器测试!

              听起来很复杂?如果您想要一些功能,例如忽略突出显示中的某些元素、变音符号映射、同义词映射、iframe 内搜索、分词搜索等,这将变得越来越复杂。

              使用现有插件

              当使用现有的、实施良好的插件时,您不必担心上面提到的事情。 Sitepoint 上的文章 10 jQuery text highlighter plugins 比较了流行的荧光笔插件。

              看看mark.js

              mark.js 就是这样一个用纯 JavaScript 编写的插件,但也可以作为 jQuery 插件使用。它的开发旨在提供比其他插件更多的机会,并提供以下选项:

              • 单独搜索关键字而不是完整的字词
              • 地图变音符号(例如,如果“justo”也应该匹配“justò”)
              • 忽略自定义元素内的匹配项
              • 使用自定义突出显示元素
              • 使用自定义高亮类
              • 映射自定义同义词
              • 也在 iframe 内搜索
              • 收到未找到的条款

              DEMO

              您也可以看到this fiddle

              使用示例

              // Highlight "keyword" in the specified context
              $(".context").mark("keyword");
              
              // Highlight the custom regular expression in the specified context
              $(".context").markRegExp(/Lorem/gmi);
              

              它是在 GitHub (project reference) 上免费开发的开源软件。

              【讨论】:

              • 单独突出显示文本不足以成为我包含 jQuery 的充分理由。
              • @Roy 我已经把它记在心里了。好消息,从 v6.0.0 开始,mark.js 放弃了 jQuery 依赖项,现在可以选择将其用作 jQuery 插件。
              • 全部为真,除了:第一点是不可能的,因为您无法获得注册的事件处理程序,即使可以,您也无法设置匿名函数...第二:mark.js 没有在两个标签之间查找文本,例如sed 不会找到 sed... 第 3:每当出现您尚未测试的浏览器(包括新版本)时,它可能会损坏。无论您编写多少测试,这始终是正确的。 17kb 的标记对于它的功能来说太大了。
              • 您指的是@StefanSteiger 的哪些要点?如果没有这些信息,就无法对第一点说些什么。但是,第二条注释是错误的,mark.js 可以使用acrossElements 选项找到标签之间的匹配项。第三条评论;与它提供的功能相比,mark.js 并不大。不,将来不太可能出现问题,因为 mark.js 已经过测试,例如从 Chrome 30 开始,以及在所有具有跨浏览器单元测试的较新版本中,即将推出的版本从未出现任何问题。
              • 别人的图书馆还是“自制”的。
              【解决方案15】:

              简单的 TypeScript 示例

              注意:虽然我在很多方面都同意@Stefan,但我只需要一个简单匹配突出显示:

              module myApp.Search {
                  'use strict';
              
                  export class Utils {
                      private static regexFlags = 'gi';
                      private static wrapper = 'mark';
              
                      private static wrap(match: string): string {
                          return '<' + Utils.wrapper + '>' + match + '</' + Utils.wrapper + '>';
                      }
              
                      static highlightSearchTerm(term: string, searchResult: string): string {
                          let regex = new RegExp(term, Utils.regexFlags);
              
                          return searchResult.replace(regex, match => Utils.wrap(match));
                      }
                  }
              }
              

              然后构造实际结果:

              module myApp.Search {
                  'use strict';
              
                  export class SearchResult {
                      id: string;
                      title: string;
              
                      constructor(result, term?: string) {
                          this.id = result.id;
                          this.title = term ? Utils.highlightSearchTerm(term, result.title) : result.title;
                      }
                  }
              }
              

              【讨论】:

                【解决方案16】:

                Range 类型上使用surroundContents() 方法。它唯一的参数是将包装该范围的元素。

                function styleSelected() {
                  bg = document.createElement("span");
                  bg.style.backgroundColor = "yellow";
                  window.getSelection().getRangeAt(0).surroundContents(bg);
                }
                

                【讨论】:

                  【解决方案17】:

                  从 HTML5 开始,您可以使用 &lt;mark&gt;&lt;/mark&gt; 标签来突出显示文本。您可以使用 javascript 在这些标签之间包装一些文本/关键字。下面是一个如何标记和取消标记文本的小示例。

                  JSFIDDLE DEMO

                  【讨论】:

                  • innerHTML 很危险。它将删除事件。
                  • 这也不能正常工作,因为例如,如果你进入 JSFIDDLE “Lorem”,它只标记它的第一个实例。
                  • 你只需要替换所有出现的关键字。这是一个全局正则表达式的示例jsfiddle.net/de5q704L/73
                  【解决方案18】:

                  我有同样的问题,一堆文本是通过 xmlhttp 请求进来的。此文本为 html 格式。我需要突出显示每一个事件。

                  str='<img src="brown fox.jpg" title="The brown fox" />'
                      +'<p>some text containing fox.</p>'
                  

                  问题是我不需要突出显示标签中的文本。例如我需要突出显示狐狸:

                  现在我可以将其替换为:

                  var word="fox";
                  word="(\\b"+ 
                      word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
                          + "\\b)";
                  var r = new RegExp(word,"igm");
                  str.replace(r,"<span class='hl'>$1</span>")
                  

                  回答您的问题:您可以在正则表达式选项中省略 g,并且只会替换第一个出现的位置,但这仍然是 img src 属性中的那个并破坏图像标签:

                  <img src="brown <span class='hl'>fox</span>.jpg" title="The brown <span 
                  class='hl'>fox</span> />
                  

                  这是我解决它的方法,但想知道是否有更好的方法,我在正则表达式中错过了一些东西:

                  str='<img src="brown fox.jpg" title="The brown fox" />'
                      +'<p>some text containing fox.</p>'
                  var word="fox";
                  word="(\\b"+ 
                      word.replace(/([{}()[\]\\.?*+^$|=!:~-])/g, "\\$1")
                      + "\\b)";
                  var r = new RegExp(word,"igm");
                  str.replace(/(>[^<]+<)/igm,function(a){
                      return a.replace(r,"<span class='hl'>$1</span>");
                  });
                  

                  【讨论】:

                  • 这是唯一一个对我有用且不会与&lt;img src="word"&gt;&lt;a href="word"&gt; 混淆的正则表达式解决方案。
                  • 黄金法则:从不。采用。常规的。表达式。到。混乱。关于。和。 XML。
                  猜你喜欢
                  • 2013-04-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-05-28
                  • 2011-09-08
                  • 2011-02-21
                  • 2017-02-04
                  相关资源
                  最近更新 更多