:nth-child(even) selector by class with specific elements [duplicate] - javascript

This question already has answers here:
Excluding an element from nth-child pattern
(5 answers)
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 2 years ago.
I have a table that has a light gray background for the even rows and white for the odd ones. it works perfectly by using .tr:nth-child(even) {}
HTML
<table>
<tr></tr>
<tr class="hidden"></tr>
<tr class="hidden"></tr>
<tr></tr>
</table>
CSS
tbody tr:nth-of-type(even) {
background-color: var(--bg);
}
I made a search field that filters table rows by adding hidden class for tr elements that not match after that the tr:nth-child(even) doesn't work.
I tried to add search-result class on the elements that match and then I made tr:nth-of-type(even) { .... }, also that not worked.
Is there any way that I can do that? for example, a way to select even elements by class?

Fixed version of the codepen in the comments using a variant of the proof of concept I have at the bottom. Count up indexes to check if even, excluding elements with display:none, done every update. This may need to be optimized for very large tables.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("input");
filter = input.value.toUpperCase();
table = document.getElementById("table");
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";
}
}
}
//let table = document.getElementsByTagName('table')[0]
(function(){
let i = 0
table.querySelectorAll('tr:not(.hidden)').forEach(el =>
el.style.display !== 'none' && i++ % 2 === 0 ? el.classList.add('even') : el.classList.remove('even'))
})()
}
* {
box-sizing: border-box;
}
#input {
background-position: 10px 12px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#table {
list-style-type: none;
padding: 0;
margin: 0;
width: 100%;
}
#table tr {
border: 1px solid #ddd;
margin-top: -1px;
background-color: #fff;
padding: 12px;
text-decoration: none;
font-size: 18px;
color: black;
}
#table th, #table td {
text-align: left;
padding: 12px;
}
#table tr :not(td) {
background-color: #424242;
color: white;
}
#table tr:not(.even) {
background-color: #eee!important;
}
<input type="text" id="input" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="table">
<tr>
<th style="width:60%;">Name</th>
<th style="width:40%;">Age</th>
</tr>
<tr>
<td>Adam</td>
<td>22</td>
</tr>
<tr>
<td>malik</td>
<td>40</td>
</tr>
<tr>
<td>Asal</td>
<td>32</td>
</tr>
<tr>
<td>Asal</td>
<td>26</td>
</tr>
<tr>
<td>Asali</td>
<td>40</td>
</tr>
<tr>
<td>malik</td>
<td>40</td>
</tr>
<tr>
<td>maaaalik</td>
<td>40</td>
</tr>
</table>
select non-hidden and use counter to find even. add class.
let table = document.getElementsByTagName('table')[0]
let i = 0
table.querySelectorAll('tr:not(.hidden)').forEach(el =>
i++ % 2 === 0 && el.classList.add('even'))
.even {
background-color: red;
}
.hidden {
opacity: 0.2;
}
<table>
<tr>
<td>1</td>
</tr>
<tr class="hidden">
<td>2</td>
</tr>
<tr class="hidden">
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
<tr class="hidden">
<td>2</td>
</tr>
<tr class="hidden">
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr class="hidden">
<td>2</td>
</tr>
<tr class="hidden">
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr class="hidden">
<td>2</td>
</tr>
<tr class="hidden">
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>1</td>
</tr>
</table>

Related

Get search results for terms that are not part of the table

