How to style all elements that share data attribute values? - html

I have a generic table on my hands to which I've added a data attribute index with a value:
<table>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>
Would it be possible to influence all elements who share the same value of data-index through css?
Something like - CSS:
td[data-index.value]:hover{
background-color: red;
}
What I want to accomplish is that when I hover over one td element all the other td elements who share the data-index value (example all who are ="1") get styliside. I am trying to accomplish a vertical column highlight.
Sollution that relies on javascript (typescript) and react:
The way I solved it with react and typescript if someone finds this later:
const handleColumnHoverEnter = (e: any) => {
const allWithAttribute = Array.from(
document.querySelectorAll("[data-index='" + e.target.dataset.index + "']")
);
allWithAttribute.forEach((element:any) => {
element.style.backgroundColor = 'red';
});
}
const handleColumnHoverLeave = (e: any) => {
const allWithAttribute = Array.from(
document.querySelectorAll("[data-index='" + e.target.dataset.index + "']")
);
allWithAttribute.forEach((element:any) => {
element.style.backgroundColor = 'white';
});
}
Thanks to users bloodyKnucklese's and t.niese's suggestions!

Using Javascript to add mouseover and mouseout event handlers on each element. Get the element's dataset data-index value and use that to change the background on all elements having the same value:
document.querySelectorAll("td[data-index]").forEach(di => {
di.addEventListener("mouseover", (event) => {
document.querySelectorAll(`td[data-index="${di.dataset.index}"]`).forEach(
dii => { dii.style.backgroundColor = "#EEEEEE"; }
);
});
di.addEventListener("mouseout", (event) => {
document.querySelectorAll(`td[data-index="${di.dataset.index}"]`).forEach(
dii => { dii.style.backgroundColor = "#FFFFFF"; }
);
});
});
<table>
<tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
<tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
<tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
<tr> <td data-index="1">1</td> <td data-index="2">2</td> <td data-index="3">3</td> <td data-index="4">4</td></tr>
</table>

You could do something like that with the :has selector (which is at the time of writing only supported by Chrome 105+ and Safari 15.4+), so not really useful right now.
Anyhow, with :has you could have a slector like table:has([data-index="1"]:hover) [data-index="1"], which means, get the table elements that contains an element [data-index="1"] that is hovered, and select all descendance of that table that match [data-index="1"]
table:has([data-index="1"]:hover) [data-index="1"] {
background-color: red;
}
table:has([data-index="2"]:hover) [data-index="2"] {
background-color: red;
}
table:has([data-index="3"]:hover) [data-index="3"] {
background-color: red;
}
table:has([data-index="4"]:hover) [data-index="4"] {
background-color: red;
}
td {
width: 10px;
height: 10px;
border: 1px solid red;
}
td::before {
content: attr(data-index);
}
<table>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>
Without the support of :has you need to use JavaScript.
For this purpose you can use event delegation, which has the advantage that the data attributes and number of elements can change without the need to update the listeners.
let table = document.querySelector('table');
table.addEventListener('mouseover', (evt) => {
if ( evt.target.matches('[data-index]') ) {
table.dataset.hover = evt.target.dataset.index;
}
})
table.addEventListener('mouseout', (evt) => {
if ( evt.target.matches('[data-index]') ) {
table.dataset.hover = 0;
}
})
[data-hover="1"] [data-index="1"] {
background-color: red;
}
[data-hover="2"] [data-index="2"] {
background-color: red;
}
[data-hover="3"] [data-index="3"] {
background-color: red;
}
[data-hover="4"] [data-index="4"] {
background-color: red;
}
td {
width: 10px;
height: 10px;
border: 1px solid red;
}
td::before {
content: attr(data-index);
}
<table>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
<tr> <td data-index="1"></td> <td data-index="2"></td> <td data-index="3"></td> <td data-index="4"></td></tr>
</table>

It can be done like below.
td[data-index="1"]:hover{
background-color: red;
}

Related

JQuery select & reset (clear) date range in HTML Calendar

