Skip to main content

Bug Tracker

Side navigation

#8066 closed bug (wontfix)

Opened January 26, 2011 08:05PM UTC

Closed January 27, 2011 10:01PM UTC

Element order not maintained correctly if chaining find and parents

Reported by: Owned by:
Priority: low Milestone:
Component: traversing Version: 1.4
Keywords: Cc:
Blocked by: Blocking:

Element order not maintained correctly if chaining find and parents. That is, if one has a set of elements which they must narrow down, then find a specific parent element, and then access different children, they must currently handle all the iteration themselves after the call to find because after a call to parents is made, the order will not be maintained correctly.

Image a DOM including:

<div class="some-parent">
   <h3>Title 1</h3>
   <div class="some-other-parent">
       <input class="cmpnId" type="hidden" value="2"/>
       <input class="cmpnType" type="hidden" value="IMAGE"/>
<div class="some-parent">
   <h3>Title 2</h3>
   <div class="some-other-parent">
       <input class="cmpnId" type="hidden" value="3"/>
       <input class="cmpnType" type="hidden" value="IMAGE"/>
<div class="some-parent">
   <h3>Title 3</h3>
   <div class="some-other-parent">
       <input class="cmpnId" type="hidden" value="6"/>
       <input class="cmpnType" type="hidden" value="TASK"/>

Next imagine jQuery JS:

    $(window.document).find('.some-parent .some-other-parent input.cmpnType[value="IMAGE"]').parents('.some-parent');

as to give one the top level parents of all the image component wrappers so to speak. It seems logical to assume:

    $($(window.document).find('.some-parent .some-other-parent input.cmpnType[value="IMAGE"]').parents('.some-parent')[0]).find('input.cmpnId').val()==='2';

But this is not the case. It can be the latter, and thus far, seems to be the case always as if a reverse iterator is used for parents. I'm currently using 1.4.2, and I don't see anything in the change logs which shows this being fixed. I will try 1.4.4 and report more information, but I wanted to go ahead and file this while it was on my mind as it seems a big deal.

Attachments (0)
Change History (7)

Changed January 26, 2011 08:12PM UTC by comment:1

I downloaded 1.4.4 and it has the same issue.

Changed January 26, 2011 08:20PM UTC by comment:2

Just so I'm completely clear here. The order is reversed after the call to parents. Thus, the order is not maintained as seems one would logically expect.

Changed January 26, 2011 10:48PM UTC by ajpiano comment:3

owner: →
status: newpending

.parents() is ordered by closesness of the parent to the original element, so I am pretty sure this is intended behaviour. If you do believe this is a bug, please create a testcase on jsFiddle and make sure to test against the 0 GIT version (which is jQuery 1.5 RC1+ at the moment). Thanks for your time!

PS, you may want to consider using closest instead of parents() or you could get a lot of duplicate iterations ...

Changed January 27, 2011 02:59PM UTC by comment:4

status: pendingnew

What does closeness mean in this context? When I read that I still think the order would be preserved, and I think this because I'm thinking of the parents of the original elements. In other words, I have a list of elements which I'm asking for the parents. In each case, it would be the parents of that element as it pertains to its location in the list, and thus I have elements 1,2,3 and then I'm wanting 1->parent, 2->parent, and 3->parent, and the order is based on that which is being requested or the parents of these elements which are in an order. I can write up a test case which will get the elements, and then make a list of the parents and compare them individually to see if the order of the parents matches that of the original elements from find, and fail if that is not the case, but I wanted to better understand exactly what you meant by closeness.

Thank you.

Changed January 27, 2011 03:01PM UTC by anonymous comment:5

Wanted to add that I have no idea why this tracker forces me to leave as new after you changed it to pending, but I can't change that as there is a single radio/option button which I can not deselect. Just a heads up on why it changed that back to new.

Changed January 27, 2011 05:38PM UTC by ajpiano comment:6

status: newpending

By closeness I mean that the immediate parent will be the first in the set, that element's parent will be the second in the set, the second element's parent will be the third in the set, etc. That is the opposite of what you'd get if you searched from a parent downwards to find all its nested children.

Again, if you do think there is a legit bug here please file a test case, but I am reasonably confident there isn't one. Don't worry about Trac quirkiness - thanks for getting back to us! "Pending" is just our way of putting the ball back in your court, and when you reply it goes back to "new."

Changed January 27, 2011 10:01PM UTC by jitter comment:7

component: unfiledtraversing
priority: undecidedlow
resolution: → wontfix
status: pendingclosed

I think the reporter understand that .parents() returns the elements in reverse DOM order as shown here .

What he is getting at with his report is that - if there is more then one element in the set of matched elements then - the parents of the individual elements aren't returned in the DOM order relative to the position of the elements in the set.

This is difficult to explain. Just look at this test case and check how the order of the parents returned changes from 1.3.2 to 1.4+.

1.3.2 : [div#i1.1, div#i1, div#i0, div#i2.1, div#i2]
1.4+  : [div#i2.1, div#i2, div#i1.1, div#i1, div#i0]

The reversed dom-order of the parents is still ok, but the order in which the parents get returned no longer matches the dom order of their children.

Now what I'm a little unsure off is if this should be fixed at all. The behavior changed with 1.4 but has stayed identical since then. So we are much more likely to break things by fixing this then by leaving it as it is.

This part of the behavior also isn't specified in the documentation and thus shouldn't be relied upon. Additionally when using .parents() on multiple elements in general you can't know how many elements are going to be returned or which elements are a "parent-chain" or which elements are the parent of which element in the matched set. If you would (need to) know all of this you shouldn't be using .parents().

Thus by looking at your original test case I suggest another way of doing this. Which has the benefit of being more readable and making clear what your intent is and doesn't rely on an unspecified behavior of .parents().

$('.some-parent').has('.some-other-parent input.cmpnType[value="IMAGE"]').first();

Considering all of this I close this ticket. So unless you make a really good point why this indeed needs fixing the behavior won't be changed.