I have an HTML table with a search function that works well. However, my search function only finds the results based on the existing table data. I am trying to show results for terms that aren't in the table. I am able to do this but with limited success.
As an example, if I search for "Apple Banana" (text that is not part of my table), the results are the same as if I searched for "ABC" (text that is part of my table). See my table below for example.
The problem is, I only get results after searching the entire term "Apple Banana". Is there a way to search for "App" or "Ban" (not exact match but contains) and still get the results? If using an object is not the best approach, I am open to any other suggestions. Note that the HTML table is generated automatically by the Content Management System and I am not able to manipulate it. I can update JavaScript or CSS file.
const obj = {
'Apple Banana':'ABC',
};
function myFunction() {
let userInput = document.getElementById("myInput").value;
if(obj[userInput]) userInput = obj[userInput];
userInput = userInput.toUpperCase();
const tableRows = document.querySelectorAll("table tr");
for (let i = 0; i < tableRows.length; i++) {
const rowTextContent = tableRows[i].innerText.toUpperCase();
tableRows[i].style.display = rowTextContent.toUpperCase().includes(userInput) ? "" : "none";
}
}
table.table_brdr td {
padding: 8px 10px;
border: none;
}
table.table_brdr th {
background-color: #a6a6a6;
color: black;
}
tr:nth-of-type(odd) {
background-color#D3D3D3;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 20%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
<p><input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search forms list" title="Search forms list"></p>
<table class="table_brdr" id="myTable">
<tr>
<th>Column1</th>
<th><strong>Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>abc</td>
<td>xyz</td>
<td>03/30/2017</td>
</tr>
<tr>
<td>test12</td>
<td>https://www.yahoo.com/ </td>
<td>03/30/2017</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column</th>
<th>Column3</th>
</tr>
<tr>
<td>John</td>
<td>abctd <td>
<td>09/30/2019</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>Doe</td>
<td>abctd </td>
<td>06/30/2019</td>
</tr>
</tbody></table>
I changed up your js a a little bit. I used 2d array of values to search for and then filtered one out. Hope it helps.
// array of values to serach for
let values = [
['ABC', 'Apple', 'Banana', 'Apple Banana'],
['test12', 'otherSearch']
]
// convert all values to upperCase or simply declare them upperCase in array
values = values.map(arr => arr.map(v => v.toUpperCase()))
function myFunction() {
let userInput = document.getElementById("myInput").value.toUpperCase();
// filter for array with user input and desired phrases
const filtered = values.filter(arr => {
return arr.some(v => v.includes(userInput))
}).flat()
const tableRows = document.querySelectorAll("table tr");
for (let i = 0; i < tableRows.length; i++) {
const rowTextContent = tableRows[i].innerText.toUpperCase();
tableRows[i].style.display = filtered.some(v => rowTextContent.includes(v)) ? "" : "none";
}
}
table.table_brdr td {
padding: 8px 10px;
border: none;
}
table.table_brdr th {
background-color: #a6a6a6;
color: black;
}
tr:nth-of-type(odd) {
background-color: #D3D3D3;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 20%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
<p><input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search forms list" title="Search forms list"></p>
<table class="table_brdr" id="myTable">
<tr>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>abc</td>
<td>xyz</td>
<td>03/30/2017</td>
</tr>
<tr>
<td>test12</td>
<td>https://www.yahoo.com/ </td>
<td>03/30/2017</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column</th>
<th>Column3</th>
</tr>
<tr>
<td>John</td>
<td>abctd <td>
<td>09/30/2019</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>Doe</td>
<td>abctd </td>
<td>06/30/2019</td>
</tr>
</table>

How can I add sorting to HTML table columns that has multiple headers

There are multiple headers in my HTML table . How do I add sorting to this table? My table is shown below.
I would like to add sort only on top header and then it should sort all the columns including the rows in the second and third header.
https://codepen.io/magic12/pen/QWmvpyM
There are multiple headers in my HTML table . How do I add sorting to this table? My table is shown below.
I would like to add sort only on top header and then it should sort all the columns including the rows in the second and third header.
https://codepen.io/magic12/pen/QWmvpyM
HTML:
<p><input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search" title="Searche"></p>
<table class="table_brdr" id="myTable">
<tr>
<th>Column1</th>
<th><strong>Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>abc</td>
<td>xyz</td>
<td>03/30/2017</td>
</tr>
<tr>
<td>test12</td>
<td>https://www.yahoo.com/ </td>
<td>03/30/2017</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column</th>
<th>Column3</th>
</tr>
<tr>
<td>John</td>
<td>abctd <td>
<td>09/30/2019</td>
</tr>
<tr>
<th>Column1</th>
<th> New Column2</th>
<th>Column3</th>
</tr>
<tr>
<td>Doe</td>
<td>abctd </td>
<td>06/30/2019</td>
</tr>
</tbody></table>
CSS:
table.table_brdr td {
padding: 8px 10px;
border: none;
}
table.table_brdr th {
background-color: #a6a6a6;
color: black;
}
tr:nth-of-type(odd) {
background-color#D3D3D3;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 20%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
Javascript:
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++) {
var allTDs = tr[i].getElementsByTagName("td");
for (index = 0; index < allTDs.length; index++) {
txtValue = allTDs[index].textContent || allTDs[index].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
break;
} else {
tr[i].style.display = "none";
break;
}
}
}
}

