使用jQuery从包装集合中收集所有文本节点,用空格分隔

时间:2010-05-14 17:40:28

标签: javascript jquery dom traversal

我正在寻找一种方法来收集jQuery包装集中的所有文本,但我需要在它们之间没有文本节点的兄弟节点之间创建空格。

例如,请考虑以下HTML:

<div>
  <ul>
    <li>List item #1.</li><li>List item #2.</li><li>List item #3.</li>
  </ul>
</div>

如果我只是使用jQuery的text()方法来收集<div>的文本内容,就像这样:

var $div = $('div'), text = $div.text().trim();

alert(text);

产生以下文字:

  

列表项目#1。列表项目#2。列表项目#3。

因为每个<li>元素之间没有空格。我真正想要的是这个(注意每个句子之间的单一空格):

  

列出项目#1。列出项目#3。列出项目#3。

这告诉我,我需要遍历包装集中的DOM节点,将每个文本附加到字符串,然后是空格。我尝试了以下代码:

var $div = $('div'), text = '';

$div.find('*').each(function() {
  text += $(this).text().trim() + ' ';
});

alert(text);

但是这产生了以下文字:

  

这是列表项#1。这是列表项#2。这是列表项#3。这是列表项#1。这是列表项#2。这是列表项目#3。

我认为这是因为我正在遍历<div>的每个后代并附加文本,所以我在<ul>和每个<li>中都获得了文本节点孩子,导致重复的文字。

我想我可能会找到/编写一个简单的JavaScript函数来递归遍历包装集的DOM,收集和附加文本节点 - 但有没有更简单的方法来使用jQuery?跨浏览器的一致性非常重要。

感谢您的帮助!

3 个答案:

答案 0 :(得分:7)

jQuery主要处理元素,其文本节点功能相对较弱。您可以获得contents()所有孩子的列表,但是您仍然必须检查类型,这与使用普通DOM childNodes完全没有区别。没有方法可以递归地获取文本节点,因此您必须自己编写一些内容,例如。类似的东西:

function collectTextNodes(element, texts) {
    for (var child= element.firstChild; child!==null; child= child.nextSibling) {
        if (child.nodeType===3)
            texts.push(child);
        else if (child.nodeType===1)
            collectTextNodes(child, texts);
    }
}
function getTextWithSpaces(element) {
    var texts= [];
    collectTextNodes(element, texts);
    for (var i= texts.length; i-->0;)
        texts[i]= texts[i].data;
    return texts.join(' ');
}

答案 1 :(得分:2)

这是我能想到的最简单的解决方案:

$("body").find("*").contents().filter(function(){return this.nodeType!==1;});

答案 2 :(得分:0)

您可以使用jQuery contents()方法获取所有节点(包括文本节点),然后将您的集合过滤到仅文本节点。

$("body").find("*").contents().filter(function(){return this.nodeType!==1;});

从那里你可以创建你需要的任何结构。