2011-07-20 37 views
4

我需要找到匹配的一些内部文本该网页上的所有元素:过滤器()的内部文本返回空父节点

$("body *:visible").filter(function(){ return $(this).text() == 'jQuery' }); 

但是我得到蒙山在某些情况下mathed元素的父节点。
例如
月1日的比赛:<李> < A HREF = “#” > jQuery的</A > < /李>
第二节比赛:< A HREF = “#” > jQuery的</A >

哪有我从选择中删除所有具有父节点的元素,并仅保留真正包含定义的内部文本的元素?

对于测试,你可以尝试执行上面的脚本上jquery.com

+2

而不是链接到jQuery的网页一些未知的原因,在jsfiddle.net创建一个测试,演示你的问题。另外,由于比较区分大小写,因此您的示例可能不甚准确。 –

回答

0

该代码会遍历只有元素的文本节点,然后进行比较。

$("body *:visible").filter(function() { 

    var childNodes = this.childNodes, 
     text = ''; 

    $.each(childNodes, function(i, node) { 
     if (node.nodeType != 3) { 
      return true; 
     } 
     text += node.data; 
    }); 

    return text == 'jQuery'; 

}); 

jsFiddle

此外,如果您要执行不区分大小写的搜索,请务必在文本节点上使用toLowerCase(),然后再与您的字符串的小写版本进行比较来进行匹配。

+0

我相信这个逻辑会失败,例如:'

jQueryMore content
',因为你只比较firstChild节点类型。 http://jsfiddle.net/YJfbv/ OP似乎只想返回只包含单词“jQuery”而没有其他的节点。这只是我的猜测! –

+0

@AdamTerlson:听起来像你正在看我的代码的早期版本:) – alex

+0

我确实。良好的编辑。但是,当nodeType不是文本类型时,不应该只返回false而不是true? –

0

您的逻辑失败,因为您正在比较.text()值。这将剥离所有HTML标记,包括子节点的标记。如果你想不包含子元素和匹配的文本元素,只需修改于:

$("body *:visible").filter(function(){ return $(this).html().toLowerCase() == 'jquery' }); 

现在虽如此,这是一个非常邪恶的过滤器,我怀疑是相当缓慢的。

+0

谢谢大家。这个问题可以结束。 – Slava

0

这是因为text()返回元素的内部文本,其中包括其所有后代的内部文本。

你必须为了使用contents()只匹配直接子元素和文本节点:

$("body *:visible").filter(function() { 
    var textNodes = $(this).contents().filter(function() { 
     return this.nodeType == 3; 
    }); 
    return (textNodes.length > 0 && textNodes[0].nodeValue == "jQuery"); 
}); 
+0

但是,这看起来不错,它不会仅仅比较第一个文本节点吗? – alex

+0

@alex,确实,它只是检查第一个文本节点。这是因为提问者只想匹配其* full *内部文本等于'jQuery'的元素。在这种情况下,不会存在空白文本节点,并且该值将存储在单个文本节点中。 –

+0

Frédéric,谢谢。您的解决方案完美运行,但需要大约1-2秒才能找到该元素。有没有机会提高这种方法的性能(我需要它包含在我的Selenium 2(WebDriver)项目中,并且测试的性能对我来说非常重要)? – Slava