简体   繁体   English

如果开头标签已指定类,则Javascript RegExp会替换两个标签之间的文本

[英]Javascript RegExp replace text between two tags if the opening tag has specified class

I have the following HTML code: 我有以下HTML代码:

<span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span>
<span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text AAA</span>

I want to replace the text between the span tags, but only if the span tag has the class " search-text ". 我想替换span标签之间的文本,但是仅当span标签具有类“ search-text ”时才可以 So in my case, I have a string containing an HTML code with two spans. 因此,就我而言,我有一个包含两个跨度的HTML代码的字符串。 I want to replace the text from the second span if it contains a searched text. 如果它包含搜索到的文本,我想替换第二个跨度中的文本。

I search for: " aa " and I want to replace it with <span class="highlight-text">aa</span> . 我搜索:“ aa ”,我想用<span class="highlight-text">aa</span>替换它。 So the final result should be: 因此,最终结果应为:

<span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span>
<span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text <span class="highlight-search">AA</span>A</span>

Right now I'm doing something like: 现在我正在做类似的事情:

var paint = $.proxy(this._paint, this);
var regex = /(<span class="search-text[^>]+>|<\/span>)/g;
item.node.innerHTML = item.html.replace(regex, paint);

where " value " is: " aa " and " item.html " is the HTML presented at the beginning of my question. 其中“ value ”是:“ aa ”和“ item.html ”是在我的问题开头出现的HTML。

the _paint function: _paint函数:

_paint: function($0) {
   return '<span class="highlight-text">' + $0 + '</span>';
},

At this moment the result is that the second span is entirely wrapped into the '<span class="highlight-text">' + $0 + '</span>'; 这时的结果是第二个跨度被完全包裹在'<span class="highlight-text">' + $0 + '</span>'; . This is the result: 结果如下:

<span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span>
<span class="highlight-text"><span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text AAA</span></span>

I want only the text match to be wrapped inside the hghlight span, like this: 我只希望将文本匹配项包装在hghlight跨度内,如下所示:

<span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span>
<span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text <span class="highlight-text">AA</span>A</span>

Any ideas? 有任何想法吗? Thanks. 谢谢。

Regex is notoriously the wrong tool for most of this job; 众所周知 ,正则表达式是大多数工作的错误工具。 it's designed for manipulating strings, not structured data such as HTML. 它是为处理字符串而不是HTML之类的结构化数据而设计的。 Fortunately, you're already in the browser, so you have an entire toolset designed for DOM manipulation available: may as well use it. 幸运的是,您已经在浏览器中,因此您拥有一个为DOM操作设计的完整工具集:也可以使用它。 (You've also tagged the question with jQuery, which makes it even easier.) (您还用jQuery标记了问题,这使它变得更加容易。)

Update: I'd misread a detail in the question, and was pulling the search string from a parent node's attribute instead of externally; 更新:我会误解问题的详细信息,并且是从父节点的属性中而不是从外部拉出搜索字符串。 I also failed to make the search case-insensitive. 我也未能使搜索不区分大小写。 Both now corrected in the below: 现在都在以下内容中进行了更正:

 // Make a case-insensitive regex from the search string let str = 'aa'; let re = new RegExp(str, "gi"); // operate only on the .search-text nodes: $('.search-text').each(function(i, el) { // get the current contents of the element: let text = $(el).html(); // Add your highlights: text = text.replace(re, '<span class="highlight-text">$&</span>'); // insert the modified text back into the DOM: $(el).html(text); }) 
 .highlight-text { background-color: #FFC } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span> <span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text AAA</span> I 

This is only really safe if the .search-text elements have no child nodes. 仅当.search-text元素没有子节点时,这才是真正安全的。 It will generally work even if they contain some HTML, but only if: 即使它们包含一些HTML,它通常也可以工作,但前提是:

  • You're certain that the strings you're highlighting will never match portions of the HTML itself, and 您可以确定要突出显示的字符串永远不会与HTML本身的某些部分匹配,并且
  • there aren't any event bindings attached to the DOM elements (this script replaces the contents of .search-text wholesale.) DOM元素上没有任何事件绑定(此脚本替换了.search-text Wholesale的内容。)

For example, trying to highlight the word "span" in an html string containing <span> elements would result in invalid html: 例如,尝试在包含<span>元素的html字符串中突出显示单词“ span”会导致无效的html:

 // same script as above $('.search-text').each(function(i, el) { let text = $(el).html(); let highlights = $(el).attr("attribute").split(" "); for (str of highlights) { text = text.replace(str, '<span class="highlight-text">' + str + '</span>'); } $(el).html(text); }) 
 .highlight-text { background-color: #FFC } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <span class="search-text" attribute="span">Text AAA <span>test</span></span> 

Starting with a string 以字符串开头

If your starting point is an HTML string instead of an already-built DOM tree, all you need to do is convert that string into a document fragment first so you can use these DOM tools on it: 如果您的起点是HTML字符串而不是已经构建的DOM树,那么您要做的就是首先将该字符串转换为文档片段,以便可以在其上使用以下DOM工具:

let fragment = $('<template>');
fragment.html($yourStringHere);
/* manipulate fragment contents as above, then */
return fragment.html();

A partial solution inspired by Daniel Beck's answer. 受Daniel Beck的答案启发的部分解决方案。 This solution doesn't manipulate the DOM. 此解决方案不操纵DOM。 (I just displayed the result on the DOM for demonstration purposes) (我只是将结果显示在DOM上以进行演示)

https://jsfiddle.net/mt2yz90L/3/ https://jsfiddle.net/mt2yz90L/3/

HTML: HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="result">
</div>

JS: JS:

  let searchedText = 'aa';
  let html ='<span class="whatever-class custom-class-name" attribute="Whatever 1 AAA">AAA BBB</span><span class="search-text custom-class-name" attribute="Whatever 2 AAA">Text AAA</span> I';
  var htmlParts = html.split(/(<span class="search-text[^>]+>|<\/span>)/g);
  var htmlPartsIndex = 0;
  for(var i=0; i < htmlParts.length; i++) {
    if(htmlParts[i].indexOf('search-text') !== -1) {
        htmlPartsIndex = ++i;
      break;
    }
  }
  if(htmlPartsIndex > 0) {
     htmlParts[htmlPartsIndex] = htmlParts[htmlPartsIndex].toLowerCase().replace(searchedText, '<span class="highlight-text">' + searchedText + '</span>')
  }
  $('#result').html(htmlParts.join(''));

CSS: CSS:

.highlight-text {
  background-color: red;
}

My only issue is that in my case (over 300 items to parse) it blocks the browser. 我唯一的问题是,就我而言(要解析的项目超过300个),它阻止了浏览器。 So this is quite slow. 所以这很慢。 I posted it in the idea that maybe someone will share a faster solution. 我发布它的想法是,也许有人会分享更快的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM