views:

38

answers:

4
<table>
    <tbody>
      <tr>
     <td class="TargetRow">Not this one</td>
      </tr>
    </tbody>
    <tbody> ... </tbody>
    <tbody>
      <tr>
     <td class="TargetRow">This one</td>
      </tr>
    </tbody>
    <tbody> ... </tbody>
    <tbody>
        <tr class="ContextRow"> ... </tr>
    </tbody>
</table>

Given the above HTML I'm trying to find a way of getting the contents of the preceding tr of class TargetRow. I.e. for the first preceding tbody that contains a td.TargetRow return the td.TargetRow

I'm using jQuery, at present I can get hold of the tbody containing the ContextRow using:

 jQuery(contextRow).parents("tbody").first()

How can I now find the previous sibling of that tbody that contains tr.ContextRow?

If there was just a way for me to say from contextRow walk up the DOM tree until you find an element matching "td.TargetRow" then that would be ideal.

Many Thanks.

A: 

Closest - .closest() does exactly what you need.

Gets the first ancestor element that matches the selector, beginning at the current element and progressing up through the DOM tree.

Your query would be,

$('.ContextRow').closest('tbody').siblings('tbody td.TargetRow').last(); 

It will return one object( unlike parents, which returns multiple element until top), or zero if id didn't find one.

simplyharsh
-1 closest looks at parents, has nothing to do with siblings
Bob Fincheimer
Ah sorry, my bad. I know what closest does. But as I said, my bad...
simplyharsh
+1  A: 
jQuery('.ContextRow').closest("tbody").siblings('tbody td.TargetRow:last'); 

EDIT: last not first

see it work: http://jsfiddle.net/wU6h9/

Mark Schultheiss
+1 for introducing me to jsFiddle, very nice!
chillitom
A: 

$(".ContextRow").closest("tbody").prevAll().find(".TargetRow").eq(0).css({color: "red"});

This returns the single closest previous .TargetRow

http://jsfiddle.net/LfWg3/3/

Ian Wetherbee
+1  A: 

I'm a little confused by your description, but when you say "find the previous sibling of that tbody that contains tr.ContextRow" it sounds like you want to find the previous <tbody> that contains an element with the class .contextRow and get its .targetRow.

If that's what you want, try this.

jQuery(contextRow).parents("tbody:first")
                  .prevAll('tbody:has(tr.ContextRow):first td.TargetRow');

If you meant to say td.TargetRow then do 'tbody:has(td.TargetRow):first td.TargetRow'.

patrick dw
$(contextRow).parents("tbody:first").prevAll("tbody:contains(.TargetRow):first") -- was what I was after, thanks very much
chillitom
@chillitom - You're welcome, but be aware that `:contains()` matches the given text, while `:has()` matches the given selector.
patrick dw