Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6713475
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T08:23:06+00:00 2026-05-26T08:23:06+00:00

Earlier, I answered this question , which was basically about removing a table row.

  • 0

Earlier, I answered this question, which was basically about removing a table row. This question came about as the result of the comments on that question. Given the following HTML:

<div><a href="#" class="removelink">remove</a></div>
<table>
    <tr>
        <td>Row 1</td> 
    </tr>
</table>

And the following jQuery:

$('.removelink').click(function(){
    $(this).parent().siblings('table tr:last').remove();
});

I would expect nothing to happen, because the siblings method should select the siblings of the currently matched element, optionally filtered by a selector. From the jQuery docs:

The method optionally accepts a selector expression of the same type
that we can pass to the $() function. If the selector is supplied, the
elements will be filtered by testing whether they match it.

Based on that, I read the above code as “get the siblings of the current element (the div) which are the last tr within a table“. Obviously there are no elements that match that description – there is a tr within a table, but it’s not a sibling of the div. So, I wouldn’t expect any elements to be returned. However, it actually returns the entire table, as if it ignores the tr:last part of the selector entirely.

What confused me further was that if you remove the :last pseudo-selector, it works as expected (returning no elements).

Why is the entire table removed by the above code? Am I just being stupid and missing something obvious? You can see the above code in action here.

Edit – Here’s a simplified version. Given the following HTML:

<div id="d1"></div>
<div>
    <span></span>
</div>

Why does the following jQuery return the second div:

$("#d1").siblings("div span:last");

I would expect it to return nothing, as there is not a span which is a sibling of #d1. Here’s a fiddle for this simplified example.

Update

Following the brilliant investigation from @muistooshort, I have created a jQuery bug ticket to track this issue.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T08:23:06+00:00Added an answer on May 26, 2026 at 8:23 am

    Allow me to expand on my comment a little bit. All of this is based on your second simplified example and jQuery 1.6.4. This is a little long winded perhaps but we need to walk through the jQuery code to find out what it is doing.


    We do have the jQuery source available so let us go a wandering
    through it and see what wonders there are to behold therein.

    The guts of siblings looks like this:

    siblings: function( elem ) {
        return jQuery.sibling( elem.parentNode.firstChild, elem );
    }
    

    wrapped up in this:

    // `name` is "siblings", `fn` is the function above.
    jQuery.fn[ name ] = function( until, selector ) {
        var ret = jQuery.map( this, fn, until )
    
        //...
    
        if ( selector && typeof selector === "string" ) {
            ret = jQuery.filter( selector, ret );
        }
    
        //...
    };
    

    And then jQuery.sibling is this:

    sibling: function( n, elem ) {
        var r = [];
    
        for ( ; n; n = n.nextSibling ) {
            if ( n.nodeType === 1 && n !== elem ) {
                r.push( n );
            }
        }
    
        return r;
    }
    

    So we go up one step in the DOM, go to the parent’s first child,
    and continue sideways to get all of the parent’s children (except
    the node we started at!) as an array of DOM elements.

    That leaves us with all of our sibling DOM elements in ret and
    now to look at the filtering:

    ret = jQuery.filter( selector, ret );
    

    So what is filter all about? filter is all about this:

    filter: function( expr, elems, not ) {
        //...
        return elems.length === 1 ?
            jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
            jQuery.find.matches(expr, elems);
    }
    

    In your case, elems will have have exactly one element (as #d1
    has one sibling) so we’re off to jQuery.find.matchesSelector which
    is actually Sizzle.matchesSelector:

    var html = document.documentElement,
        matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
    //...
    Sizzle.matchesSelector = function( node, expr ) {
        // Make sure that attribute selectors are quoted
        expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
    
        if ( !Sizzle.isXML( node ) ) {
            try {
                if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
                    var ret = matches.call( node, expr );
    
                    // IE 9's matchesSelector returns false on disconnected nodes
                    if ( ret || !disconnectedMatch ||
                            // As well, disconnected nodes are said to be in a document
                            // fragment in IE 9, so check for that
                            node.document && node.document.nodeType !== 11 ) {
                        return ret;
                    }
                }
            } catch(e) {}
        }
    
        return Sizzle(expr, null, null, [node]).length > 0;
    };
    

    A bit of experimentation indicates that neither the Gecko nor WebKit
    versions of matchesSelector can handle div span:first so we end
    up in the final Sizzle() call; note that both the Gecko and WebKit
    matchesSelector variants can handle div span and your
    jsfiddles work as expected in the div span case.

    What does Sizzle(expr, null, null, [node]) do? Why it returns an array
    containing the <span> inside your <div> of course. We’ll have
    this in expr:

    'div span:last'
    

    and this in node:

    <div id="d2">
        <span id="s1"></span>
    </div>
    

    So the <span id="s1"> inside node nicely matches the selector
    in expr and the Sizzle() call returns an array containing the
    <span> and since that array has a non-zero length, the matchesSelector
    call returns true and everything falls apart in a pile of nonsense.

    The problem is that jQuery isn’t interfacing with Sizzle properly in this case. Congratulations, you are the proud father of a bouncing baby bug.

    Here’s a (massive) jsfiddle with an inlined version of jQuery with a couple console.log calls to support what I’m talking about above:

    http://jsfiddle.net/ambiguous/TxGXv/

    A few things to note:

    1. You will get sensible results with div span and div span:nth-child(1); both of these use the native Gecko and WebKit selector engine.
    2. You will get the same broken results with div span:first, div span:last, and even div span:eq(0); all three of these go through Sizzle.
    3. The four argument version of the Sizzle() call that is being used not documented (see Public API) so we don’t know if jQuery or Sizzle is at fault here.
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I had asked a question about this earlier, but it didn't get answered right
Earlier today I answered this question . The question is about toggling a class
This question was asked earlier by someone else but never answered: MKAnnotation - Map
An earlier question was answered about getting the OrderID and the number of associated
Earlier this week I ask a question about filtering out duplicate values in sequence
Earlier today I asked this question which arose from A- My poor planning and
Earlier I asked this question How to correctly unit test my DAL? , one
Earlier I asked a question about why I see so many examples use the
Earlier today I asked a question about environ , and one of the more
Earlier I asked this question ( and after some googling I read Using your

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.