Bootstrap Table - Searchable Treegrid - javascript

I am pretty new to Javascript and I am having troubles to implement a searchable method for the following treegrid.
Just by adding the method data-search="true" within the <table> variables doesn't seem to work as I expected. Only the parents can be searched, while the children are not found. Does this imply that I need to create a custom search function to return the children plus parent?

Seems like your estructure needs a little more order, I recommend you to create the full table with HTML and the Javascript function separatly:
For the html table I will give you an example like this one:
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
</table>
Then if you gonna add some CSS Style it could be something like this:
<style>
#myInput {
background-image: url('/css/searchicon.png'); /* Add a search icon to input */
background-position: 10px 12px; /* Position the search icon */
background-repeat: no-repeat; /* Do not repeat the icon image */
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 18px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 12px; /* Add padding */
}
#myTable tr {
/* Add a bottom border to all table rows */
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
/* Add a grey background color to the table header and on hover */
background-color: #f1f1f1;
}
</style>
And of course at the end of it you can add the Java script that is gonna do the job for you, in this case it will filter the first column, but you can change it and even make it search on all colums
<script>
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
I hope this actually help you! :)

Related

Abp framework js code doesn't work inside modal

.net mvc efcore, no angular, abp 5.3.1
Purpose: Dynamic search within a table.
Method: I create modal according to the tutorial (https://docs.abp.io/en/abp/latest/Tutorials/Part-3?UI=MVC&DB=EF). I add table, css and js codes into it. Myinput will filter the word entered in the textbox by searching in the 3rd column of the Mytables table. (https://www.w3schools.com/howto/howto_js_filter_table.asp)
Problem: There is no problem with tables and css, but js codes are not triggered in any way.
#page
#using xxx.Localization
#using xxx.xxx.Web.Pages.xxx
#using Microsoft.Extensions.Localization
#using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
#model xxxModalModel
#inject IStringLocalizer<xxxx> L
#{
Layout = null;
}
<style>
#myInput {
width: 100%; /* Full-width */
font-size: 10px; /* Increase font-size */
padding: 5px 5px 5px 5px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 5px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 10px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 5px; /* Add padding */
}
#myTable tr {
/* Add a bottom border to all table rows */
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
/* Add a grey background color to the table header and on hover */
background-color: #f1f1f1;
}
</style>
<form asp-page="/xxx/xxx">
<abp-modal>
<abp-modal-header title="#L["xxx"].Value"></abp-modal-header>
<abp-modal-body>
<abp-input asp-for="Id" />
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<abp-table responsive-md="true" small="true" striped-rows="true" id="myTable" border-style="Bordered">
<thead>
<tr>
<th scope="Column">#</th>
<th scope="Column">1</th>
<th >2</th>
<th >3</th>
<th >4</th>
<th >5</th>
<th >6</th>
</tr>
</thead>
<tbody>
#{
var sutun = 1;
for (var i = 0; i < Model.xxx.Count; i++)
{
if (#Model.xxx[i].IsSelected)
{
var x= Model.xxx[i];
<tr>
<th scope="Row">#sutun</th>
<td>#Model.xxx[i].1</td>
<td>#Model.xxx[i].2</td>
<td>#Model.xxx[i].3</td>
<td>#Model.xxx[i].4</td>
<td>#Model.xxx[i].5</td>
<td>#Model.xxx[i].6</td>
</tr>
sutun +=1;
}
}
}
</tbody>
</abp-table>
</abp-modal-body>
<abp-modal-footer></abp-modal-footer>
</abp-modal>
</form>
<script>
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.indexOf.toUpperCase(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>

How to filter exact phrase in table?

Can someone please help with this code;
<style>
#myInput {
background-image: url('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8iOHV-jsRl0FQ2hVomg1GUjdg4W63HoqXrREEp4m5KNpOVWRAJRxJD_SBXN-l2hlAc7rbL_LNpl145QhEjTUC54EHfJImTH-gKe-a2CtD8XFq9ZBUG4xJekQwHfIvIP4yaU_Zm-QX3HnvawVcXY82APg5QNY6rlcKX2Bx9b3wQ6v_f7zVuOF19Mn4/s1600/149852.png'); /* Add a search icon to input */
background-position: 10px 12px; /* Position the search icon */
background-repeat: no-repeat; /* Do not repeat the icon image */
width: 60%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
#myTable {
border-collapse: collapse; /* Collapse borders */
width: 100%; /* Full-width */
border: 1px solid #ddd; /* Add a grey border */
font-size: 18px; /* Increase font-size */
}
#myTable th, #myTable td {
text-align: left; /* Left-align text */
padding: 12px; /* Add padding */
}
</style>
<script>
const myFunction = () => {
const trs = document.querySelectorAll('#myTable tr:not(.header)')
const filter = document.querySelector('#myInput').value
const regex = new RegExp(filter, 'i')
const isFoundInTds = td => regex.test(td.innerHTML)
const isFound = childrenArr => childrenArr.some(isFoundInTds)
const setTrStyleDisplay = ({ style, children }) => {
style.display = isFound([
...children // <-- All columns
]) ? '' : 'none'
}
trs.forEach(setTrStyleDisplay)
}
</script>
I need it to show results with the exact phrases. For instance, if I type DR it should only show where DR is alone and not part of a sentence. Unfortunately, I can't explain it any better than this, but ask me questions and I'll try to provide an answer. Not a program.
Make your regular expression match start '^' and end '$' of a string.
const tds = document.querySelectorAll("table tbody td");
const highlightRows = (text) => {
var re = new RegExp('^' + text + '$', 'i');
tds.forEach(td => {
if (td.textContent.trim().match(re)) {
td.classList.add("selected");
td.closest("tr").classList.add("selected");
}
})
};
highlightRows("foo");
tr.selected td{
background-color: yellow;
}
tr.selected td.selected{
color: green;
}
<table>
<tbody>
<tr>
<td>1</td>
<td>foo bar</td>
<td>bar</td>
</tr>
<tr>
<td>2</td>
<td>foo</td>
<td>bar</td>
</tr>
<tr>
<td>3</td>
<td>foo</td>
<td>foo</td>
</tr>
</tbody>
</table>

