使用 jQuery 突出显示一个单词
Posted
技术标签:
【中文标题】使用 jQuery 突出显示一个单词【英文标题】:Highlight a word with jQuery 【发布时间】:2010-09-12 06:39:17 【问题描述】:我基本上需要突出显示文本块中的特定单词。例如,假设我想在这段文字中突出显示“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 实现吗?
编辑:作为Sebastianpointed out,如果没有jQuery,这很可能 - 但我希望可能有一种特殊的jQuery方法可以让您对文本本身进行选择器。我已经在这个网站上大量使用 jQuery,因此将所有内容都包含在 jQuery 中可能会让事情变得更整洁。
【问题讨论】:
这可能也很有趣:jquery.info/The-plugin-SearchHighlight 嘿,我写了一个插件来做这个——它就像约翰伯卡德插件 mlarsen 发布的一样,但使用正则表达式而不是字符串。 Check it out on github,如果您需要其他功能,请告诉我。 如果您需要 jQuery 高亮插件的宽松版本:http://www.frightanic.com/2011/02/27/lenient-jquery-highlight-plugin-javascript/ 从语义上讲,使用<mark>
而不是使用<span>
突出显示单词更正确。
您好,我迟到了,但这里还有另一个代码 sn-p,它有助于根据标签突出显示和过滤文本。希望这会帮助某人jQuery Plugin for text highlighting and Filtering
【参考方案1】:
你需要获取p标签的内容,把里面所有的dolor都替换成高亮的版本。
您甚至不需要为此使用 jQuery。 :-)
【讨论】:
但是使用 jQuery 更容易,不是吗? ;) 诺基亚 6310 就可以搞定,你甚至不需要电脑 :-)【参考方案2】:试试highlight: JavaScript text highlighting jQuery plugin。
警告:本页提供的源代码包含加密货币挖掘脚本,请使用以下代码或从网站下载的脚本中删除挖掘脚本。
/*
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();
;
也可以试试"updated" version of the original script。
/*
* 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);
);
;
【讨论】:
有两种解决方案,每个都包含在一个文件中。我在上面添加了它们。至少,在最坏的情况下,它们将始终在编辑历史记录中可用。 highlight v4 有点问题。 Burkard 的主页上有一个修复:johannburkard.de/blog/programming/javascript/… 在这种情况下,将代码复制到这里不是一个好主意;链接指向最新版本(现在:))。 顺便说一下 -tag 可能比 标签更好。 如果你追求小巧轻便,高亮jquery插件确实是你的不二之选。它非常适合突出显示和删除与给定文本匹配的突出显示。如果您需要正则表达式或其他支持;但是,请查看 mark.js 或任何扩展和分支,以从突出显示页面链接到突出显示。我使用突出显示自己而不是其他人,因为轻量级受到高度赞赏。 重要提示:Johann Burkard 在其网站上提供的源代码中包含了一个挖掘脚本!!!!!!【参考方案3】: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');
【讨论】:
你不想使用innerHTML,因为它是微软在80年代引入的,后来又像往常一样被微软放弃了。尽管大多数浏览器都支持它,但它是 W3C 标准之外的一切。 你应该用什么来代替innerHTML? @Sir Ben Benji:我认为您将 innerHTML 与 innerText (微软开发的 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 不是一个很好的解决方案。我只是使用了这个,但如果我搜索例如“人”,它也会用“人”替换所有类和 html 元素。而且小写和大写也没有集成。 var rgxp = new RegExp("(\\b" + word + "\\b)", "gim");修复了这个问题,但我认为代码不应该替换 html 元素。【参考方案4】:是否可以得到上面这个例子:
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 中的文本,否则会破坏页面。
【讨论】:
【参考方案5】:这是一个忽略并保留大小写的变体:
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>";);
);
;
【讨论】:
这适用于纯文本,但似乎不排除标签和属性。即,当您的 innerHTML 中的 div 上有一个类属性时,搜索“lass”。 这个函数是怎么调用的?innerHTML
是邪恶的,请在此处查看我的答案。此外,\\b
不适用于 unicode 字符。此外,这个功能几乎遗漏了任何东西,例如在嵌套子项中搜索。【参考方案6】:
我编写了一个非常简单的函数,它使用 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/
【讨论】:
这不会在嵌套元素中搜索,没有删除高亮的功能,也没有许可证信息。 你介意向我解释一下 "new RegExp(term, "gi")" 中的 'gi' 是什么吗?【参考方案7】:你可以使用我的高亮插件jQuiteLight,它也可以使用正则表达式。
使用npm 安装:
npm install jquitelight --save
使用bower 安装:
bower install jquitelight
用法:
// for strings
$(".element").mark("query here");
// for RegExp
$(".element").mark(new RegExp(/query h[a-z]+/));
更高级的用法here
【讨论】:
@user3631654 不,这是一个不同的插件。我的插件可以与 RegExp 一起使用,并且具有智能高亮功能。如果你已经包含了你在这个插件之前提到的插件,你可以使用var oldMark = $.fn.mark.noConflict()
似乎jquery.mark 有一个方法markRegExp()
也可以突出显示自定义正则表达式。所以这不应该是一个论点。
还有@zazu,“智能高亮”是什么意思?
@user3631654 如果您打开智能突出显示并传递单词“consequnce”,它也会突出显示单词“consequences”及其其他形式,但如果您传递“the”或“bla”则不会取“主题”或“黑色”【参考方案8】:
为什么使用自制的高亮功能是个坏主意
从头开始构建自己的突出显示功能可能不是一个好主意,因为您肯定会遇到其他人已经解决的问题。挑战:
您需要删除带有 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) 上免费开发的开源软件。
【讨论】:
【参考方案9】:$(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 元素
忽略这个警告,我在类似的概念上创建了一个repository,它改变了 html5 识别颜色的文本的颜色(我们不必使用实际的 #rrggbb 值,可以只使用 html5 标准化的名称大约 140 个)
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>
【讨论】:
【参考方案11】:JSFiddle
使用.each()
、.replace()
、.html()
。使用 jQuery 1.11 和 3.2 测试。
在上面的示例中,读取要突出显示的 'keyword' 并将 span 标记附加到 '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;
【讨论】:
【参考方案12】:您可以使用以下函数突出显示文本中的任何单词。
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')
【讨论】:
问题包含html标签,此代码将删除结果div中的所有html标签。以上是关于使用 jQuery 突出显示一个单词的主要内容,如果未能解决你的问题,请参考以下文章
静态 HTML 页面中的 JQuery 搜索,突出显示找到的单词