Javascript:突出显示子字符串,保持原始大小写,但在不区分大小写的模式下搜索

发布于 2024-09-10 20:32:41 字数 513 浏览 10 评论 0原文

我正在尝试编写一个“建议搜索框”,但找不到允许使用 JavaScript 突出显示子字符串并保留原​​始大小写的解决方案。

例如,如果我搜索“ca”,我会以不区分大小写的模式搜索服务器端,并得到以下结果:

计算器

日历

ESCAPE

我想查看前面所有单词中的搜索字符串,因此结果应该是:

Calculator

calendar

ESCAPE

我尝试使用以下代码:

var reg = new RegExp(querystr, 'gi');
var final_str = 'foo ' + result.replace(reg, '<b>'+querystr+'</b>');
$('#'+id).html(final_str);

但显然这样我就失去了原始情况!

有办法解决这个问题吗?

I'm trying to write a "suggestion search box" and I cannot find a solution that allows to highlight a substring with javascript keeping the original case.

For example if I search for "ca" I search server side in a case insensitive mode and I have the following results:

Calculator

calendar

ESCAPE

I would like to view the search string in all the previous words, so the result should be:

Calculator

calendar

ESCAPE

I tried with the following code:

var reg = new RegExp(querystr, 'gi');
var final_str = 'foo ' + result.replace(reg, '<b>'+querystr+'</b>');
$('#'+id).html(final_str);

But obviously in this way I loose the original case!

Is there a way to solve this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

美煞众生 2024-09-17 20:32:42

使用函数作为 .replace() 的第二个参数,该函数返回带有连接标签的实际匹配字符串。

尝试一下: http://jsfiddle.net/4sGLL/

reg = new RegExp(querystr, 'gi');
       // The str parameter references the matched string
       //    --------------------------------------v
final_str = 'foo ' + result.replace(reg, function(str) {return '<b>'+str+'</b>'});
$('#' + id).html(final_str);​

带输入的 JSFiddle 示例: https://jsfiddle.net/pawmbude/

Use a function for the second argument for .replace() that returns the actual matched string with the concatenated tags.

Try it out: http://jsfiddle.net/4sGLL/

reg = new RegExp(querystr, 'gi');
       // The str parameter references the matched string
       //    --------------------------------------v
final_str = 'foo ' + result.replace(reg, function(str) {return '<b>'+str+'</b>'});
$('#' + id).html(final_str);​

JSFiddle Example with Input: https://jsfiddle.net/pawmbude/

南渊 2024-09-17 20:32:42

ES6版本

const highlight = (needle, haystack) =>
  haystack.replace(
      new RegExp(needle, 'gi'),
      (str) => `<strong>${str}</strong>`
  );

ES6 version

const highlight = (needle, haystack) =>
  haystack.replace(
      new RegExp(needle, 'gi'),
      (str) => `<strong>${str}</strong>`
  );
猫七 2024-09-17 20:32:42

好的结果

function str_highlight_text(string, str_to_highlight){
   var reg = new RegExp(str_to_highlight, 'gi');
   return string.replace(reg, function(str) {return '<span style="background-color:#ffbf00;color:#fff;"><b>'+str+'</b></span>'});
}

并且更容易记住......
感谢 user113716:https://stackoverflow.com/a/3294644/2065594

nice results with

function str_highlight_text(string, str_to_highlight){
   var reg = new RegExp(str_to_highlight, 'gi');
   return string.replace(reg, function(str) {return '<span style="background-color:#ffbf00;color:#fff;"><b>'+str+'</b></span>'});
}

and easier to remember...
thx to user113716: https://stackoverflow.com/a/3294644/2065594

绮筵 2024-09-17 20:32:42

虽然到目前为止其他答案看起来很简单,但它们不能真正用于许多现实世界的情况,因为它们不处理正确的文本 HTML 转义和 RegExp 转义。如果您想突出显示每个可能的片段,同时正确转义文本,这样的函数将返回您应添加到建议框中的所有元素:

function highlightLabel(label, term) {
  if (!term) return [ document.createTextNode(label) ]
  const regex = new RegExp(term.replace(/[\\^$*+?.()|[\]{}]/g, '\\
amp;'), 'gi')
  const result = []
  let left, match, right = label
  while (match = right.match(regex)) {
    const m = match[0], hl = document.createElement('b'), i = match.index
    hl.innerText = m
    left = right.slice(0, i)
    right = right.slice(i + m.length)
    result.push(document.createTextNode(left), hl)
    if (!right.length) return result
  }
  result.push(document.createTextNode(right))
  return result
}

While the other answers so far seem simple, they can't be really used in many real world cases as they don't handle proper text HTML escaping and RegExp escaping. If you want to highlight every possible snippet, while escaping the text properly, a function like that would return all elements you should add to your suggestions box:

function highlightLabel(label, term) {
  if (!term) return [ document.createTextNode(label) ]
  const regex = new RegExp(term.replace(/[\\^$*+?.()|[\]{}]/g, '\\
amp;'), 'gi')
  const result = []
  let left, match, right = label
  while (match = right.match(regex)) {
    const m = match[0], hl = document.createElement('b'), i = match.index
    hl.innerText = m
    left = right.slice(0, i)
    right = right.slice(i + m.length)
    result.push(document.createTextNode(left), hl)
    if (!right.length) return result
  }
  result.push(document.createTextNode(right))
  return result
}
预谋 2024-09-17 20:32:42

string.replace 在一般情况下会失败。如果您使用 .innerHTML,replace 可以替换标签中的匹配项(如标签)。如果您使用 .innerText 或 .textContent,它将删除 html 中以前存在的所有标签。更重要的是,在这两种情况下,如果您想删除突出显示,它都会损坏您的 html。

真正的答案是 mark.js (https://markjs.io/)。我刚刚找到了这个 - 这是我一直在寻找的东西。它只是做你想做的事。

string.replace fails in the general case. If you use .innerHTML, replace can replace matches in tags (like a tags). If you use .innerText or .textContent, it will remove any tags there were previously in the html. More than that, in both cases it damages your html if you want to remove the highlighting.

The true answer is mark.js (https://markjs.io/). I just found this - it is what I have been searching for for such a long time. It does just what you want it to.

一身仙ぐ女味 2024-09-17 20:32:42

我也做同样的事情。

您需要复印一份。

我在数据库中存储真实字符串的副本,全部小写。

然后我使用小写版本的查询字符串进行搜索或执行不区分大小写的正则表达式。

然后使用在主字符串中找到的起始索引加上查询字符串的长度来突出显示结果中的查询字符串。

您不能在结果中使用查询字符串,因为它的大小写不确定。您需要突出显示原始字符串的一部分。

I do the exact same thing.

You need to make a copy.

I store in the db a copy of the real string, in all lower case.

Then I search using a lower case version of the query string or do a case insensitive regexp.

Then use the resulting found start index in the main string, plus the length of the query string, to highlight the query string within the result.

You can not use the query string in the result since its case is not determinate. You need to highlight a portion of the original string.

万劫不复 2024-09-17 20:32:42

.match() 执行不区分大小写的匹配并返回大小写完整的匹配数组。

var matches = str.match(queryString),
    startHere = 0,
    nextMatch,
    resultStr ='',
    qLength = queryString.length;

for (var match in matches) {
    nextMatch = str.substr(startHere).indexOf(match);
    resultStr = resultStr + str.substr(startHere, nextMatch) + '<b>' + match + '</b>';
    startHere = nextMatch + qLength;
}

.match() performs case insensitive matching and returns an array of the matches with case intact.

var matches = str.match(queryString),
    startHere = 0,
    nextMatch,
    resultStr ='',
    qLength = queryString.length;

for (var match in matches) {
    nextMatch = str.substr(startHere).indexOf(match);
    resultStr = resultStr + str.substr(startHere, nextMatch) + '<b>' + match + '</b>';
    startHere = nextMatch + qLength;
}
甜妞爱困 2024-09-17 20:32:42

我找到了实现它的最简单方法。 JavaScript 正则表达式会记住它匹配的字符串。此处可以使用此功能。

我对代码做了一些修改。

reg = new RegExp("("+querystr.trim()+")", 'gi');
final_str = 'foo ' + result.replace(reg, "<b>&1</b>");
$('#'+id).html(final_str);

I have found a easiest way to achieve it. JavaScript regular expression remembers the string it matched. This feature can be used here.

I have modified the code a bit.

reg = new RegExp("("+querystr.trim()+")", 'gi');
final_str = 'foo ' + result.replace(reg, "<b>&1</b>");
$('#'+id).html(final_str);
掌心的温暖 2024-09-17 20:32:42

突出显示搜索词并锚定到首次出现的位置 - 开始

function highlightSearchText(searchText) {
    var innerHTML = document.documentElement.innerHTML;
    var replaceString = '<mark>'+searchText+'</mark>';
    var newInnerHtml = this.replaceAll(innerHTML, searchText, replaceString);
    document.documentElement.innerHTML = newInnerHtml;
    var elmnt = document.documentElement.getElementsByTagName('mark')[0]
    elmnt.scrollIntoView();
}

function replaceAll(str, querystr, replace) {
    var reg = new RegExp(querystr, 'gi');
    var final_str = str.replace(reg, function(str) {return '<mark>'+str+'</mark>'});
    return final_str
}

突出显示搜索词并锚定到首次出现的位置 - 结束

Highlight search term and anchoring to first occurence - Start

function highlightSearchText(searchText) {
    var innerHTML = document.documentElement.innerHTML;
    var replaceString = '<mark>'+searchText+'</mark>';
    var newInnerHtml = this.replaceAll(innerHTML, searchText, replaceString);
    document.documentElement.innerHTML = newInnerHtml;
    var elmnt = document.documentElement.getElementsByTagName('mark')[0]
    elmnt.scrollIntoView();
}

function replaceAll(str, querystr, replace) {
    var reg = new RegExp(querystr, 'gi');
    var final_str = str.replace(reg, function(str) {return '<mark>'+str+'</mark>'});
    return final_str
}

Highlight search term and anchoring to first occurence - End

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文