jQuery用html替换匹配的文本 [英] jquery replace matching text with html
问题描述
我想使用jQuery动态地将与给定正则表达式匹配的所有文本括入特定标签.例如:
<div class="content">
<div class="spamcontainer">
Eggs and spam is better than ham and spam.
<img src="spam-and-eggs.jpg">
I do not like green eggs and spam, though.
</div>
</div>
如果我的正则表达式为ham|spam
,并且我想用<span class='meat-product'>
括起来,那么我想转换为
<div class="content">
<div class="spamcontainer">
Eggs and <span class='meat-product'>spam</span> is better than <span class='meat-product'>ham</span> and <span class='meat-product'>spam</span>.
<img src="spam-and-eggs.jpg">
I do not like green eggs and <span class='meat-product'>spam</span>, though.
</div>
</div>
这是我的问题.我知道如何仅使用文本和仅使用html来做到这一点:
$("div.content").text(function() {
return $(this).text().replace(/ham|spam/, function(match) {
return '<span class="meat-product">' + match + '</span>';
});
});
和
$("div.content").html(function(_, html) {
return html.replace(/ham|spam/, function(match) {
return '<span class="meat-product">' + match + '</span>';
});
});
,但是前者将文本替换为文本(因此我得到了文本<span ...
而不是<span>
元素),而后者则在任何HTML而不是仅文本中都匹配了ham
和spam
. >
我如何只匹配文本,还可以用HTML元素替换文本?
我如何只匹配文本,还可以用HTML元素替换文本?
您可以选择所有后代元素和文本节点,并将集合过滤为仅包括文本节点.然后,您可以简单地将每个文本节点替换为修改后的字符串:
$(".content *").contents().filter(function() {
return this.nodeType === 3;
}).replaceWith(function () {
return this.textContent.replace(/(ham|spam)/g, '<span class="meat-product">$1</span>');
});
$(".content *").contents().filter(function() {
return this.nodeType === 3;
}).replaceWith(function() {
return this.textContent.replace(/(ham|spam)/g, '<span class="meat-product">$1</span>');
});
.meat-product {
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="spamcontainer">
Eggs and spam is better than ham and spam.
<img src="spam-and-eggs.jpg">I do not like green eggs and spam, though.
</div>
</div>
- 使用通用选择器
*
选择所有后代元素(当然您也可以使用$('.content').children()
,但这只会深入一层……您可能会遇到嵌套元素,这意味着您将需要检索 all 文本节点,因此我使用*
选择所有后代元素的内容. -
.contents()
方法获取所有文本节点和子元素. - 然后过滤集合,以便仅包含文本节点,因为我们不想替换任何HTML.文本节点的
nodeType
属性值为3. - 最后,
.replaceWith()
方法用于用替换后的文本字符串更新每个文本节点..replaceWith()
方法的好处是,您可以用HTML字符串替换文本. - 您也可以使用捕获组来缩短
.replace()
方法,如上例所示.然后,您可以在span
元素之间简单地替换$1
.
I want to use jQuery to dynamically enclose all text matching a given regexp with a specific tag. For example:
<div class="content">
<div class="spamcontainer">
Eggs and spam is better than ham and spam.
<img src="spam-and-eggs.jpg">
I do not like green eggs and spam, though.
</div>
</div>
If my regexp is ham|spam
and I want to enclose with <span class='meat-product'>
then I would want to transform to
<div class="content">
<div class="spamcontainer">
Eggs and <span class='meat-product'>spam</span> is better than <span class='meat-product'>ham</span> and <span class='meat-product'>spam</span>.
<img src="spam-and-eggs.jpg">
I do not like green eggs and <span class='meat-product'>spam</span>, though.
</div>
</div>
Here's my problem. I know how to do this with just text, and with just html:
$("div.content").text(function() {
return $(this).text().replace(/ham|spam/, function(match) {
return '<span class="meat-product">' + match + '</span>';
});
});
and
$("div.content").html(function(_, html) {
return html.replace(/ham|spam/, function(match) {
return '<span class="meat-product">' + match + '</span>';
});
});
but the former replaces text with text (so I get the text <span ...
instead of a <span>
element), and the latter matches ham
and spam
inside any HTML rather than in just text.
How can I match only text, but also be able to replace that text with HTML elements?
How can I match only text, but also be able to replace that text with HTML elements?
You could select all the descendant elements and text nodes and filter the set to only include text nodes. Then you can simply replace each text node with the modified string:
$(".content *").contents().filter(function() {
return this.nodeType === 3;
}).replaceWith(function () {
return this.textContent.replace(/(ham|spam)/g, '<span class="meat-product">$1</span>');
});
$(".content *").contents().filter(function() {
return this.nodeType === 3;
}).replaceWith(function() {
return this.textContent.replace(/(ham|spam)/g, '<span class="meat-product">$1</span>');
});
.meat-product {
color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<div class="spamcontainer">
Eggs and spam is better than ham and spam.
<img src="spam-and-eggs.jpg">I do not like green eggs and spam, though.
</div>
</div>
- Use the universal selector,
*
, to select all descendant elements (of course you could also use$('.content').children()
, but that will only go one level deep... you will probably encounter nested elements which means that you will need to retrieve all text nodes, therefore I used*
to select the contents of all the descendant elements). - The
.contents()
method gets all the text nodes and children elements. - Then filter the set so that only text nodes are included since we don't want to replace any HTML. The
nodeType
property value of a text node is 3. - Finally, the
.replaceWith()
method is used to update each text node with the replaced text string. The good thing about the.replaceWith()
method is that you can replace the text with an HTML string. - You can also shorten your
.replace()
method by using a capturing group like in the example above. Then you can simply substitute$1
between thespan
elements.
这篇关于jQuery用html替换匹配的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!