用jQuery替换一个包含HTML和文本的文本节点的“jQuery方式”是什么?

8
在我的网页浏览器脚本项目中,我需要替换一个文本节点,而不会影响与该文本节点在同一父节点下的其他HTML元素。并且我需要用多个节点来替换它:
<div id="target"> foo / bar; baz<img src="/image.png"></div>

Needs to become:

<div id="target"> <a href="#">foo</a> / <a href="#">bar</a>; <a href="#">baz</a><img src="/image.png"></div>

我知道jQuery对于文本节点的支持很有限。我知道我可以使用直接的DOM调用而不是jQuery。我也知道我可以像这样做:$('#target').html(我的新内容+我不想改变的内容)。请注意,我希望保留初始空格,这个看起来有些棘手。
我想问问这里的专家们,最惯用的jQuery方法是什么?

你如何知道在哪里分割替换文本? - j_mcnally
http://api.jquery.com/contents/ - Ram
@j_mcnally:假设我们有“某种方式”来生成替换文本/HTML。在我的实际项目中,我将原始文本解析为一些对象,然后使用这些对象生成基本相同的文本,但将某些单词更改为链接。 - hippietrail
1
我不知道有任何jQuery的解决方案,但我编写了一个高亮功能,可以实现你想要达到的目标:http://jsfiddle.net/rkw79/5cCuc/ - rkw
@rkw:是的,那肯定是相关的问题。 - hippietrail
3个回答

10
你基本上想用新内容替换第一个子节点(文本节点)。你需要使用http://api.jquery.com/replaceWith/

// Text node we want to process and remove
var textNode = $("#target").contents().first();
// Break the text node up
var parts = textNode.text().split(/\s/);
// Put links around them
var replaceWith = "";
for (var i =0; i < parts.length;i++) {
    replaceWith += "<a href='http://www.google.com'>"  + escapeHTML(parts[i]) + "</a> ";
}
// Replace the text node with the HTML we created
textNode.replaceWith(replaceWith);

function escapeHTML(string) {
  return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="target">example, handles escaping properly, you should see an ampersand followed by "amp;" here: &amp;amp; <img src="/foobar.png"></div>

http://jsfiddle.net/NGYTB/1/


新的HTML并不完全基于空格与非空格,但这种方法确实非常好! - hippietrail
@hippietrail 我怎么知道你将如何拆分它?这只是一个简单明了的例子,你可以按需修改它。相关部分是要访问文本节点,并用你想要创建的 HTML 替换它。 - Ruan Mendes
1
抱歉,那不是抱怨,只是对其他人的评论。除非有什么出乎意料的情况,否则我会接受你的答案,所以不用担心 (-: - hippietrail

1

尝试这种方法

// nodeType = 1 corresponds to element node
   // You are filtering everything out other than that and 
   // removing the textnodes from it..
   // contents() will get everything including the text
    ​$('#target'​).contents().filter(function() {
        return this.nodeType != 1; 
    }).remove();

   // Then you are prepending the div with the html  that needs to 
   //  replaced with the text...
    $('#target').prepend('<a href="#">mixed</a> text <a href="#">and</a> HTML');
   // This makes sure you do not touch the initial img element inside the div

如果您不想删除特定的节点类型,可以添加其他节点类型。 检查FIDDLE


这个可行。我想这不是一个非常通用的方法,但它似乎是一个略微超出jQuery范围的问题领域,而且这确实是符合惯用的jQuery方式。 - hippietrail

0

试试这个...编辑过的版本

$('#target').html('<a href="#">mixed</a> text <a href="#">and</a> HTML' + $('#target').html());

但这将导致 一些文本<img src="/image.png"><a href="#">mixed</a> 文本 <a href="#">和</a> HTML - hippietrail
不行,调用.html()会返回旧的HTML,包括旧的文本节点。所以基本上它会在新内容之前添加而不是用新内容替换旧内容。 - hippietrail
我还没有代码。我有网站的HTML,我正在为用户脚本编写尝试各种方法直接在JavaScript控制台中。如果你真的需要看一些HTML,我正在尝试从网站转换,我们可以在SE聊天室中进行。我已经更新了我的示例HTML,使其更像我的问题,如果有帮助的话。 - hippietrail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接