4

I have a specific id ("mysubid"), now I want to check if this element (this id) is in a child path of an other id ("mymainid").

Is there an easy way to do this or will I go upwards, element by element, to see if the element is in a child path.

By child path I am talking about something like this:

A > B > C > D

So D is in the Child Path of A,B and C

Chris
  • 4,325
  • 11
  • 51
  • 70
  • 3
    A more correct way to express this: *Is `mymainid` an **ancestor** of `mymsubid`?*. Or vice versa: *Is `mysubid` an **descendant** of `mymainid`?*. – Felix Kling Sep 24 '10 at 15:04
  • 1
    Thank you, yes that was what I tried to ask. I will remember these vocabularies for the next time. – Chris Sep 24 '10 at 15:18

7 Answers7

11

You all are making this very complicated. Use the descendant selector:

if ($('#mymainid #mysubid').length) {
    // #mysubid is inside #mymainid
}
kevingessner
  • 18,559
  • 5
  • 43
  • 63
  • this uses Sizzle engine and unneeded regex test, you *can* use `$('#mymainid',$('#mysubid')).length` which relies purely on `getElementById` :) – RobertPitt Sep 24 '10 at 15:28
  • 1
    @RobertPitt - I'm not sure about that. A quick bit of Firebug testing shows that the descendant selector is waaay faster than using context: 1.28ms per call v. 14.5ms per call (500 iterations each, Firebug 1.5.4 in Firefox 3.6.10). – kevingessner Sep 24 '10 at 15:55
  • then i may be wrong, I have not fully profiled the code, I have taken a look into the source and that's what it shows, I will look into that soon, thanks. – RobertPitt Sep 24 '10 at 16:01
4
var isInPath = $("#mysubid").closest("#mymainid").length > 0;
Dave Thieben
  • 5,388
  • 2
  • 28
  • 38
4
  if( $("#mymainid").find("#mysubid").length > 0 )
sathis
  • 547
  • 1
  • 3
  • 21
1
if($('#mysubid','#mymainid').length)
{

}

This will check to see if #mysubid is within #mymainid

jQuery( selector, [ context ] )
  • selector: A string containing a selector expression
  • context: A DOM Element, Document, or jQuery to use as context

This is a just an overlaod for $('#mymainid').find('#mysubid').lentgh btw, verified from: http://github.com/jquery/jquery/blob/master/src/core.js#L162

On another note, using a method such as $('#a #b') resorts to using the Sizzle Selector witch is slower than doing $('#a',$('#b')), witch uses purely javascript's getElementById

Note: as jQuery returns an empty object by default if the selection is not found you should always use length.

RobertPitt
  • 56,863
  • 21
  • 114
  • 161
  • You're missing a `.length` on the end of that. – BBonifield Sep 24 '10 at 14:51
  • yes as you was writing that I was performing a test to see what distinct variables there was and forgot about `length`, witch returns `0 or greater` and 0 is boolean-able – RobertPitt Sep 24 '10 at 14:54
  • Your first jQuery call isn't valid syntax: see http://api.jquery.com/jQuery/#jQuery1. The context must be an element or jQuery object, not another selector. – kevingessner Sep 24 '10 at 14:54
  • 1
    http://stackoverflow.com/questions/1777719/what-is-the-definition-of-an-implementation-detail – kevingessner Sep 24 '10 at 15:04
  • @Robert: I think you better refer to line 171: http://github.com/jquery/jquery/blob/master/src/core.js#L171 – Felix Kling Sep 24 '10 at 15:08
  • I never stated it was valid sir,I just know that this is mealy a an overload for `$('#a').find('#b')`, witch was also stated in my post, if the OP Wishes for STRICT Standards then I will be happy to change my answer to a method that has been implemented into the docs. – RobertPitt Sep 24 '10 at 15:12
  • @Felix, Line 171 refers to passing jquery objects like so: `var a = $('a');` followed by `$(a)`, this is never executed because using my method your passing in 2 strings, please refer to line 92: http://github.com/jquery/jquery/blob/master/src/core.js#L92 – RobertPitt Sep 24 '10 at 15:15
1

If you want to see the entire chain as an array use elm.parentNode and work backwards. So, to answer your question (and the depth or distance between the elements) in POJ, you can use:

var doc = document,
child = doc.getElementById("mysubid"),
parent = doc.getElementById("mymainid"),
getParents = function (elm) {
    var a = [], p = elm.parentNode;
    while (p) {
        a.push(p);
        p = p.parentNode;
    }
    return a;
};
getParents(child).indexOf(parent);
AutoSponge
  • 1,444
  • 10
  • 7
1

I tried on various browsers and the DOM function below is between 3 to 10 times faster than the selector methods(jQuery or document.querySelectorAll)

    function is(parent){
        return {
            aParentOf:function(child){
                var cp = child.parentNode;
                if(cp){
                    return cp.id === parent.id ? 
                       true : is(parent).aParentOf(cp);
                }
            }
        }
    }

The call below will return true if A is a parent of D

is(document.getElementById('A')).aParentOf(document.getElementById('D'))

For just few calls I would use the $('#A #D').length
For very frequent calls I would use the DOM one.

Mic
  • 24,812
  • 9
  • 57
  • 70
0

Using the 'is' method actually returns a boolean.

if($('#mymainid').is(':has(#mysubid)')) // true

Going the other direction...

if($('#mysubid').parents('#mymainid').length) // 1
Josiah Ruddell
  • 29,697
  • 8
  • 65
  • 67