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 my table structure:
<table border="0"> <tr> <td colspan="2">Header</td> </tr> <tr> <td>data</td> <td>data</td> </tr> <tr> <td>data</td> <td>data</td> </tr> <tr> <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>
Any thoughts on how can I accomplish this task. Using div this task seems quite simple, but I have tabular data which I want to manipulate.
One idea I can think of is to use css class in every row which distinguish rows in under each header and use JQuery to expand/collapse those rows only when header is clicked. But if my table has 10-15 headers then it seems difficult to keep track of css classes.
Please suggest a suitable way to achieve this.
The expandable table can be achieved by using JavaScript with HTML. By Clicking on a row of the table, it expands and a sub-table pops up. When the user again clicks on that row the content will hide.
To set the table width in HTML, use the style attribute. The style attribute specifies an inline style for an element. The attribute is used with the HTML <table> tag, with the CSS property width.
Just set the width and height of your table to 100%.
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.
$('.header').click(function(){ $(this).nextUntil('tr.header').slideToggle(1000); });
<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>
Another Example:
$('.header').click(function(){ $(this).find('span').text(function(_, value){return value=='-'?'+':'-'}); $(this).nextUntil('tr.header').slideToggle(100); // or just use "toggle()" });
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);
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()
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With