I have a table that can be toggled fine with a button or by clicking on the row. The problem is when the 1st column is spanned over 2 or more rows everything goes out of sync. Also would like the bottom border to move under the toggled area and the hovered area background colour to line up with additional rows (currently only works with 1st row because of the rowspan). Hopefully this makes sense and someone can help with this.
$(document).ready(function() {
$("#hide").click(function() {
$(".toggle").hide();
});
$("#show").click(function() {
$(".toggle").show();
});
$("#data tr td").click(function() {
$(this).parents(".pointer").next().toggle();
});
});
table {
border-collapse: collapse;
margin-top: 20px;
}
table,
th {
border: solid 1px;
padding: 10px;
}
tr:hover td {
background: #e5e5e5;
}
.toggle {
display: none;
}
.toggle.active {
display: table-row;
}
.pointer {
cursor: pointer;
border: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="hide">Hide All</button>
<button id="show">Show All</button>
<table>
<tr>
<th>header</th>
<th>header</th>
<th>header</th>
<th>header</th>
<th>header</th>
</tr>
<tbody id="data">
<tr class="pointer">
<td style="border-bottom:1px solid;" >DATA1</td>
<td style="border-bottom:1px solid;">data1</td>
<td style="border-bottom:1px solid;">data1</td>
<td style="border-bottom:1px solid;">data1</td>
<td style="border-bottom:1px solid;">data1</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 1a</td>
</tr>
<tr class="pointer">
<td style="border-bottom:1px solid;" rowspan="2">DATA2</td>
<td>data2</td>
<td>data2</td>
<td>data2</td>
<td>data2</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 2a</td>
</tr>
<tr class="pointer">
<td style="border-bottom:1px solid;">data2</td>
<td style="border-bottom:1px solid;">data2</td>
<td style="border-bottom:1px solid;">data2</td>
<td style="border-bottom:1px solid;">data2</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 2b</td>
</tr>
<tr class="pointer">
<td rowspan="3">DATA3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 3a</td>
</tr>
<tr class="pointer">
<td>data3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 3b</td>
</tr>
<tr class="pointer">
<td>data3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
</tr>
<tr class="toggle">
<td></td>
<td colspan="4">toggled area 3c</td>
</tr>
</tbody>
</table>
<tbody>
. tr.toggle
should have only one <td>
and it should have colspan='4'
<td>
of each <tbody>
has the class .pointer
and a rowspan
equal to the number of initially visible rows of said <tbody>
. ex. first <tbody>
has one row initially so td.pointer
in that <tbody>
has a rowspan='1'
.<td>
other than a <td>
nested within a tr.toggle
is clicked and is now visible, the corresponding .pointer
rowspan
increases by 1..pointer
rowspan
decreases by 1 when a tr.toggle
is not visible.<tr>
of data area 1 and 2 has an unclickable <td colspan='5'>
which contains a <hr>
. $("#all").on('click', function(e) {
$(this).toggleClass('show hide');
toggleRow(e);
});
$('.pointer').on('click', toggleRow);
$("td").not('.toggle > td').on('click', toggleRow);
function toggleRow(e) {
if (e.target.matches('td')) {
var toggle = $(this).parent().next('.toggle');
var data = $(this).closest('tbody');
var pointer = data.find('.pointer');
var rowspan = Number(pointer.attr('rowspan'));
toggle.toggle();
if (toggle.is(':visible')) {
pointer.prop('rowspan', `${rowspan+=1}`);
if (e.target.matches('.borderA')) {
data.find('.borderA').css('border-width', '0');
}
} else {
pointer.prop('rowspan', `${rowspan-=1}`);
if (e.target.matches('.borderA')) {
data.find('.borderA').css('border-width', '1px');
}
}
} else if (e.target.matches('#all')) {
$('tbody').each(function() {
var pointer = $(this).find('.pointer');
var rows = $(this).children().length;
var rowspan = Number(pointer.attr('rowspan'));
if ($('#all').hasClass('hide')) {
$('.toggle').show();
pointer.attr('rowspan', rows);
$(this).find('.borderA').css('border-width', '0');
} else {
$('.toggle').hide();
pointer.attr('rowspan', rowspan);
$(this).find('.borderA').css('border-width', '1px');
}
});
}
return false;
};
table {
margin-top: 20px;
border-spacing: 0;
}
table,
th {
border: solid 1px #000;
}
tr:hover td,
tbody:hover .pointer {
background: #e5e5e5;
}
.toggle {
display: none;
text-align: center
}
.pointer {
border: 0;
border-bottom: 1px solid #000;
}
.border,
.borderA {
border-bottom: 1px solid #000;
}
#all {
width: 10ch;
}
#all.hide::before {
content: 'Hide ';
}
#all.show::before {
content: 'Show ';
}
<button id="all" class='show'>All</button>
<table>
<thead>
<tr>
<th>header</th>
<th>header</th>
<th>header</th>
<th>header</th>
<th>header</th>
</tr>
</thead>
<tbody>
<tr>
<th class="pointer show" rowspan='1'>DATA1</th>
<td class='borderA'>data1</td>
<td class='borderA'>data1</td>
<td class='borderA'>data1</td>
<td class='borderA'>data1</td>
</tr>
<tr class="toggle">
<td class='border' colspan="4">1A</td>
</tr>
</tbody>
<tbody>
<tr>
<th class='pointer show' rowspan="2">DATA2</th>
<td>data2</td>
<td>data2</td>
<td>data2</td>
<td>data2</td>
</tr>
<tr class="toggle">
<td colspan="4">2A</td>
</tr>
<tr>
<td class='borderA'>data2</td>
<td class='borderA'>data2</td>
<td class='borderA'>data2</td>
<td class='borderA'>data2</td>
</tr>
<tr class="toggle">
<td class='border' colspan="4">2B</td>
</tr>
</tbody>
<tbody>
<tr>
<th class="pointer show" rowspan="3">DATA3</th>
<td>data3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
</tr>
<tr class="toggle">
<td colspan="4">3A</td>
</tr>
<tr>
<td>data3</td>
<td>data3</td>
<td>data3</td>
<td>data3</td>
</tr>
<tr class="toggle">
<td colspan="4">3B</td>
</tr>
<tr>
<td class='borderA'>data3</td>
<td class='borderA'>data3</td>
<td class='borderA'>data3</td>
<td class='borderA'>data3</td>
</tr>
<tr class="toggle">
<td class='border' colspan="4">3C</td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>