Fixing HTML Table Header while scrolling - javascript

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.

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>

Css failed to set green color on hover on the first row, while it's working on the last row after adding my Javascript code

My Css code was working just fine, until I added my Javascript code, which works as a sorter for the table itself, the Javascript code seems to change my Css code (the green color when on hover on the first row and the last one) for the first row < tr > but not the last one.
In the code I used Css and Javascript comments to explain the origin of the problem and what could be fixed, I think it originates from the Javascript code. All I want is for the first row to be green when clicked on or hovered on and also the last one.
$(document).ready(function() {
$('th').each(function(col) {
$(this).hover(
function() {
$(this).addClass('focus');
},
function() {
$(this).removeClass('focus');
}
);
$(this).click(function() {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $('table').find('tbody >tr:has(td)').get();
arrData.sort(function(a, b) {
var val1 = $(a).children('td').eq(col).text().toUpperCase();
var val2 = $(b).children('td').eq(col).text().toUpperCase();
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else
return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
});
$.each(arrData, function(index, row) {
$('tbody').append(row);
});
});
});
});
* {
margin: 0;
padding: 0;
z-index: 0;
list-style: none;
box-sizing: border-box;
text-align: center: vertical-align: center;
transition: .4s;
}
body {
color: white;
margin: 0;
width: 100%;
background: #212121;
text-align: center: vertical-align: center;
height: 120em;
}
/* CSS OF TABLE */
table {
font-family: Arial, Helvetica, sans-serif;
width: 100%;
position: absolute;
top: 10em;
border-collapse: collapse;
text-align: center: z-index: 1000;
font-size: 0.8125em;
}
table td,
table th {
border: solid;
border-width: 0 .001em .001em .001em;
border-color: black;
padding: .1em .3em .1em .3em;
text-align: center;
}
table tr:nth-child(odd) {
background-color: #f6f6f8;
}
table tr:nth-child(even) {
background-color: #CACCD6;
}
/* THIS IS WHAT DOESN'T WORK */
table tr:first-child {
background-color: #0CDC80;
color: white;
}
/* AS WELL AS THIS */
table tr:last-child {
background-color: #DA0F3A;
color: white;
}
table tr:hover {
background-color: #676B77;
color: white;
font-weight: 900;
}
table th {
padding: .5em;
text-align: center;
background-color: #6C06D8;
color: #f6f6f8;
text-transform: uppercase;
font-weight: 900;
}
#supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
table tr:nth-child(odd) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .1);
}
table tr:nth-child(even) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .2);
}
/* THIS IS EXACTLY WHAT I NEED */
table tr:first-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(12, 220, 128, .6);
}
/* THIS IS ALREADY WORKING NO IDEA WHY */
table tr:last-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(218, 15, 58, .6);
}
table tr:hover {
background-color: rgba(0, 0, 0, .01);
font-weight: 900;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>HOMETOWN</th>
<th>SOCIALS</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td>$520</td>
<td>easy/medium</td>
<td>okay</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
</table>
It looks as though the javascript isn't affecting it (but I'll check this).
On a table the first row is the one containing the headings (i.e. the th tags). The css rule that's styling the th elements is overriding the table tr:first-child:hover rule because the th elements appear on top of the tr element. If you remove the table th rule, the change of colour on the top row works. If you want the row that has $520 in the first column to change colour on hover then use the nth-child(2) pseudo class.
The rules tagged 'THIS IS WHAT DOESN'T WORK' and 'AS WELL AS THIS' don't work because the nth-child(odd) and nth-child(even) rules appear after these two rules and in css the last rule 'wins'. If you move these rules after the nth-child(odd) and (even) rules then it works.
It's worthwhile reading up on specificity. There's a good article here and a good video on it by Kevin Powell here (Kevin's channel is brilliant btw and well worth a follow). But yeah, specificity is one of those things that drives developers mad (especially newbies)!
Hope this helps
P.S. there were a number of typos in your CSS too such as missing semicolons etc.
P.P.S my changes below:
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="jquery-3.6.0.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
z-index: 0;
list-style: none;
box-sizing: border-box;
text-align: center;
vertical-align: center;
transition: .4s;
}
body {
color: white;
margin: 0;
width: 100%;
background: #212121;
text-align: center;
vertical-align: center;
height: 120em;
}
/* CSS OF TABLE */
table {
font-family: Arial, Helvetica, sans-serif;
width: 100%;
position: absolute;
top: 10em;
border-collapse: collapse;
text-align: center;
z-index: 1000;
font-size: 0.8125em;
}
table td,
table th {
border: solid;
border-width: 0 .001em .001em .001em;
border-color: black;
padding: .1em .3em .1em .3em;
text-align: center;
}
table tr:nth-child(odd) {
background-color: #f6f6f8;
}
table tr:nth-child(even) {
background-color: #CACCD6;
}
table tr:hover {
background-color: #676B77;
color: white;
font-weight: 900;
}
table th {
padding: .5em;
text-align: center;
background-color: #6C06D8;
color: #f6f6f8;
text-transform: uppercase;
font-weight: 900;
}
#supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
table tr:nth-child(odd) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .1);
}
table tr:nth-child(even) {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, .2);
}
/* THIS IS WHAT DOESN'T WORK - moved this to below table:tr:nth*/
table tr:nth-child(2) {
background-color: #0CDC80;
color: white;
}
/* AS WELL AS THIS - moved this to below table:tr:nth */
table tr:last-child {
background-color: #DA0F3A;
color: white;
}
table tr:hover {
background-color: rgba(0, 0, 0, .01);
font-weight: 900;
}
/* THIS IS EXACTLY WHAT I NEED - changed this from first-child to nth-child(2)*/
table tr:nth-child(2):hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(12, 220, 128, .6);
}
/* THIS IS ALREADY WORKING NO IDEA WHY */
table tr:last-child:hover {
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(218, 15, 58, .6);
}
}
</style>
</head>
<body>
<table>
<tr>
<th>HOMETOWN</th>
<th>SOCIALS</th>
<th>DESCRIPTION</th>
</tr>
<tr>
<td>$520</td>
<td>easy/medium</td>
<td>okay</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
<tr>
<td>WORTH</td>
<td>DIFFICULTY</td>
<td>NAME</td>
</tr>
</table>
<script>
/* POSSIBLE ORIGIN OF PROBLEM */
$(document).ready(function () {
$('th').each(function (col) {
$(this).hover(
function () {
$(this).addClass('focus');
},
function () {
$(this).removeClass('focus');
}
);
$(this).click(function () {
if ($(this).is('.asc')) {
$(this).removeClass('asc');
$(this).addClass('desc selected');
sortOrder = -1;
} else {
$(this).addClass('asc selected');
$(this).removeClass('desc');
sortOrder = 1;
}
$(this).siblings().removeClass('asc selected');
$(this).siblings().removeClass('desc selected');
var arrData = $('table').find('tbody >tr:has(td)').get();
arrData.sort(function (a, b) {
var val1 = $(a).children('td').eq(col).text().toUpperCase();
var val2 = $(b).children('td').eq(col).text().toUpperCase();
if ($.isNumeric(val1) && $.isNumeric(val2))
return sortOrder == 1 ? val1 - val2 : val2 - val1;
else
return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
});
$.each(arrData, function (index, row) {
$('tbody').append(row);
});
});
});
});
</script>
</body>
</html>

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

