filter() by inner text returns empty parent nodes
I need to find all elements on the page which match some inner text:
$("body *:visible").filter( function(){ return $(this).text() == 'jQuery' } );
However I get parent nodes whith mathed elements in some cases.
E.g. 1st match: <li><a href="#">Jquery</a></li> 2nd match: &开发者_如何转开发lt;a href="#">Jquery</a> How can I remove all the elements with parent nodes from the selection and leave only the elements which really contain defined inner text? For the test you can try to execute the script above on jquery.comYour logic is failing because you're comparing .text()
values. This will strip off all HTML markup, including that of children nodes. If you want elements that contain no child elements and match that text, simply modify to:
$("body *:visible").filter( function(){ return $(this).html().toLowerCase() == 'jquery' });
Now that having been said, this is a pretty evil filter that I'd suspect is rather slow.
This code will iterate over text nodes of that element only and then make the comparison.
$("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.
Also, if you want to do a case insensitive search, be sure to use toLowerCase()
on the text nodes before the comparison to the lowercase version of your string to match.
That's because text() returns the inner text of the element, which includes the inner text of all its descendants.
You'll have to use contents() in order to only match the immediate children elements and text nodes:
$("body *:visible").filter(function() {
var textNodes = $(this).contents().filter(function() {
return this.nodeType == 3;
});
return (textNodes.length > 0 && textNodes[0].nodeValue == "jQuery");
});
精彩评论