用jQuery突出显示一个单词


101

我基本上需要突出显示文本块中的特定单词。例如,假装我想在文本中突出显示“ dolor”一词:

<p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

我如何将以上内容转换为如下形式:

<p>
    Lorem ipsum <span class="myClass">dolor</span> sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer <span class="myClass">dolor</span> ullamcorper
    libero. Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>

jQuery有可能吗?

编辑:正如塞巴斯蒂安 指出的那样,如果没有jQuery,这是完全有可能的-但我希望可以有一种特殊的jQuery方法,该方法可以让您对文本本身进行选择。我已经在该站点上大量使用了jQuery,因此将所有内容都包裹在jQuery中可能会使事情变得更整洁。



嘿,我写了一个完全做到这一点的插件-就像mhansen发布的Johann Burkard插件一样,但是使用正则表达式而不是字符串。在github上检查一下,如果您需要其他功能,请告诉我。


1
从语义上讲<span>,与其使用a突出显示单词<mark>,不如使用它更正确。
Jose Rui Santos'3

嗨,我来晚了,但这是另一个代码段,可帮助您根据标签突出显示和过滤文本。希望这将有助于某人使用jQuery插件进行文本突出显示和过滤
Jaspreet Chahal 2012年

Answers:


85

尝试突出显示:JavaScript文本突出显示jQuery插件!警告-此页面上的源代码包含加密货币挖掘脚本,请使用下面的代码,或者从网站上的下载中删除挖掘脚本。!

/*

highlight v4

Highlights arbitrary terms.

<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>

MIT license.

Johann Burkard
<http://johannburkard.de>
<mailto:jb@eaio.com>

*/

jQuery.fn.highlight = function(pat) {
 function innerHighlight(node, pat) {
  var skip = 0;
  if (node.nodeType == 3) {
   var pos = node.data.toUpperCase().indexOf(pat);
   if (pos >= 0) {
    var spannode = document.createElement('span');
    spannode.className = 'highlight';
    var middlebit = node.splitText(pos);
    var endbit = middlebit.splitText(pat.length);
    var middleclone = middlebit.cloneNode(true);
    spannode.appendChild(middleclone);
    middlebit.parentNode.replaceChild(spannode, middlebit);
    skip = 1;
   }
  }
  else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
   for (var i = 0; i < node.childNodes.length; ++i) {
    i += innerHighlight(node.childNodes[i], pat);
   }
  }
  return skip;
 }
 return this.length && pat && pat.length ? this.each(function() {
  innerHighlight(this, pat.toUpperCase());
 }) : this;
};

jQuery.fn.removeHighlight = function() {
 return this.find("span.highlight").each(function() {
  this.parentNode.firstChild.nodeName;
  with (this.parentNode) {
   replaceChild(this.firstChild, this);
   normalize();
  }
 }).end();
};

还可以尝试原始脚本“更新”版本

/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

