Well, I think I solved it (barring edge cases) using the following:
function findByDepth(parent, child, depth){
var children = $();
$(child, $(parent)).each(function(){
if($(this).parentsUntil(parent, child).length == (depth - 1)){
children = $(children).add($(this));
}
});
return children;
}
// this would successfully return the 3.X elements of an HTML snippet structured
// as my XML example, where <parent> = #parent, etc.
var threeDeep = findByDepth('#parent', '.child', 3);
However somebody has to get the accepted answer here, and I'm not going to answer it myself and abscond with your well earned rep. So, if anyone wants to add anything, such as provide insight into optimizing this function (before I go and $.extend()
it in) I'll likely mark your answer correct, otherwise falling back to marking whoever was first on my initial question.
By the way, check it in the fiddle: http://jsfiddle.net/5PDaA/
Sub-update
Looking again at @CAFxX's answer, I realized that his approach is probably faster, taking advantage of querySelectorAll
in browsers that can. Anyways, I revised his approach to the following, yet it's still giving me guff:
$.fn.extend({
'findAtDepth': function(selector, depth){
var depth = parseInt(depth) || 1;
var query = selector;
for(var i = 1; i < depth; i++){
query += (' ' + selector);
}
return $(query, $(this)).not(query + ' ' + selector);
}
});
It works fine the first time, however as context changes to an element found in the selector
, it fails for some reason.
Alright, I was foolishly unclear, and uninformed as to the specs for what I'm doing. Since I've reviewed my implementation I'll update here; I'll mark the earliest answer that meets my initial requirements given people think me a fool for updating so gratuitously (I wouldn't blame you) however my bonus mention below is essentially a requirement. I'd post another question, but it'd likely get closed from duplication. Regardless, +1's all around for your patience:
Depth specification of a given child is necessary (given it's wrapped in a function or otherwise) thus isolating a child and equally nested (not necessarily siblings) matching elements.
For instance (XML for brevity):
<!-- depth . sibling-index-with-respect-to-depth -->
<parent>
<child> <!-- 1.1 -->
<child> <!-- 2.1 -->
<child> <!-- 3.1 -->
<child></child> <!-- 4.1 -->
</child>
<child> <!-- 3.2 -->
<child></child> <!-- 4.2 -->
</child>
</child>
<child> <!-- 2.2 -->
<child></child> <!-- 3.3 -->
</child>
</child>
</parent>
Given a depth specified of 2
, all 2.X
elements are selected. Given 4
all 4.X
, and so on.
Using the native functionality of jQuery, is there a way to select only the "first-generation" of descendants matching a selector? For instance:
Note: The following is only an example. .child
elements are nested in a parent at an arbitrary level.
Bonus: As my proposed syntax below indicates, an answer that provides a way to specify a depth to which the selection should traverse would be incredible.
// HTML
<div id="parent">
<div>
<div class="child"> <!-- match -->
<div>
<div class="child"> <!-- NO match -->
</div>
</div>
</div>
<div class="child"> <!-- match -->
<div>
<div class="child"> <!-- NO match -->
</div>
</div>
</div>
</div>
</div>
And:
// jQuery
$('#parent').find('.child:generation(1)'); // something in that vein
Trying to select from the context of #parent
, the jQuery :first
doesn't work here as it only hits the first matched .child
.
Try this (KISS!):
$("#parent .child").not(".child .child");
edit: to get the second level:
$("#parent .child .child").not(".child .child .child");
the third:
$("#parent .child .child .child").not(".child .child .child .child");
and so on... so you could have (untested):
function findChildrenDeepDown(parentSelector, level) {
level = parseInt(level);
var firstSelctor = parent, notSelector = ".child", i;
for (i=0; i<level; i++) {
firstSelector += " .child";
notSelector += " .child";
}
return $(firstSelector).not(notSelector);
}
findChildrenDeepDown("#parent", 3); // find third-level children of #parent
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