Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this jQuery return an index of 3?

HTML:

<ul>
    <li class="selected">First Item</li>
    <li class="disabled">Second Item</li>
    <li class="separator">Third Item</li>
    <li>Fourth Item</li>
</ul>

jQuery:

alert($("li:not(.disabled,.separator)").index());

According to the documentation for index:

the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

Emphasis on first element. But the above code returns 3. Based on the documentation shouldn't this code return 0?

You can see it in action here: http://jsfiddle.net/Zf9Vv/

NOTE:

My selector matches two elements: the first and last LI.

like image 868
Abe Miessler Avatar asked Dec 08 '11 00:12

Abe Miessler


1 Answers

Edit (see comments) The original answer is incorrect... I'm going to keep it here for now so the comments make sense.

Looking at the jQuery source for index, you can see the following snippet:

if ( !elem ) {
    return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
}

Compare this to the corresponding (if very different) snippet from an earlier release, 1.6.2. Note the use of this[0]:

return jQuery.inArray( this[0],
// If it receives a string, the selector is used
// If it receives nothing, the siblings are used
elem ? jQuery( elem ) : this.parent().children() );

It seems that in the current version the this.prevAll part causes the problem. If you change it to this.eq(0).prevAll (which replicates what the index documentation states) then you get the correct value returned. So it would appear this is a jQuery bug.

In the 1.6.2 version, inArray is used. That method returns the index of the first argument in the second argument (or -1 if the first argument is not found in the second). As the first argument is this[0] (the first element in the matched set) we get the expected result.

Here's an updated fiddle with the modified jQuery source included. The correct result is alerted.


Original answer (this is incorrect):

Read the quoted part of the docs again carefully (bold highlighting added):

the return value is an integer indicating the position of the first element within the jQuery object relative to its sibling elements.

Just because two of the siblings have been removed from the matched set, it doesn't change the value returned by index. In other words, the matched element (<li>Fourth Item</li>) will always have index 3, relative to its siblings (unless, of course, new siblings are inserted into the DOM before the element in question).

like image 149
James Allardice Avatar answered Nov 15 '22 12:11

James Allardice