56

Is there a better way to select grandparent elements in jQuery in order to avoid this ?

$(this).parent().parent().parent().parent().parent().children(".title, .meta").fadeIn("fast");

Thanks.

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
aneuryzm
  • 63,052
  • 100
  • 273
  • 488
  • 1
    and what about children().children().children().children(".title") ? – aneuryzm Mar 03 '10 at 15:35
  • Couldn't resist, you can use $(this).gparent(2) with the code provided in my downvoted answer. Don't know why it's downvoted, since it's the solution that answers your question... – patrick Jan 18 '18 at 11:46

7 Answers7

61

You can use the parents() method which matches parents against a selector

http://api.jquery.com/parents/

Or if you're using 1.4 there is a new parentsUntil() method

http://api.jquery.com/parentsUntil/

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
Neil Aitken
  • 7,856
  • 3
  • 41
  • 40
28

In addition to parents(), as they've said, you should also check out closest(). Read the comparison in the documentation there, but its main differences are that it searches for only one result, and it includes $(this) in what it searches (could get the thing you're searching from if you're not specific enough). Pros and cons.

6

I wrote this simple plugin because I thought I had an unambiguous class selection somewhere giving me errors. Selecting grandparent seemed more direct than $().parents() for this particular case.

Well, I used this once then realized I actually had a spelling error. Not sure how helpful it really is. $('myelem').gparent(2); gets you the grandparent of 'myelem'.

(function( $ ){
$.fn.gparent = function( recursion ){
    if( recursion == undefined ) recursion = 2;
    if(typeof(recursion) == "number"){
        recursion = parseInt( recursion );
        if( recursion > 0 ){
            gparent_holder = $(this);
            for(var gparent_i = 0; gparent_i < recursion; gparent_i++){
                gparent_holder = gparent_holder.parent();
            }
            return gparent_holder;
        }
        else return false;
    }
    else return false;
}
})( jQuery );
Femi
  • 61
  • 1
  • 1
  • I like this solution. We're into jQuery >2.0 and there's still no straightforward, clean way to navigate 'k' levels up. Seems like a trivial thing to add to the base framework. – Evan Steinkerchner Jul 22 '14 at 14:56
  • nice to bring up recursiveness. A recursive function are a great solution for problems like these... yet your solution is not recursive. I posted a recursive snippet as an answer to this question – patrick Jul 08 '16 at 22:32
3

Use the parents() selector to get all parents of an element. You can then either search the collection, or iterate over it if you want to affect all ancestors.

Traveling Tech Guy
  • 27,194
  • 23
  • 111
  • 159
3

@Femi had an answer to do this, and mentioned recursion, yet his solution was not recursive, here's a recursive jQuery solution for getting ancestors of an item:

$.fn.gparent = function( recursion ){
   console.log( 'recursion: ' + recursion );
   if( recursion > 1 ) return $(this).parent().gparent( recursion - 1 );
   return $(this).parent();
};

If this is your HTML:

<div id='grandparent'>
  <div id='parent'>
    <div id='child'>
      child
    </div>
  </div>
</div>

You can call

console.log( $('#child').gparent( 2 ) );

to get the grandparent of element child. Here's the JSFiddle

patrick
  • 11,519
  • 8
  • 71
  • 80
  • 3
    why on earth does this get a downvote without a comment... it's recursive, it's documented, a Fiddle provided to show it works, and it's the answer to the OP's question... SO should make it impossible to downvote without an explanation. Now a perfectly working solution (which I use a lot!) is not showing as a valid one... – patrick Jan 18 '18 at 11:43
  • 1
    Instead of adding our own function to do `gparent(2)` we can use `parents().eq(2)` – Stéphane Bruckert Oct 20 '18 at 15:22
1

Using parents() and children() get the same results.

Example instead of using this :

$(this).parent().parent().parent().children(".title").fadeIn("fast");

you can use this :

$(this).parents().children(".title").fadeIn("fast");
odil-io
  • 180
  • 9
NJENGAH
  • 955
  • 15
  • 12
0

Basic Example

<div id="europe">
   <div>
       <span id="denmark">Minimum Stok</span> 
   </div>
</div>

$('span#denmark').parents("div#europe").attr('class', 'place')

Result;

<div id="europe" class="place">
   <div>
       <span id="denmark">Minimum Stok</span> 
   </div>
</div>
Melisa
  • 310
  • 2
  • 16