Reputation: 437
I have been piecing together a table format by using a range of templates that I have found online (am not a skilled programmer myself). I am trying to create a table that will highlight both the entire row and column when you hover over a specific table cell while it also includes a scrolling feature with the top row fixed. I have figured out how to highlight the row but am having difficulties with the column.
I have created a JSFiddle, which should reveal the problem: https://jsfiddle.net/n2p0zj6m/4/
I am using the code below to add the relevant classes to the table upon hover of a table cell. I am very sure that the error lies in this code somewhere but I can't figure out why this doesn't work.
(function ($) {
"use strict";
$('.column100').on('mouseover',function(){
var table1 = $(this).parent().parent().parent();
var table2 = $(this).parent().parent();
var verTable = $(table1).data('vertable')+"";
var column = $(this).data('column') + "";
$(table2).find("."+column).addClass('hov-column-'+ verTable);
$(table1).find(".row100.head ."+column).addClass('hov-column-head-'+ verTable);
});
$('.column100').on('mouseout',function(){
var table1 = $(this).parent().parent().parent();
var table2 = $(this).parent().parent();
var verTable = $(table1).data('vertable')+"";
var column = $(this).data('column') + "";
$(table2).find("."+column).removeClass('hov-column-'+ verTable);
$(table1).find(".row100.head ."+column).removeClass('hov-column-head-'+ verTable);
});
})(jQuery);
I will also include a snippet of the HTML structure below:
<div class="tbl-header">
<table data-vertable="ver1" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr class="row100 head">
<th class="column100 column1" data-column="column1">Code</th>
<th class="column100 column2" data-column="column2">Company</th>
<th class="column100 column3" data-column="column3">Price</th>
<th class="column100 column4" data-column="column4">Change</th>
<th class="column100 column5" data-column="column5">Change %</th>
</tr>
</thead>
</table>
</div>
<div class="tbl-content">
<table data-vertable="ver1" cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr class="row100">
<td class="column100 column1" data-column="column1">AAC</td>
<td class="column100 column2" data-column="column2">AUSTRALIAN COMPANY </td>
<td class="column100 column3" data-column="column3">$1.38</td>
<td class="column100 column4" data-column="column4">+2.01</td>
<td class="column100 column5" data-column="column5">-0.36%</td>
</tr>
Upvotes: 0
Views: 1243
Reputation: 866
One thing, is there's no need to separate the various levels of the table into different divs
- this creates issues, and will confuse any robots/accessibility technology. In my snippet below, I've merged it into a single table. Using thead
and tbody
instead.
Also, with the approach I use (collecting the index
of the cell - thus its column) there's no need for extra data-x
or classes
for tracking. And if your goal is for styling purposes, you should look into :nth-child()
to create alternating rows and the like.
$('tbody td').on('mouseover', function() { // Triggers when a table cell is hovered under a tbody
column = $(this).index(); // Find which column the cell belongs to (its index amongst its siblings)
$(this).parent().siblings().each(function() { // loop over all rows except current (the siblings)
$(this).children().eq(column).addClass('colHover'); // addClass to the cell in the same column
});
});
$('tbody td').on('mouseout', function() { // Triggers when leaving a table cell
$(this).parent().siblings().each(function() {
$(this).children().removeClass('colHover'); // removeClass from all children, of all siblings
});
});
table thead tr {
background-color: #AAA;
}
table td,
table th {
padding: .5em .75em;
}
table tr td:nth-child(n+2) {
text-align: center;
}
table tbody tr:hover,
table tbody tr td.colHover {
background-color: #FFDDFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tblFinance">
<table data-vertable="ver1" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<th>Code</th>
<th>Company</th>
<th>Price</th>
<th>Change</th>
<th>Change %</th>
</tr>
</thead>
<tbody>
<tr class="row100">
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr class="row101">
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr class="row102">
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr class="row103">
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
</tbody>
</table>
</div>
EDIT: I've built an extra function, which attaches an event to scrolling. Once the user has scrolled to (or past) the top of the table, the <tr>
inside the <thead>
becomes "sticky" - it applies position: fixed
, and adjusts the table to handle the missing row without bouncing the page around.
NOTE: This is NOT very scalable, in its current form. It will only really support a single "sticky" element, in the specific table.
$(document).ready(() => {
var tblObject = $('table#tblFinance');
var tblTop = tblObject.offset().top; // Find Table's offset from the top of the page
var tblSticky = false; // reduce redundant conditional spam
$(window).scroll(() => {
if (!tblSticky && $(document).scrollTop() >= tblTop) {
// If Sticky is OFF, and user scrolls to/below the table's top
tblObject.find('thead tr').css('position', 'fixed'); // Set Position: fixed
tblObject.css('padding-top', tblObject.find('thead tr').outerHeight() + 'px'); // Add padding to table, to account for <tr> being removed from the flow
tblSticky = true; // Enable Sticky
} else if (tblSticky && $(document).scrollTop() <= tblTop) {
// If Sticky is ON, and user scrolls to/above the table's top
tblObject.find('thead tr').css('position', 'static'); // Set Position: Static
tblObject.css('padding-top', '0'); // Remove padding; <tr> is back in the flow
tblSticky = false; //Disable Sticky
}
});
});
$('tbody td').on('mouseover', function() { // Triggers when a table cell is hovered under a tbody
column = $(this).index(); // Find which column the cell belongs to (its index amongst its siblings)
$(this).parent().siblings().each(function() { // loop over all rows except current (the siblings)
$(this).children().eq(column).addClass('colHover'); // addClass to the cell in the same column
});
});
$('tbody td').on('mouseout', function() { // Triggers when leaving a table cell
$(this).parent().siblings().each(function() {
$(this).children().removeClass('colHover'); // removeClass from all children, of all siblings
});
});
table {
text-align: center;
}
table thead tr {
top: 0;
background-color: #AAA;
}
table td,
table th {
padding: .5em .75em;
}
table td:first-child,
table th:first-child {
width: 80px;
}
table td:nth-child(2),
table th:nth-child(2) {
width: 300px;
}
table td:nth-child(n+3),
table th:nth-child(n+3) {
width: 100px;
}
table tbody tr:hover,
table tbody tr td.colHover {
background-color: #FFDDFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h1>Title</h1>
<p>Some content, to push the table down a bit.</p>
<table id="tblFinance" data-vertable="ver1" cellpadding="0" cellspacing="0" border="0">
<thead>
<tr>
<th>Code</th>
<th>Company</th>
<th>Price</th>
<th>Change</th>
<th>Change %</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAA</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>BBB</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>CCC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>DDD</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
<tr>
<td>AAC</td>
<td>AUSTRALIAN COMPANY </td>
<td>$1.38</td>
<td>+2.01</td>
<td>-0.36%</td>
</tr>
</tbody>
</table>
</div>
Upvotes: 2
Reputation: 551
If I understood correctly, I think your problem is in the CSS. Your columns are getting the right class hov-column-ver1
, but in the CSS you are only giving the green background to the elements under tbl-header
:
.tbl-header .hov-column-ver1 {
background-color: green;
}
You need to add the style for the elements under tbl-content
. Add this in your CSS block:
.tbl-content .hov-column-ver1 {
background-color: green;
}
Is this what you meant?
P.S. Please consider to review the closest() element in jQuery. Instead of using .parent().parent().parent()
you could use .closest("table")
. IMHO it is really useful in case the HTML structure changes as it will not affect your JS code. It is also more friendly to read :)
Upvotes: 1