如何使用JavaScript突出显示文本


98

有人可以通过可以在网页上突出显示文本的JavaScript函数来帮助我。要求是-仅突出显示一次,而不像我们在搜索情况下突出显示所有出现的文本。


4
如果您发布该函数的代码,我们将为您提供帮助。如果您要求我们为您创建此类功能,则可能性较小。您必须自己做一些事情。开始做某事,遇到困难时再回来。
Felix Kling

7
是的,我已经阅读了《如何问》,我自己做了一些事情,但是我被困住了,这就是为什么我问。我在Android上工作,对javasript却一无所知,这就是为什么我不能自己做的原因。早些时候,我使用了其他的javascript来完成这项工作,但并非没有一定的限制。在问这个问题时,我可能没有使用正确的词,对此我感到抱歉,但是请不要以为然。
Ankit

1
这个插件可能会让您感兴趣:github.com/julmot/jmHighlight。它可以单独突出显示关键字或作为术语突出显示,可以突出显示与您的自定义元素和类名匹配的内容,还可以搜索变音符号。最重要的是,它允许您筛选搜索匹配项的上下文。
花花公子

1
按照正则表达式的方式结帐... stackoverflow.com/a/45519242/2792959

我在此处准备了一篇文章,exhesham.com/2017/11/20/…
Hesham Yassin

Answers:


101

您可以使用jquery 突出显示效果

但是,如果您对原始javascript代码感兴趣,请看一下我得到的内容。简单地将粘贴复制到HTML中,打开文件并单击“突出显示”-这应该突出显示“ fox”一词。在性能方面,我认为这适用于小文本和单个重复(如您指定的那样)

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

我看到这个答案越来越受欢迎,我想我可以补充一下。您也可以轻松使用replace

"the fox jumped over the fence".replace(/fox/,"<span>fox</span>");

或者对于多次出现(与问题不相关,但在注释中被询问),您只需添加global替换正则表达式即可。

"the fox jumped over the other fox".replace(/fox/g,"<span>fox</span>");

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

将HTML替换为整个网页

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

document.body.innerHTML


非常感谢您的答复,但您还能告诉我如何在javascript中指定颜色吗?
-Ankit

你可以替换"<span class='highlight'>"使用"<span style='color: " + color + ";'>",颜色应该是这样的var color = "#ff0000";
Yaniro

如果我想突出显示整个页面上某个单词的所有出现,该怎么办?@guy mograbi
Baqer Naqvi

4
使用简单的“替换”是一个坏主意。我在这里描述了原因:stackoverflow.com/a/32758672/3894981
花花公子

2
这不是一个好主意,因为这将尝试突出显示HTML标签/属性/等。例如,在以下情况下将发生的情况: <img src="fox.jpg" /> 您将获得如下所示的无效HTML:<img src="<span class='highlight'>fox</span>.jpg" /> 不好
dcporter7

46

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

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

你需要做什么:

遍历HTML文档,找到所有文本节点,获取textContent,使用来获取高亮文本的位置indexOftoLowerCase如果不区分大小写,则带有可选项),将indexofas 之前的所有内容textNode附加到,用高亮范围附加匹配的Text,并对其余的textnode重复此操作(突出显示字符串可能在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, '%')[不应该使用fulltext-search或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(因为CAN有成千上万的结果),好奇,如果这种方法会增加高延迟的延迟加载。
Pogrindis

5
抱歉,您的论点都不对。1.您绝对可以使用RegExp,您不应在元素的HTML值内而是在文本值内进行搜索。2.绝对可以将RegExp与变音符号一起使用,如mark.js中所实现的。3. HTML符号将转换为浏览器DOM中的实际字符,因此您也绝对会使用它们!
花花公子

1
@julmot; 到1:这意味着您需要遍历每个元素,而这正是我要做的。除非您不担心失去格式,否则可以在document.body.innerText中搜索,这会非常慢。3.不是在DOM中,而是在text-element的innerText或textContent属性中。这再次意味着您需要遍历文本元素;regEx AFAIK无法完成。2:不知道mark.js,但是我会避免做jQuery.each的所有事情,因为那太慢了。
Stefan Steiger

1
@StefanSteiger 1.然后,您应该更正您的决策关系,因为它说我们根本不能使用RegExp进行搜索,这是不正确的。2.它不使用jQuery.each。什么让你有那个想法?3.至少在Firefox中不是这样。&auml;即使使用,eg也将转换为实际字符innerHTML
花花公子

1
您好@StefanSteiger实际上,我正在使用您的解决方案。这是完美的。但是有一些问题,例如,如果II具有一个P,其中有两个跨度,一个跨度具有Diploma MSBTE之类的数据,而第二个跨度具有2012年的数据。现在,如果我要突出显示的字符串是Diploma MSBTE 2012,则整个字符串我都检查不到,如果要匹配的所有内容都存在一个跨度中,那么它将起作用,但是如果文本内容位于diff标签中,则这是行不通的。你能谈谈这个吗?
ganeshk '18

41

为什么使用自制的突出显示功能是个坏主意

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

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

听起来复杂吗?如果您需要某些功能,例如忽略突出显示,变音符号映射,同义词映射,iframe内搜索,分隔词搜索等某些元素,则此功能将变得越来越复杂。

使用现有的插件

使用现有的,实现良好的插件时,您不必担心上面提到的事情。文章10 jQuery的文本荧光笔插件上Sitepoint比较流行的高亮插件。

看看mark.js

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

  • 分别搜索关键字而不是整个术语
  • 地图变音符号(例如,如果“ justo”也应匹配“justò”)
  • 忽略自定义元素中的匹配项
  • 使用自定义突出显示元素
  • 使用自定义突出显示类
  • 地图自定义同义词
  • 还在iframe中搜索
  • 收到未找到的条款

演示

或者,您可以看到这个小提琴

用法示例

// Highlight "keyword" in the specified context
$(".context").mark("keyword");

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

它是免费的,并在GitHub上开源(项目参考)。


4
仅突出显示文本不足以使我包含jQuery。
罗伊

10
@罗伊,我对此深信不疑。好消息是,从v6.0.0版本起,mark.js放弃了jQuery依赖关系,现在可以选择将其用作jQuery插件。
花花公子

都是正确的,除了:第一点是不可能的,因为您无法获得注册的事件处理程序,即使可以,也无法设置匿名函数...第二个:mark.js也不在两个标签之间找到文本,例如<span> s </ span> ed找不到sed ...第三:只要出现浏览器(包括新版本),而您尚未对其进行测试,它可能会损坏。无论您编写了多少测试,这始终是正确的。标记为17kb,太大了。
Stefan Steiger,

您指的是@StefanSteiger?没有这些信息就无法说出第一点。但是,第二条评论是错误的,mark.js可以使用acrossElements选项在标签之间找到匹配项。第三点评论;与它提供的功能相比,mark.js并不大。不,将来不太可能出现问题,因为对mark.js进行了测试,例如,启动了Chrome 30以及所有具有跨浏览器单元测试的较新版本,并且以后的版本永远不会出现任何问题。
花花公子

@dude:第一段之后的三点。嗯,好的,在我观看的演示中缺少该选项。在这种情况下,这可能是有道理的。但是,我发现它太大了。
Stefan Steiger,

10
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);
}

3
Mohit,欢迎来到SO。代码的一些描述会很好!
Nippey 2012年

不应该有一种无需创建另一个节点即可选择文本的方法吗?
戴夫·格雷戈里

@ user191433的问题不仅在于选择文本,还在于应用样式。为此,您需要一个节点。
Christophe

提醒/提示,JavaScript可以span.style.backgroundColor = "yellow";转换为CSS style="background-color: yellow;"- camelCase和破折号之间的细微差别一开始让我感到震惊。
MarkHu 2013年

1
PS Mohit在stackoverflow.com/questions/7991474/…上的答案是此代码的更简化变体。(例如,此处省略仅用于诊断/不起作用的开始和结束变量。)
MarkHu 2013年

7

这是我的regexp纯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
KlemenTušar2015年

如果文本末尾有>字符,它将不会替换文本。使用(?!([^<]+)?<)它修改正则表达式。
Archie Reyes

根据要求修改。
KlemenTušar16年

完善!这对我来说是最好的
marco burrometo

5

我有同样的问题,一堆文本通过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>")

要回答您的问题:您可以在regexp选项中省略g,仅将替换第一个匹配项,但这仍然是img src属性中的那个,并破坏了image标签:

<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>");
});

这是唯一对我有效而又不会弄乱<img src="word">or的正则表达式解决方案<a href="word">
yvesmancera 2015年

1
黄金法则:永不。用。定期。表达式。至。乱了 关于。用。XML。
ScottMcGready

5

其他解决方案都不能真正满足我的需求,尽管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);

这个工作很适合我,但它也需要一种方式来“取消标记””
jwzumwalt

4

简单的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;
        }
    }
}

3

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

JSFIDDLE演示


innerHTML是危险的。它将删除事件。
花花公子

2
这也不能正常工作,因为例如,如果您输入JSFIDDLE“ Lorem”,则仅标记它的第一个实例。
agm1984年

1
您只需要替换所有出现的关键字即可。这是全球正则表达式的示例jsfiddle.net/de5q704L/73
kasper Taeymans

2

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

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

而且你很好走!anchorNode是选择开始节点,focusNode是选择结束节点。并且,如果它们是文本节点,offset则是相应节点中开始和结束字符的索引。这是文档

他们甚至有现场演示


哦,这太棒了。像这样简单地使用它:selection.setBaseAndExtent(desiredNode,0,wantedNode,1); 突出显示您需要的唯一节点。它与古腾堡一起工作
tonyAndr

1

我也想知道,您可以尝试我在这篇文章中学到的知识。

我用了:

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

c



-1

Range类型上使用SurroundContents()方法。它唯一的参数是一个将包裹Range的元素。

function styleSelected() {
  bg = document.createElement("span");
  bg.style.backgroundColor = "yellow";
  window.getSelection().getRangeAt(0).surroundContents(bg);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.