Bootstrap Table - Searchable Treegrid

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! :)

How to Optimize big Data Tables VueJS

I have this table that I'm using to intelligently render over 4000 records, but I want to know how to do it in a way that there is no lag whatsoever. I did a performance recording using so I could see how the memory was being used and I ended up with this.
This is actually much more optimized than what I had before and I'm achieving this by conditionally rendering all but the first td in each row in order to maintain height for scrolling, but also to reduce the amount of nodes that are being iterated over. Is there any way that I can optimize this further?
Here is my Vue Template
<template>
<div class="table-container" >
<div class="table-header" ref="tableHead">
<table class="data-table" border="0">
<thead>
<tr>
<th
v-for="(head, index) in contents.order"
:key="index"
class="col"
:class="contents.stickyCols.indexOf(head) === 0 ? 'sticky-left' : contents.stickyCols.indexOf(head) === 1 ? 'sticky-right' : ''"> {{ head }}
</th>
</tr>
</thead>
</table>
</div>
<div class="table-body" ref="tableBody" #scroll="changeScrollVal" :style="'height: ' + height + ';'">
<table id="bodytable" width="100%" cellpadding="5" cellspacing="5">
<tbody>
<tr
v-for="(row, idx) in theData"
:key="idx">
<td
:class="contents.stickyCols.indexOf(key) === 0 ? 'sticky-left' : contents.stickyCols.indexOf(key) === 1 ? 'sticky-right' : ''"
:style="contents.colorCols.indexOf(key) > -1 ? 'color:' + contents.colorRefs[row[contents.colorRefs.label]] : '' "
class="body-cell col"
v-for="(key, index) in contents.order"
v-if="idx >= (scrollBottom / 6 - 100 < 0 ? 0 : scrollBottom / 6 - 100) && idx <= scrollBottom - 1 || key === contents.order[0]"
:key="index"
>{{ row[key] }}
</td>
</tr>
</tbody>
<!-- > {{ row[key] }} -->
</table>
</div>
</div>
<script>
export default {
props: ['contents', 'dashData', 'height'],
data () {
return {
theData: [],
scrollBottom: 100
}
},
methods: {
changeScrollVal (e) {
this.$refs.tableHead.scrollLeft = e.target.scrollLeft
this.scrollBottom = Math.floor(this.$refs.tableBody.scrollTop / 9 < 100 ? 100 : this.$refs.tableBody.scrollTop / 9 > this.dashData.length - 1 ? this.dashData.length - 1 : this.$refs.tableBody.scrollTop / 9)
this.theData = this.dashData.slice(0, this.scrollBottom)
}
},
mounted () {
this.theData = this.dashData// .slice(0, 17)
}
}
</script>
<style lang="scss">
table
{
border-collapse: collapse;
}
td, th {
border-bottom: 1px solid rgba(0,0,0,0.2);
margin-bottom: 2px;
}
.sticky-right {
position: sticky;
background: white;
right: 0;
padding-left: 20px!important;
}
.sticky-left {
position: sticky;
background: white;
left: 0;
}
.outer-container
{
background-color: #ccc;
position: absolute;
top:0;
left: 0;
right: 300px;
bottom: 40px;
}
.inner-container
{
height: 100%;
overflow: hidden;
}
.table-header
{
position: relative;
&::-webkit-scrollbar {
display: none;
}
}
.table-body
{
overflow: scroll;
display:inline-block;
width: 79vw;
}
.table-header {
overflow: scroll;
width: 79vw;
}
th
{
background-color: white;
text-align: left;
height: 40px;
}
.body-cell
{
text-align: left;
color: rgba(0,0,0,0.6);
padding-top: 10px;
padding-bottom: 10px;
}
.col
{
width:120px;
min-width: 265px;
max-width: 265px;
padding-left: 0px;
padding-right: 0px;
font-weight: 500;
// background-color: white;
}
</style>
Thanks!

Categories