0

使用这样的 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。但是通过计算子文本长度,它还会添加到前面的文本和跨度的文本中(这很容易通过减去它来消除从总数)。

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

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

我还查看了仅列出直到某个点的所有文本节点并将它们求和,但它在我的跨度文本之前列出了孩子的前面文本,因此它的求和顺序不正确。

此外,嵌套可能有 n 层深,所以不要假设只有一层。

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

4

2 回答 2

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 个字符进行独占搜索。这可能是因为你忽略了里面的“ipsum”和里面div>p的“This”之间的空间div>p>p

于 2013-05-25T16:41:54.013 回答
1

这个上班族

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

演示

于 2013-05-25T16:32:39.493 回答