jQuery a solution between children() and find(): anything that looks like closest()?

3.3k Views Asked by At

Based on the different answers received, the only solution using jQuery without implementing our own selector function is a basic selector with ":first" or followed by ".eq(0)" for jQuery.

I wanted to know if their were any kind of max depth option or a function like "get only the first result then return it" but it seems it's not available in jQuery since even :first in the selector does not seem to be faster that a call to .eq(0) Thanks for all the comments.


Original post:

I'm wondering if a function like "closest" is available for the children elements.

Let's say I have an html structure like that:

div.container > [* some elements, I can't use children()] > div.sub1 > div.sub2 > div.sub1 > [other various children elements]

If I want the first div.sub1 I'm doing something like:

$("div.container").find("div.sub1").eq(0)

The problem is that we cannot specify a "max depth" so it will be searched in ALL the children. I see it as a performance issue.

I'm talking about "max depth" because I could list the possibles selectors cases but it would be a long list, about 6-10 items depending on the case.

Anyone has a solution for this?

Thank you

1

There are 1 best solutions below

0
On

You can possibly get this by combining the child-selector (>) and the wildcard (*) at various amounts:

// max-depth: grand-children
$('.container').find('> .sub1, > * > .sub1').first();

// max-depth: great-grand-children
$('.container').find('> .sub1, > * > .sub1, > * > * > .sub1').first();

And, since this can be rather tedious to have hard-coded, you can use a custom method to build the selector for you:

jQuery.fn.findAtDepth = function (selector, maxDepth) {
    var depths = [], i;

    if (maxDepth > 0) {
        for (i = 1; i <= maxDepth; i++) {
            depths.push('> ' + new Array(i).join('* > ') + selector);
        }

        selector = depths.join(', ');
    }

    return this.find(selector);
};

$('.container').findAtDepth('.sub1', 3).first();

Examle: http://jsfiddle.net/V82f3/2/


The primary pitfall of this is that it's limited to relatively simple selectors (or possibly just to single selectors):

$('.container').findAtDepth('.sub1, .sub2', 3).first();

This will search for .sub1 at a max depth of 3, but for .sub2 at any depth.