查找嵌套HTML中文本节点的长度直至某一点



用这样的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> 

我不希望对我的span进行字符计数。我只想让字符数达到我的span,所以正确答案仍然是42。但是,通过计算子文本的长度,它还会添加前面的文本和span的文本(这很容易通过从总数中减去它来消除)。

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

我还在考虑使用类似于非常好的xpath的东西来查找所有节点直到我正在寻找的节点,然后总结文本。

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

同样,嵌套可以有n层深,所以不要假设只有一层。

有什么最好的方法可以做到这一点吗?

始终可用的一个选项是手动遍历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"之间的空格

这个工作人

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

相关内容

最新更新