I'm looking for a way to select elements that contain a certain element and then filter the results to get only the highest level. Difficult to explain but made easier with an example:
<div id="one">
<div id="two">
<div id="three" class="find-me"></div>
</div>
</div>
<div id="four">
<div id="five" class="find-me"></div>
</div>
In this case, I would want my set to contain #one and #four. If I try to do something like this:
var elements = $('div').has('.find-me');
I get elements #one, #two and #four.
Note: By 'highest level' relates to the topmost element in the first selector, $('div')
in this case.
Well the definition of what the highest level
is, is a bit ambiguous because in practice if there is any .find-me
in your page the highest level parent would be html
tag! which is useless.
By defining your problem more specifically you can come up with a clearer definition for this highest-definition
and for example say the farthest div parent
et. and in order to traverse parents of an element you can use .parents()
and .closest()
methods.
var farthestDiv = $(".find-me").parents("div").last();
obviously if you have more than one occurances of find-me
you need to run this in a .each()
loop.
see an example here: http://jsfiddle.net/GsQDb/3/
Assuming by "top level", you mean a direct descendant of the body tag, you can use this one liner. It finds all objects with a .find-me
class, then searches the parents for a tag that is a descendant of the body tag (which will be the top level).
$(".find-me").parents("body > *")
You can see it work here: http://jsfiddle.net/jfriend00/9LF6u/
This has these advantages:
.find-me
objects (which will be a fast operation internally in most browsers via getElementsByClassName
) and just walks up their parent hierarchy..parents(selector)
method to reflect that change.use filter to filter out elements that don't match what you want after your first selector. example:
var elements = $('div.find-me').filter(function(idx){
return !$(this).parents('div.find-me').length;
});
This will do what you want, it will find the elements first and then find the highest elements of those and create a jQuery object of the found highest elements.
var elements = $('div.find-me'), highest = [];
elements.each( function(){
var parent = this, body = document.body;
while( parent && parent.parentNode !== body ) {
parent = parent.parentNode;
}
if( $.inArray( parent, highest ) < 0 ) {
highest.push( parent );
}
});
highest = jQuery( highest );
jsfiddle:
http://jsfiddle.net/D3jC8/2/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With