jQuery.extend({
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match) {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                wordNode.parentNode.replaceChild(highlight, wordNode);
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);

    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    words = jQuery.map(words, function(word, i) {
      return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);

    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
};

有两种解决方案,每个解决方案都包含在一个文件中。我在上面添加了它们。至少在最坏的情况下,它们在编辑历史记录中始终可用。
艾里克·罗伯逊

突出显示v4有点问题。Burkard主页上有一个修复程序: johannburkard.de/blog/programming/javascript / ...在这种情况下,在此处复制代码不是一个好主意。链接指向最新版本(现在:)。
Lerin Sonberg 2015年

顺便说一句,<mark>标签可能比这里的<span>标签更好。
unitario

1
如果您正在寻找小型轻巧的产品,那么突出显示jquery插件确实是您的最佳选择。突出显示和删除与给定文本匹配的突出显示非常有用。如果您需要正则表达式或其他支持;但是,请从高亮页面中检出mark.js或任何扩展名和派生所链接的高亮。因为轻量级功能受到高度赞赏,所以我会突出自己而不是其他人。
格雷格

3
重要信息:约翰·伯卡德(Johann Burkard)在其网站上提供的源代码中包含了一个挖掘脚本!
卢卡斯

42
function hiliter(word, element) {
    var rgxp = new RegExp(word, 'g');
    var repl = '<span class="myClass">' + word + '</span>';
    element.innerHTML = element.innerHTML.replace(rgxp, repl);
}
hiliter('dolor');

2
您不想使用innerHTML,因为它是Microsoft在80年代引入的,后来又像往常一样被Microsoft再次删除了。即使大多数浏览器都支持它,但W3C标准都是一切。
史蒂夫·K

21
代替innerHTML应该使用什么?
Kebman

15
@Sir Ben Benji先生:我认为您是将innerHTML与innerText(由Microsoft开发的textContent替代品,这确实是规范的混乱)混淆了。innerHTML可能已作为Microsoft扩展开始,但丝毫没有被“丢弃”;自2000年代初以来,所有主流浏览器都支持它,并且它是HTML5的一部分(最早于2008年):w3.org/TR/2008/WD-html5-20080610/dom.html#innerhtml它仍然存在于最新版本中在w3.org/TR/DOM-Parsing上进行了修订。另请参阅w3.org/TR/html5/references.html#refsDOMPARSING
Jay Dansand

1
这不是一个很好的解决方案。我只是用这个,但是如果我搜索“ person”,它也会用“ person”替换所有类和html元素。而且小写和大写也没有集成。var rgxp = new RegExp(“(\\ b” + word +“ \\ b)”,“ gim”); 修复了该问题,但我仍然认为代码不应替换html元素。
理查德·林德豪特

32

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

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

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

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

使用现有的插件

使用现有的,实现良好的插件时,您不必担心上面提到的事情。Sitepoint上的文章10 jQuery文本荧光笔插件比较了流行的荧光笔插件。这包括此问题的答案插件。

看看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上开源(项目参考)。


11

这是一个忽略并保留大小写的变体:

jQuery.fn.highlight = function (str, className) {
    var regex = new RegExp("\\b"+str+"\\b", "gi");

    return this.each(function () {
        this.innerHTML = this.innerHTML.replace(regex, function(matched) {return "<span class=\"" + className + "\">" + matched + "</span>";});
    });
};

6
这适用于纯文本,但似乎并不排除标签和属性。例如,当您在innerHTML中的div上具有class属性时,搜索“ lass”。
乔纳森·

如何调用此函数?
jiy

innerHTML是邪恶的,请在此处查看我的答案。另外,\\b不适用于unicode字符。此外,此功能几乎错过任何事情,例如在嵌套子项中搜索。
花花公子

3

您可以使用以下功能突出显示文本中的任何单词。

function color_word(text_id, word, color) {
    words = $('#' + text_id).text().split(' ');
    words = words.map(function(item) { return item == word ? "<span style='color: " + color + "'>" + word + '</span>' : item });
    new_words = words.join(' ');
    $('#' + text_id).html(new_words);
    }

只需针对包含文本的元素选择要着色的词和选择的颜色即可

这是一个例子

<div id='my_words'>
This is some text to show that it is possible to color a specific word inside a body of text. The idea is to convert the text into an array using the split function, then iterate over each word until the word of interest is identified. Once found, the word of interest can be colored by replacing that element with a span around the word. Finally, replacing the text with jQuery's html() function will produce the desired result.
</div>

用法

color_word('my_words', 'possible', 'hotpink')

在此处输入图片说明

Azle对此也有很好的功能。它使用类,因此只需将类名称分配给要定位的任何文本块。

az.style_word("target_class", target_instance, {
     "this_class" : "pink_word",
     "word" : "possible", // list any CSS styling after this line ...
     "color" : "hotpink", 
     "font-weight" : "bold"
})

2

您可以使用我的突出显示插件jQuiteLight,该插件也可以与正则表达式一起使用。

要使用npm进行安装,请输入:

npm install jquitelight --save

要使用凉亭类型安装:

bower install jquitelight 

用法:

// for strings
$(".element").mark("query here");
// for RegExp
$(".element").mark(new RegExp(/query h[a-z]+/));

这里更高级的用法


@ user3631654否,这是一个不同的插件。我的插件可以与RegExp一起使用,并具有智能突出显示功能。如果您已包含在此插件之前提到的插件,则可以使用var oldMark = $.fn.mark.noConflict()
iamawebgeek,2016年

好像jquery.mark有一种方法markRegExp()也可以突出显示自定义正则表达式。所以这不应该是一个争论。
user3631654 '16

@zazu,“智能高亮”是什么意思?
user3631654 '16

@ user3631654如果您打开智能突出显示并传递单词“后果”,它也会突出显示单词“后果”及其其他形式,但是如果您传递“ the”或“ bla”,则不会采用“ theme”或“ black”
iamawebgeek '16

2

JSFiddle

使用.each()、. replace()、. html()。经过jQuery 1.11和3.2测试。

在上面的示例中,读取要突出显示的“关键字”,并在跨度标签后附加“ highlight”类。.each()中所有选定类的文本“关键字”都突出显示。

的HTML

<body>
   <label name="lblKeyword" id="lblKeyword" class="highlight">keyword</label>
   <p class="filename">keyword</p>
   <p class="content">keyword</p>
   <p class="system"><i>keyword</i></p>
</body>

JS

$(document).ready(function() {
   var keyWord = $("#lblKeyword").text(); 
   var replaceD = "<span class='highlight'>" + keyWord + "</span>";
   $(".system, .filename, .content").each(function() {
      var text = $(this).text();
      text = text.replace(keyWord, replaceD);
      $(this).html(text);
   });
});

的CSS

.highlight {
    background-color: yellow;
}


1

我编写了一个非常简单的函数,该函数使用jQuery来用.highlight类迭代包装每个关键字的元素。

function highlight_words(word, element) {
    if(word) {
        var textNodes;
        word = word.replace(/\W/g, '');
        var str = word.split(" ");
        $(str).each(function() {
            var term = this;
            var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
            textNodes.each(function() {
              var content = $(this).text();
              var regex = new RegExp(term, "gi");
              content = content.replace(regex, '<span class="highlight">' + term + '</span>');
              $(this).replaceWith(content);
            });
        });
    }
}

更多信息:

http://www.hawkee.com/snippet/9854/


2
这不会在嵌套元素中搜索,没有删除突出显示的功能,也没有许可证信息。
花花公子

您介意向我解释“新RegExp(term,“ gi”)“中的'gi'是什么吗?
vuquanghoang '19

0

我创建了一个类似概念的存储库,该存储库更改了html5可以识别其颜色的文本的颜色(我们不必使用实际的#rrggbb值,而可以将html5的名称标准化为其中的140个左右)

colors.js colors.js

$( document ).ready(function() {
	
	function hiliter(word, element) {
		var rgxp = new RegExp("\\b" + word + "\\b" , 'gi'); // g modifier for global and i for case insensitive 
		var repl = '<span class="myClass">' + word + '</span>';
		element.innerHTML = element.innerHTML.replace(rgxp, repl);
			
			};

	hiliter('dolor', document.getElementById('dolor'));
});
.myClass{

background-color:red;
}
<!DOCTYPE html>
<html>
	<head>
		<title>highlight</title>
		
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
	
		 <link href="main.css" type="text/css"  rel="stylesheet"/>
		 
	</head>
	<body id='dolor'>
<p >
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
</p>
<p>
    Quisque bibendum sem ut lacus. Integer dolor ullamcorper libero.
    Aliquam rhoncus eros at augue. Suspendisse vitae mauris.
</p>
 <script type="text/javascript" src="main.js" charset="utf-8"></script>
	</body>
</html>


-2

是否可以得到以上示例:

jQuery.fn.highlight = function (str, className)
{
    var regex = new RegExp(str, "g");

    return this.each(function ()
    {
        this.innerHTML = this.innerHTML.replace(
            regex,
            "<span class=\"" + className + "\">" + str + "</span>"
        );
    });
};

不要替换html-tags之类的文本,否则会破坏页面。


-2
$(function () {
    $("#txtSearch").keyup(function (event) {
        var txt = $("#txtSearch").val()
        if (txt.length > 3) {
            $("span.hilightable").each(function (i, v) {
                v.innerHTML = v.innerText.replace(txt, "<hilight>" + txt + "</hilight>");
            });

        }
    });
});

Jfiddle在这里


hilight是无效的HTML元素
user3631654'3

只需忽略此警告,<hilight>是您的自定义元素,您就可以编写任何内容。你看过小提琴吗?
L.Grillo'3

@nickf我的脚本所做的事情与接受的答案完全相同
L.Grillo
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.