Collapse HTML table rows by default - javascript

I'm using slight modification from this answer to make header rows collapsible in an HTML table.
I want to modify the JS snippet so that rows are collapsed rather than expanded by default (on page load/document ready). How can I do this?
Basically what I'm trying to achieve is for:
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100, function(){
to be run once at page load/refresh, in addition to when header rows are clicked and toggled.
I know that I'll need to change the two tags two <span>+</span> in HTML, but am stuck on how to trigger this behavior on page load.
Javascript:
$(document).ready(function(){
$('tr.header').click(function(){
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100, function(){
});
});
});
HTML:
<table border="0">
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</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>
CSS:
table, tr, td, th
{
border: 1px solid black;
border-collapse:collapse;
}
tr.header
{
cursor:pointer;
}
JSFiddle: https://jsfiddle.net/mkb39x0u/

Seems like you'd just do this in document.ready:
$('tr:not(.header)').hide();
Demo
Also, I'd probably toggle visibility of your plus and minus characters with a class on the row and CSS rather than cluttering up your script with that.

I just update your code with few JS changes, I hope it'll help you out. Thanks
Add below JS code before your click method
$('tr.header').nextUntil('tr.header').slideToggle(100);
$(document).ready(function(){
$('tr.header').nextUntil('tr.header').slideToggle(100);
$('tr.header').click(function(){
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100, function(){
});
});
});
table, tr, td, th {
border: 1px solid black;
border-collapse:collapse;
}
tr.header {
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="0">
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</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>
Another way you can achieve this functionality by using CSS
$(document).ready(function(){
$('tr.header').click(function(){
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100, function(){
});
});
});
table {
border-collapse: collapse;
}
tr {
border: 1px solid #000;
display: none;
}
td + td {
border-left: 1px solid #000;
}
tr + tr {
border-top: 0;
}
tr.header {
cursor: pointer;
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="0">
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr class="header">
<th colspan="2">Header <span>-</span></th>
</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>

Related

Creating a Collapsible table in JSP

JSP Code:
<c:forEach var="map" items="${map}">
<tr>
<td>
<table border="1">
<tr class="header expand">
<th>${map.key.id}</th><th>${map.key.name}</th><th>${map.key.status}<span class="sign"></span></th>
</tr>
</table>
</td>
<td>
<table border="1">
<tr>
<th>REQUEST_ID</th>
<th>LOGIN_USER</th>
<th>PRICE</th>
<th>STATUS</th>
</tr>
<c:forEach var="item" items="${map.value}">
<tr>
<td>${item.REQUEST_ID}</td><td>${item.LOGIN_USER}</td><td>${item.PRICE}</td><td>${item.STATUS}</td>
</tr>
</c:forEach>
</table>
</td>
</tr>
</c:forEach>
Collapsible Table Code:
<style type="text/css">
table, tr, td, th
{
border: 1px solid black;
border-collapse:collapse;
}
tr.header
{
cursor:pointer;
}
.header .sign:after{
content:"+";
display:inline-block;
}
.header.expand .sign:after{
content:"-";
}
</style>
<body>
<table border="0">
<tr class="header expand">
<th colspan="2">Header <span class="sign"></span></th>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
</tr>
</table>
<script type="text/javascript">
$('.header').click(function(){
$(this).toggleClass('expand').nextUntil('tr.header').slideToggle(100);
});
</script>
</body>
I have a map which is being retrieved in JSP. It has object as key and arraylist as values.The arraylist consists of rows as objects.For a particular key which has unique reqid,it has all rows specific to the reqid as objects in the arraylist. I want to retrieve it in JSP. It must be collapsible table in such a way that key is my header and values i.e rows related to reqid must be present under that header.I have independent JavaScript code to implement it.I tried adding up in JSP but there is no outcome on browser.I need help in designing collapsible table in JSP code.
Expected Output:
123 A 1 ///Table header
123 A 5 2
123 A 10 3
//N no of rows
456 B 2 ///Table header
456 B 20 3
456 B 25 2
//N no of rows
Your jquery code is working but structure of your table is wrong .There are many invalid elements in it. That's the reason jquery is not able to find correct element to expand or collapse.
Some of the changes you need to make in your table structure :
<table>
<c:forEach var="map" items="${map}">
<!--no need to have new tr td here that just add extra row to your table-->
<tr class="header expand">
<th>${map.key.id}</th>
<th>${map.key.name}</th>
<th>${map.key.status}</th>
<th><span class="sign"></span></th>
</tr>
<!--no need to have different table-->
<tr>
<th>REQUEST_ID</th>
<th>LOGIN_USER</th>
<th>PRICE</th>
<th>STATUS</th>
</tr>
<c:forEach var="item" items="${map.value}">
<tr>
<td>${item.REQUEST_ID}</td>
<td>${item.LOGIN_USER}</td>
<td>${item.PRICE}</td>
<td>${item.STATUS}</td>
</tr>
</c:forEach>
</c:forEach>
</table>
Here is the demo code for above table structure:
$('.header').click(function() {
$(this).toggleClass('expand').nextUntil('tr.header').slideToggle(100);
});
table,
tr,
td,
th {
border: 1px solid black;
border-collapse: collapse;
}
tr.header {
cursor: pointer;
color: blue;
}
.header .sign:after {
content: "-";
display: inline-block;
}
.header.expand .sign:after {
content: "+";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr class="header expand">
<th>${map.key.id}</th>
<th>${map.key.name}</th>
<th>${map.key.status}</th>
<th><span class="sign"></span></th>
</tr>
<tr style="display:none" >
<th>REQUEST_ID</th>
<th>LOGIN_USER</th>
<th>PRICE</th>
<th>STATUS</th>
</tr>
<tr style="display:none">
<td>${item.REQUEST_ID}</td>
<td>${item.LOGIN_USER}</td>
<td>${item.PRICE}</td>
<td>${item.STATUS}</td>
</tr>
<tr class="header expand">
<th>${map.key.id}</th>
<th>${map.key.name}</th>
<th>${map.key.status}</th>
<th><span class="sign"></span></th>
</tr>
<tr style="display:none">
<th>REQUEST_ID</th>
<th>LOGIN_USER</th>
<th>PRICE</th>
<th>STATUS</th>
</tr>
<tr style="display:none">
<td>${item.REQUEST_ID}</td>
<td>${item.LOGIN_USER}</td>
<td>${item.PRICE}</td>
<td>${item.STATUS}</td>
</tr>
</table>

How to hide element correctly in html tables

I would like to behind row2by default and by clicking tables,it will show itself.
When I try my work like below,row2 is behind. but the shape of tables distorted.
I would like to align tables and behind row2 by deafault.
How can I fix it ?
Why this table distorted?
Thanks
$(function() {
$("table").click(function() {
$("table tr:eq(1)").toggleClass('show');
});
});
td {
padding:5px;
border:solid black 1px;}
table{
border-collapse:collapse;
border:solid black 1px;
cursor:pointer}
tr:nth-child(2):not([class]) {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th rowspan="2">header</th>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th rowspan="2">header</th>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
If you want to toggle the row, I suggest you have a concept of "hide", rather than "show".
Also, get rid of the second row header. Not sure why you need it, if you are spanning 2 rows.
$(() => {
$('table').click(function(e) {
$(this).find('tr:eq(1)').toggleClass('hide');
});
});
table, th, td {
border: solid black 1px;
}
table {
border-collapse: collapse;
}
th, td {
padding: 0.25em;
}
th {
cursor: pointer
}
.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<thead></thead>
<tbody>
<tr>
<th rowspan="2">Header</th>
<td>01</td>
<td>02</td>
<td>03</td>
<td>04</td>
<td>05</td>
</tr>
<tr class="hide">
<td>06</td>
<td>07</td>
<td>08</td>
<td>09</td>
<td>10</td>
</tr>
</tbody>
</table>

Hide tbody if number of shown tr is smaller than n

I have a table who looks like following
<table>
<tbody>
<tbody class="green">
<tr>
<td>Data</td>
</tr>
</tbody>
<tbody class="blue">
<tr>
<td>Data</td>
</tr>
</tbody>
</tbody>
</table>
Is it possible, using jquery, to hide each tbody from the table if the number of the tr inside the tbody is lower than 2? I tiried this but it didin't worked. All the tr in the table got hidden.
$('.table tbody').each(function(){
if($(this).not("tr:hidden").length <2)
{
$(this).parent().find("tbody").hide();
}
});
You can use find() on this object to find the length of all tr
$(this).find("tr").length
Then you can use this to target the specific tbody element to hide.
Please Note: nested tbody (tbody inside tbody) is not valid.
Demo:
$('table tbody').each(function(){
if($(this).find("tr").length < 2){
$(this).hide();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody class="green">
<tr>
<td>First tbody Data1</td>
</tr>
</tbody>
<tbody class="blue">
<tr>
<td>Second tbody Data1</td>
</tr>
<tr>
<td>Second tbody Data2</td>
</tr>
</tbody>
</table>
You can do this with vanilla JS quite easily, just grab all the tbodys and check their children's length for the amount you want and then set display to non if it doesn't meet that threshold.
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style
const tbodys = document.querySelectorAll('tbody')
Array.from(tbodys).forEach(tbody => {
const { children } = tbody;
const threshold = children.length < 2;
tbody.style.display = threshold ? 'none' : '';
})
.blue {background-color: blue}
.green {background-color: green}
<table>
<tbody>
<tbody class="green">
<tr>
<td>Data</td>
</tr>
</tbody>
<tbody class="blue">
<tr>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
</tr>
</tbody>
</tbody>
</table>
But if you want to just Jquery
$('table tbody').each(function() {
if (this.children.length < 2) $(this).hide();
});
.blue {
background-color: blue
}
.green {
background-color: green
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tbody class="green">
<tr>
<td>Data</td>
</tr>
</tbody>
<tbody class="blue">
<tr>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
</tr>
</tbody>
</tbody>
</table>

Table with horizontal and vertical scroll with fixed header

I do have a table with horizontal and vertical scroll with a fixed header with elements taking as much as space it needs. I am working with React. It would be awesome if there is a react based solution too if CSS alone cannot solve it.
Note:
I did try other solutions here but it is not what I'm looking for
It would be better if td can have min-width set on them too
The header shows menu when it is clicked for sorting and filtering
There's a simple CSS solution to fix rows(headers) and columns in a table.
th {
position: sticky:
top: 0;
}
The above snippet will fix the header to the top. Then it's just a matter of adding a simple overflow to the parent container of the table. You can find a simple example below -
.table-container {
overflow: auto;
max-height: 160px;
border: 1px solid red;
}
th {
position: sticky;
top: 0;
background: white;
}
<div class="table-container">
<table>
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
<th>Head 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</tbody>
</table>
</div>

Moving (highlighting) the last row in an HTML table using jQuery

I need your help.
How can the existing jQuery code below be modified such that, at the click of a button, I would be able to move to the last row in the html table and select (highlight) it? My way of thought was that it would be possible to get the row count, then using the row count, move the selection to the last row. I guess I was wrong because its not working :(
Im jQuery friendly please.
Here is the markup:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style type="text/css">
.highlight {
background-color: rgb(255,0,0);
}
</style>
<script type="text/javascript">
window.onload = function() {
var rowCount = $('#data >tbody >tr').length;
var $tbody = $("#data tbody").on('click', 'tr', function() {
highlight($(this));
});
$('#goto_prev').click(function() {
var $prev = $tbody.find('.highlight').prev();
highlight($prev);
});
$('#goto_next').click(function() {
var $next = $tbody.find('.highlight').next();
highlight($next);
});
$('#goto_last').click(function() {
highlight(rowCount);
});
function highlight($row) {
if ($row.length) {
$tbody.children().removeClass("highlight");
$row.addClass('highlight');
$("#rownum").val($row[0].rowIndex);
}
}
}
</script>
</head>
<body>
<table id="data" border="1" cellspacing="1" cellpadding="1">
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
<th>header4</th>
<th>header5</th>
</tr>
</thead>
<tbody>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
<tr>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
</tbody>
</table>
Row Number:
<br>
<input type="text" id="rownum" readonly>
<input type="button" id="goto_prev" value="prev">
<input type="button" id="goto_next" value="next">
<input type="button" id="goto_last" value="last">
</body>
</html>
Your highlight function takes a Jquery object as parameter, it won't work by sending index of row. You can solve it using this:
$('#goto_last').click(function() {
highlight($("#data tr").eq(rowCount));
});

Categories

Resources