用这样的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
});
演示