在事件中突出显示div元素中特定子字符串的最佳方法是什么? 通过突出显示,我的意思是应用一些CSS样式,如黄色背景或其他东西。
基本上我需要一个简单的JS客户端函数:
function (element, start, end) {
// element is the element to manipulate. a div or span will do
// start and end are the start and end positions within the text of that
// element where highlighting should be.
// do the stuff
}
只有一个高亮显示处于活动状态。
答案 0 :(得分:7)
您需要将您想要的文本包装在其自己的<span>
标记中,以便您可以为该文本提供自己的样式。使用您请求的函数定义,您可以这样做:
function (element, start, end) {
var str = element.innerHTML;
str = str.substr(0, start) +
'<span class="hilite">' +
str.substr(start, end - start + 1) +
'</span>' +
str.substr(end + 1);
element.innerHTML = str;
}
然后,您可以为类hilite定义CSS以控制该文本的样式。
.hilite {color: yellow;}
这假设start和end是要突出显示的第一个和最后一个字符的innerHTML的索引。
如果您希望能够在同一元素上重复调用它(以移动高光),您可以这样做:
function (element, start, end) {
var item = $(element);
var str = item.data("origHTML");
if (!str) {
str = item.html();
item.data("origHTML", str);
}
str = str.substr(0, start) +
'<span class="hilite">' +
str.substr(start, end - start + 1) +
'</span>' +
str.substr(end + 1);
item.html(str);
}
答案 1 :(得分:5)
从头开始构建自己的突出显示功能可能是一个坏主意的原因是因为你肯定会遇到其他人已经解决的问题。挑战:
innerHTML
就是这种情况)听起来很复杂?如果你想要一些功能,比如忽略突出显示,变音符号映射,同义词映射,iframe内搜索,分离词搜索等一些元素,这就变得越来越复杂。
使用现有的,实施良好的插件时,您不必担心上面提到的内容。 Sitepoint上的文章 10 jQuery text highlighter plugins 比较了流行的荧光笔插件。
mark.js是一个用纯JavaScript编写的插件,但也可以作为jQuery插件使用。它的开发目的是提供比其他插件更多的机会,可以选择:
<强> 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)上开发了开源。
答案 2 :(得分:3)
如果您没有附加事件或复杂的HTML,您只需在HTML上进行搜索和替换:
element.innerHTML = element.innerHTML.replace(/search/gi, function(match) {
return '<span class="highlight">' + match + '</span>'
});
如果你想要更好的东西,你可以直接操作DOM而不使用innerHTML
,这将保留事件并适用于更复杂的HTML:
/*
* Takes in an array of consecutive TextNodes and returns a document fragment with `word` highlighted
*/
function highlight_text_nodes($nodes, word) {
if (!$nodes.length) {
return;
}
var text = '';
// Concatenate the consecutive nodes to get the actual text
for (var i = 0; i < $nodes.length; i++) {
text += $nodes[i].textContent;
}
var $fragment = document.createDocumentFragment();
while (true) {
// Tweak this if you want to change the highlighting behavior
var index = text.toLowerCase().indexOf(word.toLowerCase());
if (index === -1) {
break;
}
// Split the text into [before, match, after]
var before = text.slice(0, index);
var match = text.slice(index, index + word.length);
text = text.slice(index + word.length);
// Create the <mark>
var $mark = document.createElement('mark');
$mark.className = 'found';
$mark.appendChild(document.createTextNode(match));
// Append it to the fragment
$fragment.appendChild(document.createTextNode(before));
$fragment.appendChild($mark);
}
// If we have leftover text, just append it to the end
if (text.length) {
$fragment.appendChild(document.createTextNode(text));
}
// Replace the nodes with the fragment
$nodes[0].parentNode.insertBefore($fragment, $nodes[0]);
for (var i = 0; i < $nodes.length; i++) {
var $node = $nodes[$nodes.length - i - 1];
$node.parentNode.removeChild($node);
}
}
/*
* Highlights all instances of `word` in `$node` and its children
*/
function highlight($node, word) {
var $children = $node.childNodes;
var $current_run = [];
for (var i = 0; i < $children.length; i++) {
var $child = $children[i];
if ($child.nodeType === Node.TEXT_NODE) {
// Keep track of consecutive text nodes
$current_run.push($child);
} else {
// If we hit a regular element, highlight what we have and start over
highlight_text_nodes($current_run, word);
$current_run = [];
// Ignore text inside of our <mark>s
if ($child.nodeType === Node.ELEMENT_NODE && $child.className !== 'found') {
highlight($child, word);
}
}
}
// Just in case we have only text nodes as children
if ($current_run.length) {
highlight_text_nodes($current_run, word);
}
}
/*
* Removes all highlighted <mark>s from the given node
*/
function unhighlight($node) {
var $marks = [].slice.call($node.querySelectorAll('mark.found'));
for (var i = 0; i < $marks.length; i++) {
var $mark = $marks[i];
// Replace each <mark> with just a text node of its contents
$mark.parentNode.replaceChild(document.createTextNode($mark.childNodes[0].textContent), $mark);
}
}
演示:https://jsfiddle.net/wLkbbo5m/4/
如果您想要更多功能,只需使用库(如mark.js)。重新发明整个轮没有意义。
答案 3 :(得分:1)
您可以使用mark.js,它提供了一个简单而强大的jquery插件:
$('p').mark('sit');
mark {
background: orange;
color: black;
}
<script src="https://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://cdn.jsdelivr.net/mark.js/8.6.0/jquery.mark.min.js"></script>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
答案 4 :(得分:0)
在此处尝试Highlighter.js库: https://gist.github.com/wliwanag/03d95916c7ba5d17e226
它支持: 突出显示子元素中的文本。 使用文字中的单词作为搜索键(例如,下面的示例将突出显示&#34;简单地&#34;,&#34; 1500&#34;等等。)
使用:
var searchInput = "simply 1500 bee y";
var textSource = $("#text-container").html();
var htmlSource = $("#html-container").html();
$("#text-result").html(highlightHtml(textSource, searchInput));
$("#html-result").html(highlightHtml(htmlSource, searchInput));
答案 5 :(得分:0)
我担心其他库的DOM操作如何在React项目中工作,所以我使用react-hightlight-words解决了这个问题。
有关配置,请参见the table of props。
开箱即用,它使用搜索词而不是索引范围,但是可以解决与该问题相同的问题,除非将其锁定到索引。但是,如果是 的情况,则可以为findChunks
属性提供一个功能,以任意检测要突出的部分。 (请参阅here,如何定义默认的findChunks
。)
来自the description on GitHub的简单示例。
import React from "react";
import ReactDOM from "react-dom";
import Highlighter from "react-highlight-words";
ReactDOM.render(
<Highlighter
highlightClassName="YourHighlightClass"
searchWords={["and", "or", "the"]}
autoEscape={true}
textToHighlight="The dog is chasing the cat. Or perhaps they're just playing?"
/>,
document.getElementById("root")
);
安装npm i --save react-highlight-words
答案 6 :(得分:-1)
如果您只希望替换开始/结束之间的特定文本(而不是每次出现),它将看起来像这样:
function(element, start, end) {
textToHilight = element.innerHTML.substr(start, end);
element.innerHTML = element.innerHTML.substring(0, start) + "<span class='hilight'>" + textToHilight + "</span>" + element.innerHTML.substring(end);
}