Freeze Multiple Rows & Multiple Columns of HTML Table - javascript

I have a HTML table which is generated by back-end (C#). I want to Fix the Header (2 Rows having Sale Type & Location) and First Two columns (Product Name & Description).
My table looks like the following:
The Header Row has a rowspan of 2 & the First Two columns(Under Description) also need to be freezed.
I have tried the following code:
<script>
$(document).ready(function() {
$('tbody').scroll(function(e) { //detect a scroll event on the tbody
/*
Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement
of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain it's relative position at the left of the table.
*/
$('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling
$('thead th:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first cell of the header
$('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody
$('.firstrow').css("left", $("tbody").scrollLeft());
});
});
</script>
<table id="ContentPlaceHolder1_tbl_Currentday" class="table table-responsive ReportTbl table-bordered">
<tr class="firstrow">
<th colspan="2" rowspan="2">Description</th><th colspan="12">Daily Sales</th><th colspan="11">MONTH TO DATE SALES</th><th colspan="3">FORECAST</th><th colspan="12">AVAILABLE STOCK</th><th colspan="10">IN TRANSIT QUANTITY</th>
</tr>
<tr class="firstrow">
<th>PROD QTY</th><th>KHI</th><th>HYD</th><th>LHR</th><th>MUL</th><th>ISD</th><th>SUK</th><th>FSD</th><th>PSH</th><th>GUJ</th><th>QTA</th><th class="totaltd">TOTAL</th><th>KHI</th><th>HYD</th><th>LHR</th><th>MUL</th><th>ISD</th><th>SUK</th><th>FSD</th><th>PSH</th><th>GUJ</th><th>QTA</th><th class="totaltd">TOTAL</th><th>MTD</th><th>TOTAL</th><th class="totaltd">ACH%</th><th>FAC</th><th>KHI</th><th>HYD</th><th>LHR</th><th>MUL</th><th>ISD</th><th>SUK</th><th>FSD</th><th>PSH</th><th>GUJ</th><th>QTA</th><th class="totaltd">TOTAL</th><th>HYD</th><th>LHR</th><th>MUL</th><th>ISD</th><th>SUK</th><th>FSD</th><th>PSH</th><th>GUJ</th><th>QTA</th><th class="totaltd">TOTAL</th>
</tr><tr>
<td rowspan="3" style="font-weight:bold;"> AAMRUS</td><td> AAMRUS CANDY - (BAG) - (35X60) - (670)</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="totaltd">0</td><td>3,572</td><td>202</td><td>926</td><td>36</td><td>414</td><td>1,417</td><td>562</td><td>0</td><td>1,310</td><td>0</td><td class="totaltd">8,439</td><td>9,065</td><td>16,997</td><td class="totaltd">93.09%</td><td>2,426</td><td>432</td><td>531</td><td>0</td><td>167</td><td>651</td><td>327</td><td>243</td><td>4</td><td>0</td><td>36</td><td class="totaltd">2,391</td><td>0</td><td>0</td><td>0</td><td>0</td><td>152</td><td>304</td><td>0</td><td>228</td><td>0</td><td class="totaltd">684</td>
</tr><tr>
<td> AAMRUS CANDY - (BOX) - (70X30) - (1032)</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td class="totaltd">0</td><td>1,126</td><td>1,462</td><td>1,270</td><td>333</td><td>737</td><td>1,576</td><td>813</td><td>575</td><td>218</td><td>60</td><td class="totaltd">8,170</td><td>9,068</td><td>17,003</td><td class="totaltd">90.1%</td><td>4,872</td><td>723</td><td>590</td><td>964</td><td>522</td><td>613</td><td>597</td><td>634</td><td>441</td><td>646</td><td>74</td><td class="totaltd">5,804</td><td>0</td><td>441</td><td>252</td><td>252</td><td>315</td><td>126</td><td>252</td><td>0</td><td>0</td><td class="totaltd">1,638</td>
</tr><tr class="totaltd">
<td>Total</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>4,698</td><td>1,664</td><td>2,196</td><td>369</td><td>1,151</td><td>2,993</td><td>1,375</td><td>575</td><td>1,528</td><td>60</td><td>16,609</td><td>18,133</td><td>34,000</td><td>91.6%</td><td>7,298</td><td>1,155</td><td>1,121</td><td>964</td><td>689</td><td>1,264</td><td>924</td><td>877</td><td>445</td><td>646</td><td>110</td><td>8,195</td><td>0</td><td>441</td><td>252</td><td>252</td><td>467</td><td>430</td><td>252</td><td>228</td><td>0</td><td>2,322</td>
</tr>
</table>
it only freezed the First Column, NOR first Two columns, NOR first two Rows.
How can I achieve this please Help
thanks

Target output
Spreadsheet example of freezed multiple rows and columns
Box structure
Make a <div> container that will be the scrollable component. Make sure the <div> container has a fixed width and height, and should be smaller than the actual content.
Let B, C, and D be the freezed rows and columns.
Let A be the actual table content.
Make the components A, B, C, and D using the <table> tag.
HTML
<div id="container">
<table id="a">
<thead>
<tr>
<th>A1</th>
<th>A2</th>
<th>A3</th>
<th>A4</th>
</tr>
<tr>
<th>B1</th>
<th>B2</th>
<th>B3</th>
<th>B4</th>
</tr>
</thead>
<tbody>
<tr>
<td>C1</td>
<td>C2</td>
<td>C3</td>
<td>C4</td>
</tr>
<tr>
<td>D1</td>
<td>D2</td>
<td>D3</td>
<td>D4</td>
</tr>
</tbody>
</table>
<table id="b">
<thead>
<tr>
<th>A1</th>
<th>A2</th>
<th>A3</th>
<th>A4</th>
</tr>
<tr>
<th>B1</th>
<th>B2</th>
<th>B3</th>
<th>B4</th>
</tr>
</thead>
</table>
<table id="c">
<thead>
<tr>
<th>A1</th>
<th>A2</th>
</tr>
<tr>
<th>B1</th>
<th>B2</th>
</tr>
</thead>
<tbody>
<tr>
<td>C1</td>
<td>C2</td>
</tr>
<tr>
<td>D1</td>
<td>D2</td>
</tr>
</tbody>
</table>
<table id="d">
<thead>
<tr>
<th>A1</th>
<th>A2</th>
</tr>
<tr>
<th>B1</th>
<th>B2</th>
</tr>
</thead>
</table>
</div>
CSS
#container{
width:90px;
max-height:90px;
overflow: auto;
position: relative;
}
#a{
position: relative;
z-index: 1
}
#b{
background: #fff;
position: absolute;
top: 0px;
left: 0px;
z-index: 2
}
#c{
background: #fff;
position: absolute;
top: 0px;
left: 0px;
z-index: 2
}
#d{
background: #fff;
position: absolute;
top: 0px;
left: 0px;
z-index: 3
}
JavaScript / jQuery
$('#container').scroll(function(event) {
var scrolledX = $(this).scrollLeft();
var scrolledY = $(this).scrollTop();
$(this).find('#c').css('left',scrolledX+'px');
$(this).find('#b').css('top',scrolledY+'px');
$(this).find('#d').css('left',scrolledX+'px');
$(this).find('#d').css('top',scrolledY+'px');
});

