26

I'm having difficulty implementing an accordion effect on three different tables using jQuery and I could use some assistance. Right now it works o.k. When I click on the header rows the subsequent rows show, but I'd like some type of animation. I'd also like to have the first table show completely, but I'm a newbie and this is above my head.

Here is my HTML.

<table class="research">
                <tbody>
                    <tr class="accordion">
                        <td colspan="3">This is the header</td>
                    </tr>
                    <tr>
                        <td>Research</td>
                        <td>Description</td>
                        <td>Partner</td>
                    </tr>
                    <tr>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                    </tr>
                </tbody>
            </table>

            <table class="research">
                <tbody>
                    <tr class="accordion">
                        <td colspan="3">This is the header</td>
                    </tr>
                    <tr>
                        <td>Research</td>
                        <td>Description</td>
                        <td>Partner</td>
                    </tr>
                    <tr>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                    </tr>
                </tbody>
            </table>

            <table class="research">
                <tbody>
                    <tr class="accordion">
                        <td colspan="3">This is the header</td>
                    </tr>
                    <tr>
                        <td>Research</td>
                        <td>Description</td>
                        <td>Partner</td>
                    </tr>
                    <tr>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                        <td>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</td>
                    </tr>
                </tbody>
            </table>

And here is my jQuery:

$(function() {
  $(".research tr:not(.accordion)").hide();
  $(".research tr:first-child").show();
  $(".research tr.accordion").click(function(){
  $(this).nextAll("tr").toggle();
    });
  });
user965879
  • 501
  • 1
  • 6
  • 16

2 Answers2

36
$(function() {
  $(".research tr:not(.accordion)").hide();
  $(".research tr:first-child").show();
    
  $(".research tr.accordion").click(function(){
      $(this).nextAll("tr").fadeToggle(500);
  }).eq(0).trigger('click');
});

.fadeToggle(500); animates the display of the elements rather than just showimg/hiding them.

.eq(0).trigger('click'); triggers a click on the first header so that it's content will be shown when the page loads.

A cool effect to use is slideUp() and slideDown() but it appears as though you can't use them with table rows.

Here is a demo: http://jsfiddle.net/Xqk3m/

Update

You can also optimize your code a bit by caching the .research selector:

$(function() {
    var $research = $('.research');
    $research.find("tr").not('.accordion').hide();
    $research.find("tr").eq(0).show();
    
    $research.find(".accordion").click(function(){
        $(this).siblings().fadeToggle(500);
    }).eq(0).trigger('click');
});

In this example I also removed all the string selectors in favor of function selections (e.g. used .not() instead of :not()). The functions for DOM traversal are faster than putting selectors in a string.

Here is a demo: http://jsfiddle.net/Xqk3m/1/

Update

And last but not least, if you want it to be an accordion where when you open one section the rest close, here's a solution:

$(function() {
    var $research = $('.research');
    $research.find("tr").not('.accordion').hide();
    $research.find("tr").eq(0).show();
    
    $research.find(".accordion").click(function(){
        $research.find('.accordion').not(this).siblings().fadeOut(500);
        $(this).siblings().fadeToggle(500);
    }).eq(0).trigger('click');
});

$research.find('.accordion').not(this).siblings().fadeOut(500); is the important part, it selects all the .accordion elements except for the one that was clicked, then finds the siblings of all the .accordion elements selected and hides them.

Here is a demo: http://jsfiddle.net/Xqk3m/2/

Community
  • 1
  • 1
Jasper
  • 74,169
  • 13
  • 144
  • 142
  • Hi Jasper, Nice solution. :-) I am trying to get it to work on a dynamic table My table is within a DIV with id="mapcanvas" $("#mapcanvas").empty();$("#mapcanvas").css("height", "auto");$("#mapcanvas").html(" etc. The table shows correctly - with all the TR's visible, and clicking them no longer works. A hint as to what should be done to fix it would be much appreciated. Thank you.
    – user1355041 Dec 17 '15 at 00:02
  • Thanks Jasper. I worked it out. I should have put your code after the ;$("#mapcanvas").html( ...); No drinking enough coffee, it would seem – user1355041 Dec 17 '15 at 04:58
2

i added a fade effect. Check it - http://jsfiddle.net/XE6AG/1/

    $(function() {
      $(".research tr:not(.accordion)").hide();
      $(".research tr:first-child").show();
      $(".research tr.accordion").click(function(){
      $(this).nextAll("tr").fadeToggle();
       });
    });

this one is faster - http://jsfiddle.net/XE6AG/2/

    //this is fast
    $(function() {
      $(".research tr:not(.accordion)").hide();
      $(".research tr:first-child").show();
      $(".research tr.accordion").click(function(){
      $(this).nextAll("tr").fadeToggle("fast");
       });
    });

this one is really really slow - http://jsfiddle.net/XE6AG/3/

    //this is fast
    $(function() {
      $(".research tr:not(.accordion)").hide();
      $(".research tr:first-child").show();
      $(".research tr.accordion").click(function(){
      $(this).nextAll("tr").fadeToggle("fast");
       });
    });

you could also add easing to it for example - http://jsfiddle.net/XE6AG/4/.

theliberalsurfer
  • 1,821
  • 1
  • 21
  • 33
  • Thanks very much, Andrew! Appreciate it. Is there a way you can tell me how to have just the first table display in its entirety while hiding the other two? I want the user to see some content and not just the headers. – user965879 Jan 26 '12 at 23:35