Search code examples
jquerysiblings

jquery understanding how siblings method works


i have the following markup:

    <ul id="selected-plays" class="clear-after">
    <li>Comedies
      <ul>
        <li><a href="/asyoulikeit/">As You Like It</a></li>
        <li>All's Well That Ends Well</li>
        <li>A Midsummer Night's Dream</li>
        <li>Twelfth Night</li>
      </ul>
    </li>
    <li>Tragedies
      <ul>
        <li><a href="hamlet.pdf">Hamlet</a></li>
        <li>Macbeth</li>
        <li>Romeo and Juliet</li>
      </ul>
    </li>
    <li>Histories
      <ul>
        <li>cat</li>
        <li><a href="hamlet.pdf">dog</a></li>            
      </ul>
    </li>
    </ul>

i'm trying to get all the nested li elements that don't contain any links. so, my jquery looks like

    var list = $('li > a').parent().siblings(); 

it returns 6 results and i understand that, but suppose i add a couple additional li elements to "Histories" like so:

    <li>Histories
      <ul>
        <li>cat</li>
        <li><a href="hamlet.pdf">dog</a></li>
        <li><a href="hamlet.pdf">mouse</a></li>
        <li><a href="hamlet.pdf">monkey</a></li>
      </ul>
    </li>

if i run the same jquery code, i now get 9 results, the original 6 plus the 3 li elements that contain "dog," "mouse," and "monkey." this is where i'm confused. here's how i think it works.

  • comedies - 3 siblings
  • tragedies - 2 siblings
  • histories
    • 1st matching element (dog) -> 3 siblings (cat, mouse, monkey)
    • 2nd matching element (mouse) -> 3 siblings (cat, dog, monkey)
    • 3rd matching element (monkey) -> 3 siblings (cat, dog, mouse)
    • result set so far (cat*3, dog*2, mouse*2, monkey*2)
    • final result set (removing dupes) (cat, dog, mouse, monkey) - 4 total

3+2+4 = 9

is that how it works?


Solution

  • In order to understand this, let's go through it piece by piece. First, the selector used.

    $('li > a')

    This is going to create an array of a elements which are children of the list element. In your first html block, this is going to return 3 a elements.

    .parent()

    Next, you look at each of the 3 a elements' parent. Which naturally is the li element. Again we end up with an array of 3 elements, this time li.

    .siblings()

    Now, each of the li elements is examined. It looks for siblings, as in elements at the same level (essentially this is just a count of the children elements from the parent excluding the the current one). So for your first example, this is (4-1) + (3-1) + (2-1) = 6.


    The change causes a slightly different iteration. After the first selector $('li > a') there are now 5 a elements matched. .parent() yields 5 li elements. .siblings() for the first two sets is the same. But for histories, what happens is that each li asks for its siblings (excluding itself). So for your second example, you get (4-1) + (3-1) + (4-1) + (4-1) + (4-1) = 14. However, these get added into the array of elements that jQuery manages, and part of that management is to not include duplicates. The histories will have duplicates.

    The first two sets are unaffected, leaving the same (4-1) + (3-1). But, since no duplicates are allowed, the histories set will instead be (4-1) + (4-3) + (4-4) which is where the 9 comes from (3+2+3+1+0). Note that last two sets (4-3 and 4-4) should have simply excluded themselves, but as a result of the duplication more elements were excluded. Totaling the difference there (2+3) yields the amount of duplication.