Prevent table from resizing when adding border to specific cell

Here is my code. The problem is: When i click a td cell, add border to it, and the border makes the table changes size.
For some reasons, i dont want the table increase its size when adding border to td tag, and i can not use outline in css.
I tried to add this line of css code : box-sizing: border-box; but it does not seem to work.
Thank you for any idea!!
Array.prototype.forEach.call(
document.querySelectorAll('td'),
function(td) {
td.addEventListener('click', function(e) {
e.target.classList.add('myBorder')
})
})
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
box-sizing: border-box;
}
.myBorder {
border: 2px solid #4b89ff;
}
<table>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Bob</td>
<td>Male</td>
</tr>
<tr>
<td>2</td>
<td>Anna</td>
<td>Female</td>
</tr>
<tr>
<td>3</td>
<td>Christ</td>
<td>Male</td>
</tr>
</tbody>
</table>
Inspecting the td with Chrome i found that adding the class to the cell was also generating a padding of 1px. And if you set padding-bottom: 0px; on .myBorder class will solve the problem.
Array.prototype.forEach.call(
document.querySelectorAll('td'),
function(td) {
td.addEventListener('click', function(e) {
e.target.classList.add('myBorder')
})
})
table {
border-collapse: collapse;
}
th, td {
border: 1px solid black;
}
.myBorder {
border: 2px solid #4b89ff;
padding-bottom: 0px;
}
<table>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Bob</td>
<td>Male</td>
</tr>
<tr>
<td>2</td>
<td>Anna</td>
<td>Female</td>
</tr>
<tr>
<td>3</td>
<td>Christ</td>
<td>Male</td>
</tr>
</tbody>
</table>

How to grey out in html tables