Remove entire table when there is no input in searchbox?

I have been twisting my head around on this and I can't seem to fix it.
I have not coded much, but wanting to learn. However, I am trying to make a table in which when there is no input the entire table vanishes.
As of now I have managed to get it so that it starts as vanished, and that when information is inserted into the search box the non-relevant lines dissapear. However, when all text in the search box is removed the entire table is showing. I want the table to stay hidden when there is no text that matches.
Would love to get any feedback on what I am doing wrong here.
function performSearch() {
// Declare search string
var filter = searchBox.value.toUpperCase();
// Loop through first tbody's rows
for (var rowI = 0; rowI < trs.length; rowI++) {
// define the row's cells
var tds = trs[rowI].getElementsByTagName("td");
// hide the row
trs[rowI].style.display = "none";
// loop through row cells
for (var cellI = 0; cellI < tds.length; cellI++) {
// if there's a match
if (tds[cellI].innerHTML.toUpperCase().indexOf(filter) > -1)
{
// show the row
myTable.style.display = "table";
trs[rowI].style.display = "";
// skip to the next row
continue;
}
}
}
}
// declare elements
const searchBox = document.getElementById('searchBox');
const table = document.getElementById("myTable");
const trs = table.tBodies[0].getElementsByTagName("tr");
// add event listener to search box
searchBox.addEventListener('keyup', performSearch);
* {
box-sizing: border-box;
}
#searchBox {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 30%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
position: relative;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
}
#myTable {
border-collapse: collapse;
width: 80%;
border: 1px solid #ddd;
font-size: 18px;
position: relative;
left: 10%;
display: none;
}
#myTable th, #myTable td {
text-align: left;
padding: 12px;
}
#myTable tr {
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover {
background-color: #f1f1f1;
}
#Overskrift {
width: 100%;
text-align-last: center;
font-size: 40px;
}
<input class="form-control" type="text" id="searchBox" placeholder="Search ..." onkeyup="searchTableColumns()">
<table id="myTable">
<thead>
<tr class="header">
<th onclick="sortTable(0)" style="width:35%;">Fagnavn</th>
<th onclick="sortTable(1)" style="width:21%;">LK20</th>
<th onclick="sortTable(2)" style="width:21%;">LK06</th>
<th onclick="sortTable(3)" style="width:21%;">R94</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pika</td>
<td>Chu</td>
<td>Poke</td>
<td>Mon</td>
</tr>
<tr>
<td>Temporary</td>
<td>Text</td>
<td>Fields</td>
<td>Here</td>
</tr>
</tbody>
</table>
There is a simple solution for this. Just add a check to the end your performSearch function:
if (searchBox.value === ''){
table.style.display='none';
}
else {
table.style.display='table';
}
You can also check it here:
https://codepen.io/serazoltan/pen/dyZRprb

