jQuery Tip: Matching Paired Elements

Posted by Dan on Mar 1, 2008 @ 12:13 PM

A common task you might want to accomplish in jQuery is to match elements that are paired together. For example, you have a page full of authors and only want to show their biographies if they click on a link.

Your first thought might be to do something like the following:

$(document).ready(function (){
    $("dt").click(function (){
        $("dd").slideDown();
    });
});

The problem with this approach is that when you click on the <dt /> tag it will open all of the <dd /> tags. This is because the selector being used specifies all of the <dd /> tags and doesn't do anything to filter the tags to the specific matching tag.

While there are many ways to solve this problem, depending on how your DOM is structured, this method should work any time you have a DOM structure in which your paired elements appear in the same order of the DOM. This means my two selectors should return an array of elements where the positions of the paired elements match exactly. For example:

$("a.author")[0] == $("div.author_bio")[0];
$("a.author")[1] == $("div.author_bio")[1];
$("a.author")[2] == $("div.author_bio")[2];
$("a.author")[3] == $("div.author_bio")[3];
$("a.author")[4] == $("div.author_bio")[4];

If the order of the items in the array don't match, then you won't achieve the effect your after. The trick is to use the $.each() method to loop through the results. This allows you to find the paired element and attach the event to each individual element.

$(document).ready(function (){
    // loop through each of the "a.author" elements
    $("a.author").each(function (i){
        // use the loop counter argument to locate its paired match
        var $match = $("div.author_bio").eq(i);

        // attach a toggle effect to the "a.author" element
        $(this).toggle(
            function (){
                // slide down the matching "div.author_bio" element
                $match.slideDown();
            },
            function (){
                // slide up the matching "div.author_bio" element
                $match.slideUp();
            }
        );
    });
});

I've set up a page with a working example, so make sure to exam the code behind the scenes.

Categories: jQuery

7 Comments

  • Thanks, Dan!

    Just what I needed to solve the problem when multiple pairs of elements are created dynamically using ColdFusion!

    Great work!
  • That's a much cleaner technique than the one I'm currently employing to match elements like that: thanks for the tip.
  • Dan,
    Not sure how well this would work in other situations, but wouldn't this be an easier (and shorter) method for this specific example:

    $("dt").click(function (){
       $(this).next().slideToggle();
    });

    ~Max
  • @Max:

    Using the slideToggle() would definitely shorten things down, but I wanted to clearly illustrate the concept, which is why I choose the toggle() method since you can use that to build more complicated effects.

    To answer your direct question, yes--that would be the shortest way to implement the solution for that DOM model. As I stated, there are many methods to resolve this problem.

    Personally, I do prefer implementing my functions in a way that potentially don't break the site if I decide to modify the DOM a little bit. For example, let's say you decided to place all the dt tags sequentially and then float them left and then place all the dd tags so that you have a menubar like line of terms and then have the definitions slide out underneath. Using the technique above you don't have to change your function. However, if your code is relying on the order of the elements in the DOM you need to start changing your functions.

    There's nothing wrong with your method--its certainly the most concise.

    (Also, as a side not I actually created this blog entry to help a user on the jQuery Mailing List and the next() method wouldn't have worked in his situation.)
  • Thank you.

    I've been on the last 2 issues of a jQuery test for about two days now. this simply solves one of them.
  • Hey, Dan,

    Just wanted to let you know that I was able to use what I learned from this tip to develop a jQuery-powered technique for rearranging items on a page when using an iPhone/iPod Touch (since drag-and-drop doesn't work on those devices).

    It might have been possible to do it another way, but it would have been a lot harder, so thanks again.
  • @Brian:

    Glad this tip helped you out. jQuery is a magnificent piece of work and it can take a while to really learn the API. I'm still learning every day!

Comments for this entry have been disabled.