2011-07-20 38 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