Why my event listener not behaving correctly, as my function do,, sharing the same functionality?

Why is my event listener not behaving correctly, as my function do, sharing the same functionality?
I need to hide the row in a table, based on the input in the search bar.
The below is the functionality I have tried.
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_filter_table
I want this to be implemented in Event listener, instead of function.
<!DOCTYPE html>
<html>
<head>
<title>Filter Table</title>
<style>
body{
font-family: 'Bebas Neue', cursive;
font-family: 'M PLUS 2', sans-serif;
}
*{
box-sizing: border-box;
}
input[type = "text"]{
border: 1px solid black;
width: 96%;
margin: 0 50px;
padding: 10px 35px 10px 35px;
font-size: 15px;
font-family: 'Bebas Neue', cursive;
font-family: 'M PLUS 2', sans-serif;
background-image: url('https://cdn2.iconfinder.com/data/icons/ios-7-icons/50/search-512.png');
background-repeat: no-repeat;
background-size: 30px;
background-position: 3px 6px;
}
#myTable{
width: 96%;
border: 1px solid rgb(197, 194, 194);
margin: 10px 50px;
border-collapse: collapse;
font-size: 20px;
}
#myTable td,th{
text-align: left;
padding: 20px;
}
tr{
border-bottom: 1px solid #ddd;
}
#myTable tr.header, #myTable tr:hover{
background-color: rgb(241, 241, 241);
}
</style>
</head>
<body>
<h2><b>My Customers</b></h2>
<input type="text" placeholder="Search for names.." onkeyup="myFunction()" id="myInput" >
<table id="myTable">
<tr class="header">
<th style="width: 60%;"><b>Name</b></th>
<th style="width: 40%;"><b>Country</b></th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Italy</td>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
</body>
<script>
// Function to filter the table, based on search
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
}
else{
tr[i].style.display = "none";
}
}
}
}
// Event Listener, to filter the table, based on search
// var input = document.getElementById('myInput');
// input.addEventListener('click', function(){
// var myTable = document.getElementById('myTable');
// var row = myTable.getElementsByTagName('tr');
// var value = input.value;
// var ex_val = value.toUpperCase();
// for(var i=1;i < row.length;i++){
// var content = row[i].getElementsByTagName('td')[0];
// var ex_con = content.textContent.toUpperCase();
// if ( ex_con.indexOf(ex_val) > -1){
// row[i].style.display = '';
// }
// else{
// row[i].style.display = 'none';
// }
// }
// })
</script>
</html>
I have figured out the error.
I was giving click / onkeypress in event listener, instead of "input".
Now, the rows are hiding and displaying correctly for the event listeners.
var input = document.getElementById("myInput");
input.addEventListener('input',function(){
var myTable = document.getElementById('myTable');
var row = myTable.getElementsByTagName("tr");
var filter = this.value.toUpperCase();
for(var i=1;i<row.length;i++){
var td = row[i].getElementsByTagName("td")[0];
var value = td.textContent;
if(value.toUpperCase().indexOf(filter) > -1){
row[i].style.display = '';
}
else{
row[i].style.display = "none";
}
}
})

Fixing HTML Table Header while scrolling

