查找嵌套HTML中文本节点的长度到一定程度

时间:2013-05-25 16:09:31

标签: javascript jquery dom

使用这样的HTML:

<div id="container">                                                                                 
  <p>Lorem ipsum lorem ipsum
    <p>This is the second!
      <span data-attribute="my-span">Hello World</span>
    </p>
  </p>
</div> 

我想找到从容器到我的跨度的文本长度。因此,通过计算后代的指标,我得到了42的正确答案。

但如果我有这样的HTML:

  <div id="container">                                                                                 
      <p>Lorem ipsum lorem ipsum
        <p>This is the second!
          <span data-attribute="my-span">Hello World</span>
        </p>
        Some preceding HTML that I dont want!
      </p>
    </div> 

我不希望字符数继续我的范围。我只希望字符计数达到我的范围,所以正确答案仍然是42.但是通过计算子文本长度,它还会添加前面的文本和span的文本(这很容易通过减去从总数)。

我已经探讨了将html和子字符串列出到我想要的span属性,拆分结束并解析出html,只留下我想要计算的文本字符。但这似乎过于复杂。

我也在考虑使用类似wicked good xpath之类的东西来查找我正在寻找的所有节点,然后总结文本。

我还查看了将所有文本节点列出到某一点并将它们相加,但是它会在我的span文本之前列出子项的前一个文本,因此它的求和顺序不正确。

此外,嵌套可能是n级深,所以不要只假设一个级别。

关于实现这一目标的最佳方法的任何建议?

2 个答案:

答案 0 :(得分:2)

一个始终可用的选项是手动遍历DOM树。 jQuery并不擅长处理非元素节点(当我们执行.find('*').contents()时,似乎所有子节点都列在每个节点的所有子节点之后,而contents是查看这些节点的唯一方法) ,但我们仍然可以使用本机API。另请注意,处理空格在这里很棘手(我假设您想要折叠空格来模仿渲染器行为)这样的事情:

function countCharsUntil(parent, selector, inclusive){
  var done = false;
  return listChars(parent).replace(/\s+/g," ").trim().length;

  function listChars(elem){
    var cn = elem.childNodes;
    var chars = "";
    if(!inclusive && $(elem).is(selector)){
      done = true;
      return ""
    }
    for(var i=0; i<cn.length && !done; i++){
      var child = cn[i];
      switch(child.nodeType){
        case Node.ELEMENT_NODE:
          chars += listChars(child);
          break;
        case Node.TEXT_NODE:
          chars += child.nodeValue;
          break;
      }
    }
    if(inclusive && $(elem).is(selector)){
      done = true;
      return chars;
    }
    return chars;
  }
}

测试:http://jsfiddle.net/8hxb6/1/

请注意,测试会返回43个字符以进行独占搜索。这可能是因为你忽略了div>p里面的“ipsum”和div>p>p里面的“This”之间的空间

答案 1 :(得分:1)

这位工作人员

$(document).ready(function(){
  var tx = $('#container').text().split($('#container span').text())[0].replace(/[\s]{2,}/g,'');
  console.log(tx.length); //42
});

DEMO