expand/collapse table rows with JQuery

后端 未结 7 916
闹比i
闹比i 2020-11-27 11:09

I want to expand and collapse table rows when header columns is clicked. I only want to expand/collapse rows which are under the specific header (clicked).

Here is m

相关标签:
7条回答
  • 2020-11-27 11:22

    I would say using the data- attribute to match the headers with the elements inside it. Fiddle : http://jsfiddle.net/GbRAZ/1/

    A preview of the HTML alteration :

       <tr class="header" id="header1">
        <td colspan="2">Header</td>
       </tr>
       <tr data-for="header1" style="display:none">
         <td>data</td>
         <td>data</td>
       </tr>
       <tr data-for="header1" style="display:none">
         <td>data</td>
         <td>data</td>
       </tr>
    

    JS code :

    $(".header").click(function () {
       $("[data-for="+this.id+"]").slideToggle("slow");
    });
    

    EDIT: But, it involves some HTML changes. so I dunno if thats what you wanted. A better way to structure this would be using <th> or by changing the entire html to use ul, ol, etc or even a div > span setup.

    0 讨论(0)
  • 2020-11-27 11:24

    The easiest way to achieve this, without changing the HTML table-based structure, is to use a class-name on the tr elements containing a header, such as .header, to give:

    <table border="0">
      <tr class="header">
        <td colspan="2">Header</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
      <tr class="header">
        <td colspan="2">Header</td>
      </tr>
      <tr>
        <td>date</td>
        <td>data</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
    </table>
    

    And the jQuery:

    // bind a click-handler to the 'tr' elements with the 'header' class-name:
    $('tr.header').click(function(){
        /* get all the subsequent 'tr' elements until the next 'tr.header',
           set the 'display' property to 'none' (if they're visible), to 'table-row'
           if they're not: */
        $(this).nextUntil('tr.header').css('display', function(i,v){
            return this.style.display === 'table-row' ? 'none' : 'table-row';
        });
    });
    

    JS Fiddle demo.

    In the linked demo I've used CSS to hide the tr elements that don't have the header class-name; in practice though (despite the relative rarity of users with JavaScript disabled) I'd suggest using JavaScript to add the relevant class-names, hiding and showing as appropriate:

    // hide all 'tr' elements, then filter them to find...
    $('tr').hide().filter(function () {
        // only those 'tr' elements that have 'td' elements with a 'colspan' attribute:
        return $(this).find('td[colspan]').length;
        // add the 'header' class to those found 'tr' elements
    }).addClass('header')
        // set the display of those elements to 'table-row':
      .css('display', 'table-row')
        // bind the click-handler (as above)
      .click(function () {
        $(this).nextUntil('tr.header').css('display', function (i, v) {
            return this.style.display === 'table-row' ? 'none' : 'table-row';
        });
    });
    

    JS Fiddle demo.

    References:

    • addClass().
    • click().
    • css().
    • filter().
    • find().
    • hide().
    • nextUntil().
    0 讨论(0)
  • 2020-11-27 11:26

    using jQuery it's easy...

     $('YOUR CLASS SELECTOR').click(function(){
    
                $(this).toggle();
    });
    
    0 讨论(0)
  • 2020-11-27 11:37

    You can try this way:-

    Give a class say header to the header rows, use nextUntil to get all rows beneath the clicked header until the next header.

    JS

    $('.header').click(function(){
        $(this).nextUntil('tr.header').slideToggle(1000);
    });
    

    Html

    <table border="0">
      <tr  class="header">
        <td colspan="2">Header</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
      <tr>
        <td>data</td>
        <td>data</td>
      </tr>
    

    Demo

    Another Example:

    $('.header').click(function(){
       $(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
        $(this).nextUntil('tr.header').slideToggle(100); // or just use "toggle()"
    });
    

    Demo

    You can also use promise to toggle the span icon/text after the toggle is complete in-case of animated toggle.

    $('.header').click(function () {
        var $this = $(this);
        $(this).nextUntil('tr.header').slideToggle(100).promise().done(function () {
            $this.find('span').text(function (_, value) {
                return value == '-' ? '+' : '-'
            });
        });
    });
    

    .promise()

    .slideToggle()

    Or just with a css pseudo element to represent the sign of expansion/collapse, and just toggle a class on the header.

    CSS:-

    .header .sign:after{
      content:"+";
      display:inline-block;      
    }
    .header.expand .sign:after{
      content:"-";
    }
    

    JS:-

    $(this).toggleClass('expand').nextUntil('tr.header').slideToggle(100);
    

    Demo

    0 讨论(0)
  • 2020-11-27 11:43

    A JavaScript accordion does the trick.

    This fiddle by W3Schools makes a simple task even more simple using nothing but javascript, which i partially reproduce below.

    <head>
    <style>
    button.accordion {
        background-color: #eee;
        color: #444;
        font-size: 15px;
        cursor: pointer;
    }
    
    button.accordion.active, button.accordion:hover {
        background-color: #ffffd; 
    }
    
    div.panel {
        padding: 0 18px;
        display: none;
        background-color: white;
    }
    
    div.panel.show {
        display: block;
    }
    </style>
    </head><body>
    <script>
    var acc = document.getElementsByClassName("accordion");
    var i;
    
    for (i = 0; i < acc.length; i++) {
        acc[i].onclick = function(){
        this.classList.toggle("active");
        this.nextElementSibling.classList.toggle("show");
      }
    }
    </script>
    ...
    <button class="accordion">Section 1</button>
    <div class="panel">
      <p>Lorem ipsum dolor sit amet</p>
    </div>
    ...
    <button class="accordion">Table</button>
    <div class="panel">
      <p><table name="detail_table">...</table></p>
    </div>
    ...
    <button class="accordion"><table name="button_table">...</table></button>
    <div class="panel">
      <p>Lorem ipsum dolor sit amet</p>
      <table name="detail_table">...</table>
      <img src=...></img>
    </div>
    ...
    </body></html>
    

    if using php, don't forget to convert " to '. You can also use tables of data inside the button and it will still work.

    0 讨论(0)
  • 2020-11-27 11:44

    I expanded one of the answers, however my functionality is a bit different. In my version, different rows form different groups. And "header" row triggers collapsing/expanding of that particular group. Also, each individual subgroup memorizes state that its in. It might sound a bit confusing, you can test drive my version using jsfiddle. Hope this code snippets will be helpful to someone out there!

    HTML

    <table border="0">
      <tr>
          <th>Header 1</th>
          <th>Header 2</th>
      </tr>
      <tr>
        <td class='group1'>Group 1</td>
        <td>data 2</td>
      </tr>
      <tr class='group1'>
        <td>data 3</td>
        <td>data 4</td>
      </tr>
      <tr>
        <td class='group2'>Group 2</td>
        <td>data 2</td>
      </tr>
      <tr class='group2'>
        <td>data 3</td>
        <td>data 4</td>
      </tr>
      <tr class='group2'>
        <td class='sub_group1'>Sub Group 1</td>
        <td>data 6</td>
      </tr>
      <tr class='group2 sub_group1'>
        <td>data 7</td>
        <td>data 8</td>
      </tr>
      <tr class='group2 sub_group1'>
        <td>data 9</td>
        <td>data 10</td>
      </tr>
      <tr class='group2 sub_group1'>
        <td class='sub_sub_group1'>Sub Sub Group 1</td>
        <td>data 11</td>
      </tr>
      <tr class='group2 sub_group1 sub_sub_group1'>
        <td>data 12</td>
        <td>data 13</td>
      </tr>
      <tr class='group2 sub_group1 sub_sub_group1'>
        <td>data 14</td>
        <td>data 15</td>
      </tr>
      <tr class='group2'>
        <td class='sub_group2'>Sub Group 2</td>
        <td>data 11</td>
      </tr>
      <tr class='group2 sub_group2'>
        <td>data 12</td>
        <td>data 13</td>
      </tr>
      <tr class='group2 sub_group2'>
        <td>data 14</td>
        <td>data 15</td>
      </tr>
    </table>
    

    CSS

    table, tr, td, th
    {
        border: 1px solid black;
        border-collapse:collapse;
    }
    
    img.button_open{
      content:url('http://code.stephenmorley.org/javascript/collapsible-lists/button-open.png');
      cursor:pointer;
    }
    
    img.button_closed{
      content: url('http://code.stephenmorley.org/javascript/collapsible-lists/button-closed.png');
      cursor:pointer;
    }
    

    JS

    function CreateGroup(group_name)
    {
        // Create Button(Image)
        $('td.' + group_name).prepend("<img class='" + group_name + " button_closed'> ");
        // Add Padding to Data
        $('tr.' + group_name).each(function () {
            var first_td = $(this).children('td').first();
            var padding_left = parseInt($(first_td).css('padding-left'));
            $(first_td).css('padding-left', String(padding_left + 25) + 'px');
        });
        RestoreGroup(group_name);
    
        // Tie toggle function to the button
        $('img.' + group_name).click(function(){
            ToggleGroup(group_name);
        });
    }
    
    function ToggleGroup(group_name)
    {
        ToggleButton($('img.' + group_name));
        RestoreGroup(group_name);
    }
    
    function RestoreGroup(group_name)
    {
        if ($('img.' + group_name).hasClass('button_open'))
        {
            // Open everything
            $('tr.' + group_name).show();
    
            // Close subgroups that been closed
            $('tr.' + group_name).find('img.button_closed').each(function () {
                sub_group_name = $(this).attr('class').split(/\s+/)[0];
                //console.log(sub_group_name);
                RestoreGroup(sub_group_name);
            });
        }
    
        if ($('img.' + group_name).hasClass('button_closed'))
        {
            // Close everything
            $('tr.' + group_name).hide();
        }
    }
    
    function ToggleButton(button)
    {
        $(button).toggleClass('button_open');
        $(button).toggleClass('button_closed');
    }
    
    CreateGroup('group1');
    CreateGroup('group2');
    CreateGroup('sub_group1');
    CreateGroup('sub_group2');
    CreateGroup('sub_sub_group1');
    

    DEMO

    0 讨论(0)
提交回复
热议问题