I use a HTML calendar in which you can select a date range. Unfortunately it is not possible to delete a selected range. My idea would be to solve this with even and odd:
First click (odd) select first day
Second click (even) select range
Third click (odd) delete all selects and select new first day
Fourth click (even) select new range
...
I am glad about tips and help. I can't get any further on my own.
$(document).ready(function() {
$('td.day').click(function() {
if ($("td.firstClick").length == 0) {
$(this).addClass("firstClick");
}
});
$('td.day').hover(function() {
if ($("td.firstClick").length == 0) {
$(this).addClass("selected");
return;
}
$(this).addClass("secondClick");
var tds = $('td.day');
var firstClick = $(".firstClick");
var firstClickIndex = tds.index(firstClick);
var currentIndex = tds.index(this);
tds.filter(function() {
var idx = tds.index(this);
return idx >= firstClickIndex && idx <= currentIndex;
}).addClass("selected")
}, function() {
if ($("td.firstClick").length == 0) {
$(this).removeClass("selected");
return;
}
$(this).removeClass("secondClick");
var tds = $('td.day');
var firstClick = $(".firstClick");
var firstClickIndex = tds.index(firstClick);
var currentIndex = tds.index(this);
tds.filter(function() {
var idx = tds.index(this);
return idx >= firstClickIndex && idx <= currentIndex;
}).removeClass("selected")
});
$('table').on('click', 'td.secondClick', function() {
$('.selected').addClass('reserved');
});
});
table {
border-collapse: collapse;
}
table tr td {
width: 14%;
}
table tr td:hover {
cursor: pointer;
}
.firstClick {
background: green;
}
.selected {
background: lightgreen;
}
.reserved {
background: red !important;
}
.secondClick {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr>
<td colspan="7"><b>2016</b>
</td>
</tr>
<tr>
<td colspan="7"><i>November</i>
</td>
</tr>
<tr>
<th>mon</th>
<th>tue</th>
<th>wed</th>
<th>thu</th>
<th>fri</th>
<th>sat</th>
<th>sun</th>
</tr>
<tr>
<td></td>
<td class="day">1</td>
<td class="day">2</td>
<td class="day">3</td>
<td class="day">4</td>
<td class="day">5</td>
<td class="day">6</td>
</tr>
<tr>
<td class="day">7</td>
<td class="day">8</td>
<td class="day">9</td>
<td class="day">10</td>
<td class="day">11</td>
<td class="day">12</td>
<td class="day">13</td>
</tr>
<tr>
<td class="day">14</td>
<td class="day">15</td>
<td class="day">16</td>
<td class="day">17</td>
<td class="day">18</td>
<td class="day">19</td>
<td class="day">20</td>
</tr>
<tr>
<td class="day">21</td>
<td class="day">22</td>
<td class="day">23</td>
<td class="day">24</td>
<td class="day">25</td>
<td class="day">26</td>
<td class="day">27</td>
</tr>
<tr>
<td class="day">28</td>
<td class="day">29</td>
<td class="day">30</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
remove class reserved, selected and secondClick in td.day click function to remove range selected before
$('td.day').click(function() {
if ($("td.firstClick").length == 0) {
$('td.day').removeClass("reserved");
$('td.day').removeClass("selected");
$('td.day').removeClass("secondClick");
$(this).addClass("firstClick");
}
});
and in table td.secondClick click function remove class firstClick to reinit new firstClick
$('table').on('click', 'td.secondClick', function() {
$('.selected').addClass('reserved');
$('td.day').removeClass("firstClick");
});

How to hide/display a set of HTML table rows when clicking on some other sibling table row?

I've been looking around, finding some solutions and trying to apply them, with little luck.
I am putting together an HTML file that displays test results.
Test results are shown in rows:
<tr>
<th class="test_name_row" colspan="5">Test: spc-aes-gcm-decrypt</th>
</tr>
<tr>
<td class="subtest_name_col">Subtest 1</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
<tr>
<td class="subtest_name_col">Subtest 2</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
The behavior I'm looking for is the following:
If the user clicks on the 'test_name_row', the two table rows beneath will collapse / unfold, hopefully with some sleek animation.
What's the best strategy to achieve this?
My solution:
HTML
<tr>
<th class="test_name_row" colspan="5" onclick="hideShow()">Test: spc-aes-gcm-decrypt</th>
</tr>
<tr id="row1">
<td class="subtest_name_col">Subtest 1</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
<tr id="row2">
<td class="subtest_name_col">Subtest 2</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
Javascript
var hidden = false;
function hideShow() {
if (hidden == true) {
//show
document.getElementById("row1").classList.remove("hidden");
document.getElementById("row2").classList.remove("hidden");
document.getElementById("row1").classList.add("visible");
document.getElementById("row2").classList.add("visible");
hidden = false;
} else {
//hide
document.getElementById("row1").classList.add("hidden");
document.getElementById("row2").classList.add("hidden");
document.getElementById("row1").classList.remove("visible");
document.getElementById("row2").classList.remove("visible");
hidden = true;
}
}
CSS
.hidden {
opacity: 0;
transition: 0.5s;
}
.visible {
opacity: 1;
transition: 0.5s;
}
If you don't want to have animation, you can remove those classes (from both CSS and JS) and just use
.style.display = "none"
in javascript.
Same as a snippet:
var hidden = false;
function hideShow() {
if (hidden == true) {
//show
document.getElementById("row1").classList.remove("hidden");
document.getElementById("row2").classList.remove("hidden");
document.getElementById("row1").classList.add("visible");
document.getElementById("row2").classList.add("visible");
hidden = false;
} else {
//hide
document.getElementById("row1").classList.add("hidden");
document.getElementById("row2").classList.add("hidden");
document.getElementById("row1").classList.remove("visible");
document.getElementById("row2").classList.remove("visible");
hidden = true;
}
}
.hidden {
opacity: 0;
transition: 0.5s;
}
.visible {
opacity: 1;
transition: 0.5s;
}
<table>
<tr>
<th class="test_name_row" colspan="5" onclick="hideShow()">Test: spc-aes-gcm-decrypt</th>
</tr>
<tr id="row1">
<td class="subtest_name_col">Subtest 1</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
<tr id="row2">
<td class="subtest_name_col">Subtest 2</td>
<td class="neutral_metric">2880</td>
<td class="good_metric">2880</td>
<td class="neutral_metric">0</td>
</tr>
</table>
EDIT: added one missing row

Understanding specificity in table properties

"A selector's weighting is evaluated based on the components that make it up, with id's given a weighting of 100, classes with a weighting of 10, and element selectors with weighting of 1."
According to this th should weight 1 while tr:nth-child(2n+1) should weigh 11 due to pseudo class. but the background color of th is used when displayed in the browser. Can you explain why ?
table {
margin-left: 20px;
margin-right: 20px;
border: thin solid black;
caption-side: bottom;
border-collapse: collapse;
}
td,
th {
border: thin dotted gray;
padding: 5px;
}
caption {
font-style: italic;
padding-top: 8px;
}
td.center,
th.center {
text-align: center;
}
td.right,
th.right {
text-align: right;
}
th {
background-color: #cc6600;
}
tr:nth-child(2n+1) {
background-color: #fcba7a;
}
<table>
<caption>The cities I visited on my Segway'n USA travels</caption>
<tr>
<th>City</th>
<th class="center">Date</th>
<th class="center">Temprature</th>
<th class="right">Altitude</th>
<th class="right">Population</th>
<th class="center">Dinner Rating</th>
</tr>
<tr>
<td>Walla Walla, WA</td>
<td class="center">June 15th</td>
<td class="center">78</td>
<td class="right">1,204 ft</td>
<td class="right">29,686</td>
<td class="center">4/5</td>
</tr>
<tr class="cellcolor">
<td>Magic City, ID</td>
<td class="center">June 25th</td>
<td class="center">74</td>
<td class="right">5,312 ft</td>
<td class="right">50</td>
<td class="center">3/5</td>
</tr>
<tr>
<td>Bountiful, UT</td>
<td class="center">July 10th</td>
<td class="center">91</td>
<td class="right">4,226 ft</td>
<td class="right">41,173</td>
<td class="center">4/5</td>
</tr>
<tr class="cellcolor">
<td>Last Chance, CO</td>
<td class="center">July 23rd</td>
<td class="center">102</td>
<td class="right">4,780 ft</td>
<td class="right">256</td>
<td class="center">3/5</td>
</tr>
<tr>
<td>Truth Or Consequences, NM</td>
<td class="center">August 9th</td>
<td class="center">93</td>
<td class="right">4,242 ft</td>
<td class="right">7,289</td>
<td class="center">5/5</td>
</tr>
<tr class="cellcolor">
<td>Why, AZ</td>
<td class="center">August 18th</td>
<td class="center">104</td>
<td class="right">860 ft</td>
<td class="right">480</td>
<td class="center">3/5</td>
</tr>
</table>
th and tr are two different elements, so it wouldn't effect each other.
This isn't an issue of specificity. You are dealing with two different selectors.
The first selector targets table rows.
tr:nth-child(2n+1) {
background-color: #fcba7a;
}
The other selector targets table headings.
th {
background-color: #cc6600;
}
If you want to actually measure specificity, then have them target the same elements:
tr:nth-child(2n+1) > th {
background-color: #fcba7a;
}
th {
background-color: #cc6600;
}
table {
margin-left: 20px;
margin-right: 20px;
border: thin solid black;
caption-side: bottom;
border-collapse: collapse;
}
td,
th {
border: thin dotted gray;
padding: 5px;
}
caption {
font-style: italic;
padding-top: 8px;
}
td.center,
th.center {
text-align: center;
}
td.right,
th.right {
text-align: right;
}
th {
background-color: #cc6600;
}
tr:nth-child(2n+1) > th {
background-color: #fcba7a;
}
<table>
<caption>The cities I visited on my Segway'n USA travels</caption>
<tr>
<th>City</th>
<th class="center">Date</th>
<th class="center">Temprature</th>
<th class="right">Altitude</th>
<th class="right">Population</th>
<th class="center">Dinner Rating</th>
</tr>
<tr>
<td>Walla Walla, WA</td>
<td class="center">June 15th</td>
<td class="center">78</td>
<td class="right">1,204 ft</td>
<td class="right">29,686</td>
<td class="center">4/5</td>
</tr>
<tr class="cellcolor">
<td>Magic City, ID</td>
<td class="center">June 25th</td>
<td class="center">74</td>
<td class="right">5,312 ft</td>
<td class="right">50</td>
<td class="center">3/5</td>
</tr>
<tr>
<td>Bountiful, UT</td>
<td class="center">July 10th</td>
<td class="center">91</td>
<td class="right">4,226 ft</td>
<td class="right">41,173</td>
<td class="center">4/5</td>
</tr>
<tr class="cellcolor">
<td>Last Chance, CO</td>
<td class="center">July 23rd</td>
<td class="center">102</td>
<td class="right">4,780 ft</td>
<td class="right">256</td>
<td class="center">3/5</td>
</tr>
<tr>
<td>Truth Or Consequences, NM</td>
<td class="center">August 9th</td>
<td class="center">93</td>
<td class="right">4,242 ft</td>
<td class="right">7,289</td>
<td class="center">5/5</td>
</tr>
<tr class="cellcolor">
<td>Why, AZ</td>
<td class="center">August 18th</td>
<td class="center">104</td>
<td class="right">860 ft</td>
<td class="right">480</td>
<td class="center">3/5</td>
</tr>
</table>

Hide a line from a table with td class

I'm creating dynamicly an html table with a php code.
If the data are not updated(by date-time check) i get an .offline td class on the created table.
I want to have only the top 5 results sorted by the highest of the 30 temperatures for example.
I'm using
table.sortable tbody tr:nth-child(n + 6) {
visibility: hidden;
}
To do that.
But if on the top 5 results is something thats 2 hours old data i want to hide it and displat the next one.
I'm trying with:
.offline {
display: none;
}
But it just delete the line and i have for example 4 results
This is the complete table style:
<html>
<head>
<meta charset="UTF-8">
<script src="https://cretaweather.gr/protected/sorttabletemp.js" type="text/javascript"></script>
<link href="../assets/css/templatetable2.css?v=1.1" type="text/css" rel="stylesheet" >
<script>
window.onload = function() {
(document.getElementsByTagName( "th" )[1]).click();
};
</script>
<style>table.sortable tbody tr:nth-child(2n) td {
background: #c2cdd6;
}
table.sortable tbody tr:nth-child(2n+1) td {
background: #ccfffff;
}
table.sortable tbody tr:nth-child(n + 6) {
visibility: hidden;
}
table.sortable tbody td:nth-child(n + 3) {
display: none;
}
.offline {
display: none;
}
</style>
</head>
<body>
<table align="center" id="template" border="1" bordercolordark="#333333" bordercolorlight="#333333" width="300" cellpadding="0" cellspacing="0" style="border-collapse: collapse; text-align:center;" class="sortable">
<thead>
<tr height="31" bgcolor="#c9e5f2">
<th class="sorttable_nosort" width="150" valign="top" align="center">Περιοχή</th>
<th class="sorttable_numeric" valign="top" align="center">Θερμοκρασία</th>
</tr>
</thead>
<tbody>
This is a part of created html:
</tr><tr class="odd-line">
<td class="offline">Μάλια</td>
<td class="offline">22.3&degC at 8:57</td>
<td class="offline">29/04/18</td>
<td class="offline">9:01</td>
</tr><tr class="even-line">
<td class="">Μεσοχωριό</td>
<td class="">25.8&degC at 14:10</td>
<td class="">25/05/18</td>
<td class="">18:33</td>
</tr><tr class="odd-line">
<td class="offline">Μεταξοχώρι</td>
<td class="offline">32.3&degC at 13:43</td>
<td class="offline">23/05/18</td>
<td class="offline">14:00</td>
</tr><tr class="even-line">
<td class="">Μοχός</td>
<td class="">22.2&degC at 16:01</td>
<td class="">25/05/18</td>
<td class="">18:34</td>
</tr><tr class="odd-line">
<td class="">Πετροκεφάλι</td>
<td class="">29.4&degC at 13:26</td>
<td class="">25/05/18</td>
<td class="">18:30</td>
</tr><tr class="even-line">
<td class="">Πεζά</td>
<td class="">24.1&degC at 13:26</td>
<td class="">25/05/18</td>
<td class="">18:30</td>
</tr><tr class="odd-line">
<td class="">Προφήτης Ηλίας</td>
<td class="">25.5&degC at 15:16</td>
<td class="">25/05/18</td>
<td class="">18:34</td>
What shall i do to achive that.
visibility: hidden just gives an emty space.
This is how it is displayed now:
i want to hide the red line thats outdated and display the sixth line instead, to have top5 updated data

Hide table columns by class

I have a table from n columns. Each cell has a class column-n.
I want to add on table class hide-column-n and hide all cells with class column-n.
Is this possible do it through css?
Example:
.table {
border: 1px solid black;
}
.table thead{
background-color: lightgray;
}
.table td{
border: 1px solid gray;
width: 50px;
}
<table class="table">
<thead>
<tr>
<td class="column-1">One</td>
<td class="column-2">Two</td>
<td class="column-3">Three</td>
<td class="column-x">...</td>
<td class="column-n">N</td>
</tr>
</thead>
<tbody>
<tr>
<td class="column-1">One</td>
<td class="column-2">Two</td>
<td class="column-3">Three</td>
<td class="column-x">...</td>
<td class="column-n">N</td>
</tr>
<tr>
<td class="column-1">One</td>
<td class="column-2">Two</td>
<td class="column-3">Three</td>
<td class="column-x">...</td>
<td class="column-n">N</td>
</tr>
<tr>
<td>...</td>
</tr>
</tbody>
</table>
Here is example https://jsfiddle.net/xr21kwrh/
<table class="table">
<thead>
<tr>
<th class=column-1">One</th>
<th class"column-2">Two</th>
...
<th class="column-n">N</th>
</tr>
</thead>
<tbody>
<tr>
<td class=column-1">One</t>
<td class"column-2">Two</td>
...
<td class="column-n">N</td>
</tr>
<tr>
<td class=column-1">One</t>
<td class"column-2">Two</td>
...
<td class="column-n">N</td>
</tr>
...
</tbody>
</table>
<style>
th:nth-child(2){display: none;}
td:nth-child(2){display: none;}
</style>
<table class="table">
<thead>
<tr>
<th class=column-1">One</th>
<th class"column-2">Two</th>
...
<th class="column-n">N</th>
</tr>
</thead>
<tbody>
<tr>
<td class=column-1">One</t>
<td class"column-2">Two</td>
...
<td class="column-n">N</td>
</tr>
<tr>
<td class=column-1">One</t>
<td class"column-2">Two</td>
...
<td class="column-n">N</td>
</tr>
...
</tbody>
</table>
<style>
.column-n{ display-none !important; }
</style>
If you use sass/scss you can do so (in SCSS):
#for $i from 1 through 10 {
.hide-column-#{$i} .column-#{$i} {
display: none;
}
}
it will compile to:
.hide-column-1 .column-1 {
display: none;
}
.hide-column-2 .column-2 {
display: none;
}
....
.hide-column-n .column-n {
display: none;
}
then use it like expected:
<table class="table hide-column-1 hide-column-2">
codepen demo here