When I try to create html tables,I wonder How I can greyout unseected cells.
When I click cell 2,my desired result is like below.
I tried like below code. If there is more sophisticated method for greyout Please let me know.
Thanks
var $ = jQuery;
$('td').on('click', function(e) {
e.preventDefault();
$('table').toggleClass('greyout');
})
td {
background-color: aqua;
transition-duration: 0.5s;
border: solid black 1px;
padding: 5px;
}
table {
border-collapse: collapse;
}
.greyout {
opacity: 0.2;
/* Real browsers */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
You need to apply the class to all cells except the one which was clicked, so use the not() method. Also note that to enable subsequent clicks you need to remove that class from any td elements before adding it to the next set.
In addition note that preventDefault() is redundant on a td click handler as there is no default action to prevent. Also, if you want to alias $ use the argument in the document.ready handler.
With all that said, try this:
jQuery($ => {
let $td = $('td').on('click', function() {
$td.removeClass('greyout').not(this).addClass('greyout');
})
});
td {
background-color: aqua;
transition-duration: 0.5s;
border: solid black 1px;
padding: 5px;
}
table {
border-collapse: collapse;
}
.greyout {
opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
I would go for the following logic:
$mainTable = $('table');
$mainTable.on('click', 'td', function(){
if( this.classList.contains('selected') ){
$(this).removeClass('selected')
} else{
$mainTable.find('.selected').removeClass('selected');
$(this).addClass('selected')
}
$mainTable.toggleClass('withSelectedOption', $mainTable.find('.selected').length !== 0);
});
table td{
background: aqua;
padding: 10px;
}
table.withSelectedOption td{
background: grey;
}
table.withSelectedOption td.selected{
background: aqua;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>1</td><td>2</td><td>3</td>
</tr>
<tr>
<td>4</td><td>5</td><td>6</td>
</tr>
<tr>
<td>7</td><td>8</td><td>9</td>
</tr>
</table>

how to highlight table cells in a certain way when hover over

I need to highlight table cells with 'J' mark like this:
In this picture I hover over a cell (the one that has a black border) and certain cells around it changes color. How to do this? I only can change a single cell, row or column.
td {
padding: 8px;
background-color: #fff;
font-weight: bold;
}
tr:hover {
color: #fff;
background-color: #000;
}
tr:hover td {
background-color: transparent;
}
<table>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</table>
The solution that I am proposing using jQuery in order to link an event on every td:hover. By using each, hover, Math.floor and toggleClass you can easily achieve what you want to do.
$(function() {
$('#my-table td').each(function(index, elem){
$("#" + elem.id).hover(function(){
row_index = Math.floor((elem.id - 1) / 5);
col_index = (elem.id - 1) % 5;
right_cell_col = col_index + 1;
top_cell_index = parseInt(elem.id) - 4;
left_cell_col = col_index - 1;
bottom_cell_index = parseInt(elem.id) + 5;
if(left_cell_col >= 0) $("#" + (elem.id - 1)).toggleClass("colored");
if(right_cell_col <= 4) {
if (top_cell_index > 0) $("#" + top_cell_index).toggleClass("colored");
$("#" + (parseInt(elem.id) + 1)).toggleClass("colored");
}
if(bottom_cell_index < 26) $("#" + bottom_cell_index).toggleClass("colored");
});
});
});
td {
width: 10px;
height: 10px;
border: 1px solid #ddd;
padding: 8px;
background-color: #fff;
font-weight: bold;
}
td:hover {
border-color: black;
font-weight: bold;
}
.colored {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="my-table">
<tr>
<td id=1></td>
<td id=2></td>
<td id=3></td>
<td id=4></td>
<td id=5></td>
</tr>
<tr>
<td id=6></td>
<td id=7></td>
<td id=8></td>
<td id=9></td>
<td id=10></td>
</tr>
<tr>
<td id=11></td>
<td id=12></td>
<td id=13></td>
<td id=14></td>
<td id=15></td>
</tr>
<tr>
<td id=16></td>
<td id=17></td>
<td id=18></td>
<td id=19></td>
<td id=20></td>
</tr>
<tr>
<td id=21></td>
<td id=22></td>
<td id=23></td>
<td id=24></td>
<td id=25></td>
</tr>
</table>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<style>
table {
border-collapse: collapse;
border: 1px solid #000;
}
table td {
border: 1px solid #000;
}
td {
text-align: center;
font-size: 0;
width: 30px;
height: 30px;
background-color: #fff;
font-weight: bold;
}
tr.hover {
color: #fff;
background-color: #000;
}
/* tr:hover td {
background-color: transparent;
} */
td.hover {
color: #fff;
background-color: #000;
}
td.center {
color: #fff;
background-color: #fff;
outline: 2px red solid;
}
</style>
<script>
$(document).ready(function() {
var HEIGHT = 5;
var WIDTH = 5;
$('td').hover(function() {
var self = $(this);
var table = self.parent().parent();
var column = self.index();
var row = self.parent().index();
var current = table.find(`tr:eq(${row}) td:eq(${column})`)
current.toggleClass('center')
if (column > 0) {
var before = table.find(`tr:eq(${row}) td:eq(${column - 1})`)
before.toggleClass('hover');
}
if (row < HEIGHT - 1) {
var bottom = table.find(`tr:eq(${row + 1}) td:eq(${column})`)
bottom.toggleClass('hover');
}
if (column < WIDTH - 1) {
var next = table.find(`tr:eq(${row}) td:eq(${column + 1})`)
next.toggleClass('hover');
}
if (row > 0 && column < WIDTH - 1) {
var nextUp = table.find(`tr:eq(${row - 1}) td:eq(${column + 1})`)
nextUp.toggleClass('hover');
}
});
});
</script>
</head>
<body>
<table>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</table>
</body>
</html>
How about using jquery?

Categories

Resources