Related

Keep the height/width ratio of table

I have a simple table design, a square with 3x3 cells -think Rubik's cube. I want this table's width to always be 30% of the window and I don't want the height/width ratio change if the browser window is being resized. Also I want the inner 3x3 cells to be able to keep text and/or images without the symmetry being distorted. Is this possible with only css/javascript? I've tried sooooooooo many things but none has been working so far.
EDIT: I've added one of my many attempts to solve this below. The code works in Chrome when I try it in the broswer... but not here for some reason. However, it didn't solve my initial problem so I guess it's no problem.
function getTableWidth(){
var element = document.getElementById("table");
var intElemClientWidth = element.clientWidth;
document.getElementById("table").style.height=intElemClientWidth;
}
.cell{
height: 33%;
width: 33%;
<div onclick="getTableWidth()">Get 1:1 ratio</div>
<table id="table" width="30%" border="1">
<tbody>
<tr>
<td class="cell">1</td>
<td class="cell">2</td>
<td class="cell">3</td>
</tr>
<tr>
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
<tr>
<td class="cell"></td>
<td class="cell"></td>
<td class="cell"></td>
</tr>
</tbody>
</table>
I see what you mean. Let me provide a modified solution from here: html make <td> height proportional to the width
table {
width: 30%;
}
td {
border: 1px solid black;
position: relative;
}
td > div {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
td:before {
content: "";
display: block;
padding-top: 100%;
}
<table>
<tr>
<td><div>1</div></td>
<td><div>2</div></td>
<td><div>3</div></td>
</tr>
<tr>
<td><div>1</div></td>
<td><div>2</div></td>
<td><div>3</div></td>
</tr>
<tr>
<td><div>1</div></td>
<td><div>2</div></td>
<td><div>3</div></td>
</tr>
</table>
Yep it's possible just with HTML and some styling, you can easily control the table's width using percentages (Yes they are responsive):
<!DOCTYPE html>
<html>
<body>
<h2>Basic HTML Table</h2>
<table style="width:30%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
</html>
https://www.w3schools.com/html/tryit.asp?filename=tryhtml_table

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>

table with fixed first header and fixed column

I need to stress that this is about HORIZONTAL scrolling with THE FIRST COLUMN FIXED because most answers are giving me solutions to vertical scrolling.
Is it possible using pure css to have a table that scrolls horizontally but the first header and first column are fixed with the rest of the content scrollable?
For example if I had this table:
<table>
<thead>
<tr>
<th class="head1">Head 1</th>
<th class="head2">Head 2</th>
<th class="head2">Head 3</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col1">Col 1</td>
<td class="col2">Col 2</td>
<td class="col3">Col 3</td>
</tr>
</tbody>
</table>
The head1 and col1 would always be shown with the other columns scrollable.
This is what I was after. The example uses 2 tables that are floated left with an overflow applied to a div that wraps the right most table. Both tables are contained in a div with a fixed width.
<div class="table-container">
<div class="left">
<table>
...
</table>
</div>
<div class="right">
<table>
...
</table>
</div>
</div>
.table-container {
position: relative;
width: 600px;
height: 100%;
display: inline-block;
}
table {
float: left;
}
.right {
overflow: auto;
}
<table >
<tr>
<th>abc</th>
<th>xyz</th>
</tr>
<tr>
<td colspan="2">
<div style="height:50px; overflow:scroll;">
<table>
<tr>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
Please check it. It may be work.

How to apply css overflow property on specific content

I am applying overflow property for <form>, in form i used <legend>. Here the overflow is applying to whole form so if overflow needed scroll bar includes legend also. but I want the overflow has to be applying except legend tag. I mean in form along with legend i used table . I want overflow has to be apply only for table.
here is my fiddle,
http://jsfiddle.net/raghavendram040/z6jRX/1/
my html is,
<form>
<fieldset>
<legend> Menu</legend>
<table id="tab">
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
<tr>
<td>abc</td>
</tr>
</table>
</fieldset>
my css is,
form{
border: 1px #6A6A45 solid;
border-radius:6px;
height: 200px;
overflow: auto;
background-color:#efefef ;
margin-bottom: 17px;
}
to apply overflow I tried like this but it didnt worked
#tab{ overlow: auto }
How can I solve this can anyone help me in this.
Wrap your table in a div and apply overflow to that.
Have a fiddle!
HTML
<form>
<fieldset>
<legend> Menu</legend>
<div id="scroll">
<table id="tab">
<tr>
<td>abc</td>
</tr>
...
</table>
</div>
</fieldset>
</form>
CSS
#scroll {
overflow: scroll;
height: 140px;
}
You can wrap your table with a div element:
Working Demo
<div id="tab">
<table>
</table>
</div>

How to freeze thead section of the table

I have a table contains two header rows Demo.
<thead>
<tr>
<th colspan="4"><big>Variable Details</big></th>
</tr>
<tr>
<th>Variable Name</th>
<th>Starting Value</th>
<th>Default Value</th>
<th>Description</th>
</tr>
</thead>
I want to freeze the top two header rows (thead section of the table). Any thoughts.
After referring many web-site links, I am able to fix two header rows using pure CSS. Updated fix.
<div id="header-wrap"><b>Variable Details</b>
<table border=1 cellpadding=0 cellspacing=0 width=100% style="margin-top:5px">
<thead>
<tr>
<td background-color:#E0EBEB;"><b>Variable Name</b></td>
<td background-color:#E0EBEB;"><b>Starting Value</b></td>
<td background-color:#E0EBEB;"><b>Default Value</b></td>
<td background-color:#E0EBEB;"><b>Description</b></td>
</tr>
</thead>
</table>
</div>
CSS:
#header-wrap { position: fixed; width: 100%; height: 55px; top: 0; text-align:center; background-color:#F0F0F0; margin-top:0px; margin-bottom:40px;}
td {width:25% }
Change the CSS property position to "sticky" in order to get a sticky table head. See below.
CSS:
thead { position: sticky; top: 0px; z-index: 10; }
NOTE: You may have to adjust your z-index depending on your other CSS properties.

Categories

Resources