I have an HTML table which is quit long, and I need to fix the header from scrolling, I have found many and many of the plugins and tricks to do it, but none worked for me.
I guessed the reason nothing works for me is due to:
All of the solutions detach the header from the table
They use fixed width for every column to fit to keep the header on top of the content
my table is very responsive and stretches to get the full width possible (width=100%)
Do anybody have a suggestion ?
edit: thanks to ashley I updated my css technics
My hmlt table looks exactly like: http://jsfiddle.net/enPZP/4/
I think I came up with a rather nice solution to the problem, it's a little deeper than I wanted it to be but I'm really happy with the results.
The way it works is on document ready, clones the table header, sets the clone's size to the size of the table header and places it on top of the other header. On scroll if the top of the window is below the top of the table we set the clone's top to be at the top of the window. On resize we recalcuate the <th> sizes.
Note that I placed the <th>s into a <thead> separate from the .
jsFiddle
var tableBaseTop;
var originalHeader;
var floatingHeader;
$(document).ready(function () {
tableBaseTop = $('table th').offset().top;
originalHeader = $('thead');
floatingHeader = originalHeader.clone();
floatingHeader
.css('position', 'absolute')
.css('top', 0);
setFloatingHeaderSize();
$('table').prepend(floatingHeader);
$(window).scroll(function () {
var windowTop = $(window).scrollTop();
if (windowTop > tableBaseTop)
floatingHeader.css('top', windowTop - tableBaseTop);
else
floatingHeader.css('top', 0);
});
$(window).resize(setFloatingHeaderSize);
});
function setFloatingHeaderSize() {
var originalThs = originalHeader.find('th');
var floatingThs = floatingHeader.find('th');
for (var i = 0; i < originalThs.length; i++) {
floatingThs.eq(i)
.css('width', originalThs.eq(i).width())
.css('height', originalThs.eq(i).height());
}
}
Firefox header width problem
I managed to fix the problem but I couldn't figure out how to do it using jQuery's helpers. The problem was that jQuery was giving me integer sizes when the actual width/height were decimals and I needed them as floats. Here is the section of code that I changed with a working fiddle.
jsFiddle
function setFloatingHeaderSize() {
var originalThs = originalHeader.find('th');
var floatingThs = floatingHeader.find('th');
for (var i = 0; i < originalThs.length; i++) {
var padding =
parseFloat(window.getComputedStyle(this.originalThs[i], null).getPropertyValue('padding-left').replace('px', ''), 10) +
parseFloat(window.getComputedStyle(this.originalThs[i], null).getPropertyValue('padding-right').replace('px', ''), 10);
floatingThs.eq(i)
.css('width', this.originalThs[i].offsetWidth - padding)
.css('height', this.originalThs[i].offsetHeight - padding);
}
}
Update: I made this in to a reusable library shortly after coming up with the solution, view on GitHub.
I have modified your fiddle with this it fixes the Header to the top of the grid. but it does have a drawback of fixing the tile to the top left.
hopefully this will help you on your way to a full answer.
table {
width: 100%;
border-collapse: collapse;
position: relative;
}
div.scoll {
overflow: scroll;
height: 300px;
}
.center {
text-align: center;
}
thead {
position: static;
width: 100%;
}
thead tr {
position: fixed;
}
and changed you html to look something like
<div class="scoll">
<table>
<thead>
<tr>
<th>Code</th>
<th>Rank</th>
<th>Code</th>
<th>Icon</th>
<th>Message Text</th>
<th>Progress</th>
<th>Current</th>
<th>X</th>
<th>Y</th>
<th>Z</th>
<th>W</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="12"> </td>
</tr>
<tr class="data-row" id="19">
<td class="center">DDD</td>
<!-- 4 alpha numeric -->
<td class="center">111</td>
<!-- 3 digits -->
<td class="center">222</td>
<!-- 3 digits -->
<td class="center">
<img width="20" height="20" src="http://cdn1.iconfinder.com/data/icons/CrystalClear/128x128/apps/ark2.png">
<!-- icon -->
</td>
<td>Lorem ipsum</td>
<!-- text may be long -->
<td class="center">333</td>
<!-- 3 alpha numeric -->
<td class="center">444</td>
<!-- 3 alpha numeric -->
<td class="center">555</td>
<!-- 3 alpha numeric -->
<td class="center">666</td>
<!-- 3 alpha numeric -->
<td class="center">777</td>
<!-- 3 alpha numeric -->
<td class="center">888</td>
<!-- 3 alpha numeric -->
<td class="center">999</td>
<!-- 3 alpha numeric -->
</tr>
</tbody>
</table>
</div>
Seperate head row to another table and add some jquery code:
html:
<table class="headtable">
<tr>
<td>name</td>
<td>value</td>
<td>action</td>
</tr>
</table>
<div class="scrolltable">
<table class="valuetable">
<tr>
<td>hay 1</td>
<td>1</td>
<td>edit</td>
</tr>
<tr>
<td>hay 1</td>
<td>1</td>
<td>edit</td>
</tr>
<tr>
<td>hay 1</td>
<td>1</td>
<td>edit</td>
</tr>
<tr>
<td>hay 1</td>
<td>1</td>
<td>edit</td>
</tr>
</table>
</div>
js code:
$('.headtable tr').children().each(function(index)
{
$(this).width($('.valuetable tr:first td').eq(index).width());
});
style if need:
.scrolltable{height:500px; overflow:auto;}
if you want it auto resize (responsitive):
$(window).resize(function(){
$('.headtable tr').children().each(function(index)
{
$(this).width($('.valuetable tr:first td').eq(index).width());
});
});
If fixed-height column headers are acceptable, then this problem can be solved with pure CSS.
Here's an example that is configured with a fluid table width and auto column widths, just like the OP's table: jsFiddle
Note that the vertical scrollbar only appears when necessary in that example, so you may have to resize the frame to see it.
The code below is the same as the fiddle, but with a fixed table height. The scrollbar always shows in that configuration as long as there are enough rows to exceed the specified height:
HTML
<div class="scrollingtable">
<div>
<div>
<table>
<caption>Top Caption</caption>
<thead>
<tr>
<th><div label="Column 1"/></th>
<th><div label="Column 2"/></th>
<th><div label="Column 3"/></th>
<th>
<!--more versatile way of doing column label; requires 2 identical copies of label-->
<div><div>Column 4</div><div>Column 4</div></div>
</th>
<th class="scrollbarhead"/> <!--ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW-->
</tr>
</thead>
<tbody>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
<tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
</tbody>
</table>
</div>
Faux bottom caption
</div>
</div>
CSS
<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
<style>
/*the following html and body rule sets are required only if using a % width or height*/
html {
width: 100%;
height: 100%;
}
body {
box-sizing: border-box;
width: 100%;
height: 100%;
margin: 0;
padding: 0 20px 0 20px;
text-align: center;
}
.scrollingtable {
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
overflow: hidden;
width: auto; /*if you want a fixed width, set it here, else set to auto*/
min-width: /*0*/100%; /*if you want a % width, set it here, else set to 0*/
height: /*188px*/100%; /*set table height here; can be fixed value or %*/
min-height: /*0*/104px; /*if using % height, make this large enough to fit scrollbar arrows + caption + thead*/
font-family: Verdana, Tahoma, sans-serif;
font-size: 16px;
line-height: 20px;
padding: 20px 0 20px 0; /*need enough padding to make room for caption*/
text-align: left;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
position: relative;
border-top: 1px solid black;
height: 100%;
padding-top: 20px; /*this determines column header height*/
}
.scrollingtable > div:before {
top: 0;
background: cornflowerblue; /*header row background color*/
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
content: "";
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
left: 0;
}
.scrollingtable > div > div {
min-height: /*0*/43px; /*if using % height, make this large enough to fit scrollbar arrows*/
max-height: 100%;
overflow: /*scroll*/auto; /*set to auto if using fixed or % width; else scroll*/
overflow-x: hidden;
border: 1px solid black; /*border around table body*/
}
.scrollingtable > div > div:after {background: white;} /*match page background color*/
.scrollingtable > div > div > table {
width: 100%;
border-spacing: 0;
margin-top: -20px; /*inverse of column header height*/
margin-right: 17px; /*uncomment if using % width*/
}
.scrollingtable > div > div > table > caption {
position: absolute;
top: -20px; /*inverse of caption height*/
margin-top: -1px; /*inverse of border-width*/
width: 100%;
font-weight: bold;
text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
vertical-align: bottom;
white-space: nowrap;
text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
display: inline-block;
padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 20px; /*match column header height*/
border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
position: absolute;
top: 0;
white-space: pre-wrap;
color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
content: "";
display: block;
min-height: 20px; /*match column header height*/
padding-top: 1px;
border-left: 1px solid black; /*borders between header cells*/
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
position: absolute;
width: 100px;
top: -1px; /*inverse border-width*/
background: white; /*match page background color*/
}
.scrollingtable > div > div > table > tbody > tr:after {
content: "";
display: table-cell;
position: relative;
padding: 0;
border-top: 1px solid black;
top: -1px; /*inverse of border width*/
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
border-bottom: 1px solid black;
padding: 0 6px 0 6px;
height: 20px; /*match column header height*/
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /*alternate row color*/
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /*borders between body cells*/
</style>
The background colors will have to be changed and the borders removed for it to look exactly like the OP's table. Instructions for making those types of changes can be found in the CSS comments.
Check my answer here for an alternate configuration, and check d-Pixie's answer in the same post for an explanation of the basic technique used to freeze the header row.

Categories