Count visible rows from a specific class in html table using Javascript - javascript

How to count total visible rows from a specific class such as ".CountTwo" in html table using JavaScript, I have a code below that filters table rows while typing.
I'm having issues here
count.push(document.querySelectorAll('.CountTwo'))
function myFunction() {
// Declare variables
if (document.getElementById('name').checked) {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("MyTable");
tr = table.getElementsByTagName("tr");
count = [];
rowsFound = [];
// 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")[1]; // change number to any other number to target column for table search
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
rowsFound.push(1)
count.push(document.querySelectorAll('.CountTwo'))
} else {
tr[i].style.display = "none";
}
}
}
document.getElementById("archieve").innerHTML = count.length;
document.getElementById("statistic").innerHTML = rowsFound.length;
}
}
#MyTable tbody tr {
border-bottom: 1px solid #dddddd;
}
#MyTable tbody tr:nth-child(even) {
background-color: #313131;
}
#MyTable tbody tr:last-of-type {
border-bottom: 2px solid #E5BB7F;
}
#MyTable a {
color: rgb(84, 204, 255);
}
#MyTable tbody tr {
background-color: #0a2c5500;
}
<table id="MyTable">
<thead>
<tr>
<th>#</th>
<th>name</th>
<th>number</th>
<th>date</th>
<th>category</th>
<th>link</th>
<th>link2</th>
<th>link3</th>
</tr>
</thead>
<tr>
<td>1</td>
<td>John</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
</table>

I added eventListeners and used your HTML
window.addEventListener("DOMContentLoaded", () => { // when page loads
const input = document.getElementById("myInput"),
trs = document.querySelectorAll("#MyTable tbody tr"),
name = document.getElementById('name');
function myFunction() {
let cnt = 0;
if (name.checked) {
const filter = input.value.toUpperCase();
trs.forEach(tr => {
const td = tr.querySelectorAll("td")[1];
const txtValue = td.textContent;
const hide = filter && txtValue.toUpperCase().indexOf(filter) === -1;
tr.hidden = hide;
if (!hide) cnt++;
});
} else {
trs.forEach(tr => tr.hidden = false);
cnt = trs.length;
}
let visible = [...document.querySelectorAll(".CountTwo")].filter(link => !link.closest('tr').hidden).length;
document.getElementById("archieve").innerHTML = cnt;
document.getElementById("statistic").innerHTML = visible;
}
input.addEventListener("input", myFunction);
name.addEventListener("click", myFunction);
myFunction(); // set the values
})
#MyTable tbody tr {
border-bottom: 1px solid #dddddd;
}
#MyTable tbody tr:nth-child(even) {
background-color: #313131;
}
#MyTable tbody tr:last-of-type {
border-bottom: 2px solid #E5BB7F;
}
#MyTable a {
color: rgb(84, 204, 255);
}
#MyTable tbody tr {
background-color: #0a2c5500;
}
Filter <input type="text" id="myInput" /> <label>Name: <input type="checkbox" checked id="name" /></label>
<span id="archieve">0</span>
<span id="statistic">0</span>
<table id="MyTable">
<thead>
<tr>
<th>#</th>
<th>name</th>
<th>number</th>
<th>date</th>
<th>category</th>
<th>link</th>
<th>link2</th>
<th>link3</th>
</tr>
</thead>
<tr>
<td>1</td>
<td>John A</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
<tr>
<td>1</td>
<td>John B</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
<tr>
<td>1</td>
<td>JohnC</td>
<td>1000</td>
<td>1/1/2023</td>
<td>A</td>
<td><a class="CountTwo" target="_BLANK" href="#">Link To File</a></td>
</tr>
</table>

Related

Search different columns of table

I'm trying to work a way where you can click a button and search by different columns in a table. I can figure out the buttons and to change the [0] to [1] to search different columns, but how would i make it more dynamic, using javascript. I only want to search by 1 column at a time, so only search by first name or only search by nationality etc...
it is a basic code, I did web programming 20 years ago and im trying to get back up to speed.
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 (filter) {
if (txtValue.toUpperCase() == filter) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
} else {
tr[i].style.display = "";
}
}
}
}
<div class="w3-container">
<h2>All Information</h2>
<div class="w3-bar">
<button class="w3-button w3-black" style="width: 10%">#</button>
<button class="w3-button w3-teal" style="width: 10%">First Name</button>
<button class="w3-button w3-red" style="width: 10%">Last Name</button>
<button class="w3-button w3-yellow" style="width: 10%">Address</button>
<button class="w3-button w3-green" style="width: 10%">Age</button>
<button class="w3-button w3-blue" style="width: 10%">Date of Birth</button>
<button class="w3-button w3-purple" style="width: 10%">Nationality</button>
</div>
<input id="myInput" onkeyup="myFunction()" placeholder="Search by ID Number..." title="Type in a number" type="text">
<table id="myTable">
<tr class="header">
<th class="w3-center" style="width: 2%;">#</th>
<th style="text-align: left; width: 17%;">First Name</th>
<th style="text-align: left; width: 17%;">Last Name</th>
<th style="text-align: left; width: 16%;">Address</th>
<th style="text-align: left; width: 16%;">Age</th>
<th style="text-align: left; width: 16%;">Date of Birth</th>
<th style="text-align: left; width: 16%;">Nationality</th>
</tr>
<tr>
<td class="w3-center">1</td>
<td>John</td>
<td>Smith</td>
<td>Pearse Street</td>
<td>45</td>
<td>01/10/1977</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">11</td>
<td>Tim</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>17/04/1999</td>
<td>American</td>
</tr>
<tr>
<td class="w3-center">114</td>
<td>Tom</td>
<td>Deane</td>
<td>Greenwood Road</td>
<td>42</td>
<td>27/11/1980</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">208</td>
<td>Anna</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>11/06/1999</td>
<td>Scottish</td>
</tr>
<tr>
<td class="w3-center">259</td>
<td>Rachel</td>
<td>Waters</td>
<td>Station Road</td>
<td>87</td>
<td>11/02/1936</td>
<td>Irish</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>George</td>
<td>Taylor</td>
<td>Beach Avenue</td>
<td>52</td>
<td>30/07/1971</td>
<td>South African</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Neil</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>6</td>
<td>15/12/2016</td>
<td>Australian</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Sarah</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>30</td>
<td>06/01/1993</td>
<td>Australian</td>
</tr>
</table>
</div>
const column = 3
const searchFor = 'GRE'
for (const cell of document.querySelectorAll(`#myTable tr td:nth-child(${column})`))
if (cell.textContent.toUpperCase().includes(searchFor))
cell.style.background = 'lightgreen'
<table id="myTable">
<tr class="header">
<th class="w3-center" style="width: 2%;">#</th>
<th style="text-align: left; width: 17%;">First Name</th>
<th style="text-align: left; width: 17%;">Last Name</th>
<th style="text-align: left; width: 16%;">Address</th>
<th style="text-align: left; width: 16%;">Age</th>
<th style="text-align: left; width: 16%;">Date of Birth</th>
<th style="text-align: left; width: 16%;">Nationality</th>
</tr>
<tr>
<td class="w3-center">1</td>
<td>John</td>
<td>Smith</td>
<td>Pearse Street</td>
<td>45</td>
<td>01/10/1977</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">11</td>
<td>Tim</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>17/04/1999</td>
<td>American</td>
</tr>
<tr>
<td class="w3-center">114</td>
<td>Tom</td>
<td>Deane</td>
<td>Greenwood Road</td>
<td>42</td>
<td>27/11/1980</td>
<td>English</td>
</tr>
<tr>
<td class="w3-center">208</td>
<td>Anna</td>
<td>Green</td>
<td>Rosedale Avenue</td>
<td>23</td>
<td>11/06/1999</td>
<td>Scottish</td>
</tr>
<tr>
<td class="w3-center">259</td>
<td>Rachel</td>
<td>Waters</td>
<td>Station Road</td>
<td>87</td>
<td>11/02/1936</td>
<td>Irish</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>George</td>
<td>Taylor</td>
<td>Beach Avenue</td>
<td>52</td>
<td>30/07/1971</td>
<td>South African</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Neil</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>6</td>
<td>15/12/2016</td>
<td>Australian</td>
</tr>
<tr>
<td class="w3-center">1</td>
<td>Sarah</td>
<td>Smyth</td>
<td>Beach Road</td>
<td>30</td>
<td>06/01/1993</td>
<td>Australian</td>
</tr>
</table>
Looking for something like that ? (first version)
const
btSearch = document.querySelector('#bt-search')
, txt2search = document.querySelector('#txt-2-search')
, searchResult = document.querySelector('#search-result')
, myTable = document.querySelector('#my-table')
;
btSearch.disabled = true
;
myTable.onclick = ({target:TH}) =>
{
if (!TH.matches('th')) return;
clearFounds();
btSearch.disabled = true;
if (TH.classList.toggle('selec'))
{
btSearch.disabled = false;
myTable.querySelectorAll('th.selec')
.forEach(th => th.classList.toggle('selec',th===TH))
}
}
btSearch.onclick=()=>
{
clearFounds();
let txt = txt2search.value.trim()
, Rtxt = new RegExp(txt, 'i')
, nCol = 1 + myTable.querySelector('th.selec').cellIndex
, counter = 0
;
if (txt==='')
{
searchResult.textContent = 'nothing to search...';
return;
}
myTable.querySelectorAll(`tr td:nth-child(${nCol})`).forEach(td =>
{
if(Rtxt.test(td.textContent))
{
counter++;
td.classList.add('found');
}
})
searchResult.textContent = (counter===0) ? 'no result' : `${counter} element(s) found`;
}
function clearFounds()
{
searchResult.textContent = '.';
myTable.querySelectorAll('td.found')
.forEach(td => td.classList.remove('found'));
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
margin : 1rem;
}
table {
border-collapse : separate;
border-spacing : 1px;
background-color : lightslategrey;
}
th { background: cadetblue; padding: .3em .6em; cursor: pointer; }
td { background: whitesmoke; padding: .2em .5em; }
tr *:first-child { text-align: center; font-style: oblique; }
tr * { white-space: nowrap; }
th:not(.selec):hover { background: orange; }
th.selec { background: orangered }
td.found { background: aquamarine; }
caption {
text-align : left;
padding : .4rem;
font-size : 1.2rem;
background-color: #a0dbdd;
}
#search-result {
float : right;
font-size : .9rem;
}
<table id="my-table">
<caption>
Find :
<input type="text" id="txt-2-search" placeholder="select a column first...">
<button id="bt-search"> do search </button>
<span id="search-result">0</span>
</caption>
<thead>
<tr>
<th>#</th><th>First Name</th><th>Last Name</th><th>Address</th><th>Age</th><th>Date of Birth</th><th>Nationality</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>John</td><td>Smith</td><td>Pearse Street</td><td>45</td><td>01/10/1977</td><td>English</td>
</tr>
<tr>
<td>11</td><td>Tim</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>17/04/1999</td><td>American</td>
</tr>
<tr>
<td>114</td><td>Tom</td><td>Deane</td><td>Greenwood Road</td><td>42</td><td>27/11/1980</td><td>English</td>
</tr>
<tr>
<td>208</td><td>Anna</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>11/06/1999</td><td>Scottish</td>
</tr>
<tr>
<td>259</td><td>Rachel</td><td>Waters</td><td>Station Road</td><td>87</td><td>11/02/1936</td><td>Irish</td>
</tr>
<tr>
<td>1</td><td>George</td><td>Taylor</td><td>Beach Avenue</td><td>52</td><td>30/07/1971</td><td>South African</td>
</tr>
<tr>
<td>1</td><td>Neil</td><td>Smyth</td><td>Beach Road</td><td>6</td><td>15/12/2016</td><td>Australian</td>
</tr>
<tr>
<td>1</td><td>Sarah</td><td>Smyth</td><td>Beach Road</td><td>30</td><td>06/01/1993</td><td>Australian</td>
</tr>
</tbody>
</table>
As the subject interested me...
And sorry, there may be a bit too many technical things here, but I've already spent a bit too many hours there, I'll come back to explain and comment. If any questions come up here in the meantime, I'll do my best to answer them.
const
txt2search = document.querySelector('#txt-2-search')
, searchResult = document.querySelector('#search-result')
, myTable = document.querySelector('#my-table')
, tableHeads = myTable.querySelectorAll('thead th')
, styleColHover = document.querySelector('#style-col-hover')
, mouseHoverTD = ({target: TD}) =>
{
let ref = (!!TD && TD.matches('td')) ? TD.cellIndex +1 : -1;
styleColHover.textContent = `td:nth-child(${ref}) { background: var(--col-hover);}`;
};
myTable.tBodies[0].onmouseenter = mouseHoverTD;
myTable.tBodies[0].onmousemove = mouseHoverTD;
myTable.tBodies[0].onmouseout =_=> mouseHoverTD({target:null});
txt2search.onkeyup = ({key}) =>
{
if (key==='Enter') searchProcess();
}
myTable.onclick = ({target:colElm}) =>
{
if (!colElm.matches('th, td')) return;
if (colElm.matches('td'))
{
tableHeads.forEach(th=>th.classList.remove('selec'));
tableHeads[colElm.cellIndex].classList.add('selec');
}
else if (colElm.classList.toggle('selec'))
{
tableHeads.forEach(th=>th.classList.toggle('selec', th===colElm));
}
searchProcess();
}
function clearSearch()
{
searchResult.textContent = '.';
myTable.querySelectorAll('td.found').forEach(td => td.classList.remove('found'));
}
function searchProcess()
{
let indxElm = myTable.querySelector('thead th.selec')?.cellIndex ?? 'x';
clearSearch();
if(isNaN(indxElm)) return;
let txt = txt2search.value.trim()
, Regtxt = new RegExp(txt, 'i')
, counter = 0
, query = 'tr td:nth-child('+ ++indxElm +')'
;
if (txt==='')
{
searchResult.textContent = 'nothing to search...';
return;
}
myTable.querySelectorAll(query).forEach(td =>
{
if(Regtxt.test(td.textContent))
{
counter++;
td.classList.add('found');
}
})
searchResult.textContent =
(counter===0) ? 'no result' : `${counter} element(s) found`;
}
:root {
--col-hover : #eeafdb;
}
body {
font-family : Arial, Helvetica, sans-serif;
font-size : 16px;
margin : 1rem;
}
table {
border-collapse : separate;
border-spacing : 1px;
background-color : lightslategrey;
}
th { background: cadetblue; padding: .3em .6em; }
td { background: whitesmoke; padding: .2em .5em; }
tr *:first-child { text-align: center; font-style: oblique; }
tr * { white-space: nowrap; cursor: pointer; }
th:not(.selec):hover { background: orange; }
th.selec { background: orangered; }
td.found { background: aquamarine !important; }
caption {
text-align : left;
padding : .4rem;
font-size : 1.2rem;
background : #a0dbdd;
}
#search-result {
float : right;
font-size : .9rem;
}
<style id="style-col-hover"> td:nth-child(-1) { background : var(--col-hover);}</style>
<table id="my-table">
<caption>
Find :
<input type="text" id="txt-2-search" placeholder="select a column first...">
<span id="search-result">0</span>
</caption>
<thead>
<tr>
<th>#</th><th>First Name</th><th>Last Name</th><th>Address</th><th>Age</th><th>Date of Birth</th><th>Nationality</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td><td>John</td><td>Smith</td><td>Pearse Street</td><td>45</td><td>01/10/1977</td><td>English</td>
</tr>
<tr>
<td>11</td><td>Tim</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>17/04/1999</td><td>American</td>
</tr>
<tr>
<td>114</td><td>Tom</td><td>Deane</td><td>Greenwood Road</td><td>42</td><td>27/11/1980</td><td>English</td>
</tr>
<tr>
<td>208</td><td>Anna</td><td>Green</td><td>Rosedale Avenue</td><td>23</td><td>11/06/1999</td><td>Scottish</td>
</tr>
<tr>
<td>259</td><td>Rachel</td><td>Waters</td><td>Station Road</td><td>87</td><td>11/02/1936</td><td>Irish</td>
</tr>
<tr>
<td>1</td><td>George</td><td>Taylor</td><td>Beach Avenue</td><td>52</td><td>30/07/1971</td><td>South African</td>
</tr>
<tr>
<td>1</td><td>Neil</td><td>Smyth</td><td>Beach Road</td><td>6</td><td>15/12/2016</td><td>Australian</td>
</tr>
<tr>
<td>1</td><td>Sarah</td><td>Smyth</td><td>Beach Road</td><td>30</td><td>06/01/1993</td><td>Australian</td>
</tr>
</tbody>
</table>
Here's my take Dar.
//Define a column to look in
// const column = 4
//Get the value from the input
// const searchFor = document.getElementById('myInput').value
//Grab all the cells for the column
columnCells = Array.from(document.querySelectorAll(`#myTable tr td:nth-child(${column})`))
//Clear out previous matches
columnCells.forEach(cell=>cell.style.background = 'white')
//Filter the cells by the searchFor term
matchingCells = columnCells.filter(cell=>{
return cell.textContent.toLowerCase().includes(searchFor.toLowerCase()) && searchFor != ""
})
//Color them
matchingCells.forEach(cell=>cell.style.background = 'yellow')

how to use bootstrap filter for searching a name by first letter

I am using bootstrap filter for searching. But,for example when I type 'n' it shows all the name having 'n' like nathan, arjan . I don't want that.I want like this : if i type 'n' it will show only the names which starts with 'n' like nathaan,narima.
my blade.php code here:
<input class="form-control" id="myInput" type="text" placeholder="Search..">
<tbody id="myTable">
<tr>
<td>John</td>
</tr>
<tr>
<td>Anja</td>
</tr>
</tbody>
my script part here
<script>
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
</script>
There is a method called startsWith that you can use. The documentation can be found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
<script>
$(document).ready(function(){
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().startsWith(value))
});
});
});
</script>
you can change the method if you want.
$("#myInput").bind("keyup", function() {
var text = $(this).val().toLowerCase();
var items = $("tr td");
//first, hide all:
items.parent().hide();
//show only those matching user input:
items.filter(function () {
return $(this).text().toLowerCase().indexOf(text) == 0;
}).parent().show();
});
Another way would be using RegExp:
$(document).ready(function() {
$("#myInput").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
/* $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1) */
const searchRegEx = new RegExp(`^${value}`, 'i');
$(this).toggle(searchRegEx.test($(this).text().trim()));
});
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
<input class="form-control" id="myInput" type="text" placeholder="Search..">
<table class="table table-bordered">
<tbody id="myTable">
<tr>
<td>John</td>
</tr>
<tr>
<td>Anja</td>
</tr>
</tbody>
</table>
Using .charAt(0) for result set to be filtered with first character match
Basic example from w3schools modified
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
box-sizing: border-box;
}
#myInput {
background-image: url('/css/searchicon.png');
background-position: 10px 10px;
background-repeat: no-repeat;
width: 100%;
font-size: 16px;
padding: 12px 20px 12px 40px;
border: 1px solid #ddd;
margin-bottom: 12px;
}
#myTable {
border-collapse: collapse;
width: 100%;
border: 1px solid #ddd;
font-size: 18px;
}
#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;
}
</style>
</head>
<body>
<h2>My Customers</h2>
<input type="text" id="myInput" onkeyup="filterBy()" placeholder="Search..." title="Type in a name">
<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>
<tr>
<td>Laughing Bacchus Winecellars</td>
<td>Canada</td>
</tr>
<tr>
<td>Magazzini Alimentari Riuniti</td>
<td>Italy</td>
</tr>
<tr>
<td>Marimba</td>
<td>Something</td>
</tr>
<tr>
<td>Marimba</td>
<td>Something</td>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
<script>
function filterBy() {
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) {
if (txtValue.toUpperCase().charAt(0) == filter.charAt(0)) {
tr[i].style.display = "";
}
} else {
tr[i].style.display = "none";
}
if(filter.length == 0)
{
tr[i].style.display = "";
}
}
}
}
</script>
</body>
</html>

Individual column searching (text inputs)

I'm trying to add an individual search box for each table column without success.
What should be added to code below in order to make it work?
Currently my code contains a single search box for first column only.
Please run snippet to get full details.
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";
}
}
}
}
p.a {
white-space: nowrap;
}
h2 {
text-align: center;
font-family: Helvetica, Arial, sans-serif;
}
table {
margin-left: auto;
margin-right: auto;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: left;
font-family: Helvetica, Arial, sans-serif;
font-size: 90%;
white-space:nowrap;
}
table tbody tr:hover {
background-color: #dddddd;
}
.wide {
width: 90%;
}
<h2> Title here </h2>
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name"><table border="1" class="dataframe wide" id="myTable">
<thead>
<tr style="text-align: right;">
<th></th>
<th>KEY</th>
<th>DEVREVSTEP</th>
<th>WW32</th>
<th>WW33</th>
<th>WW34</th>
<th>WW35</th>
<th>WW36</th>
<th>WW37</th>
<th>WW38</th>
<th>WW39</th>
<th>WW40</th>
<th>Rule</th>
<th>LINK</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>First</td>
<td>A</td>
<td>-0.64</td>
<td>6.47</td>
<td>23.14</td>
<td>3.51</td>
<td>0.13</td>
<td>-0.41</td>
<td>-0.59</td>
<td>-0.31</td>
<td>33.13</td>
<td>A</td>
<td>Google.com</td>
</tr>
<tr>
<th>1</th>
<td>Second</td>
<td>B</td>
<td>-18.04</td>
<td>-18.42</td>
<td>-17.44</td>
<td>-16.35</td>
<td>-19.06</td>
<td>-17.49</td>
<td>-18.62</td>
<td>-17.92</td>
<td>-18.23</td>
<td>C</td>
<td>Amazon.com</td>
</tr>
<tr>
<th>2</th>
<td>Third</td>
<td>C</td>
<td>NaN</td>
<td>NaN</td>
<td>-0.59</td>
<td>2.25</td>
<td>-0.33</td>
<td>0.55</td>
<td>-0.53</td>
<td>8.96</td>
<td>17.53</td>
<td>B</td>
<td>Ebay.com</td>
</tr>
<tr>
<th>3</th>
<td>Fourth</td>
<td>A</td>
<td>-0.18</td>
<td>3.25</td>
<td>7.63</td>
<td>1.90</td>
<td>-0.19</td>
<td>0.41</td>
<td>0.15</td>
<td>0.20</td>
<td>17.31</td>
<td>A</td>
<td>Yahoo.com</td>
</tr>
<tr>
<th>4</th>
<td>Fourth</td>
<td>A</td>
<td>0.24</td>
<td>-3.25</td>
<td>-6.42</td>
<td>-1.51</td>
<td>0.60</td>
<td>-0.01</td>
<td>0.25</td>
<td>-0.02</td>
<td>-15.13</td>
<td>A</td>
<td>MSN.com</td>
</tr>
<tr>
<th>5</th>
<td>First</td>
<td>D</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>5.06</td>
<td>NaN</td>
<td>1.27</td>
<td>-0.56</td>
<td>13.24</td>
<td>A</td>
<td>Google.com</td>
</tr>
</tbody>
</table>
If you want to show only rows that are a match for all entered filter values - then you best loop over all the input fields on each change, that is easiest to handle.
I inserted input fields into the table header cells here, and then simply select them using getElementsByTagName - you can change that to a different position and / or using a different method to select them (f.e. by class maybe), it might need some slight adaptations then.
Notice how in both loops I start with the index 1 here, not 0 - to ignore the first table row in the i loop (because the header row should not disappear; could be done differently by selecting only the rows in the tbody to begin with), and to ignore the first cell in the j loop. And since the number of input fields is one less than the number of cells per row, I access the input using index j - 1, got get the one corresponding to the cell index.
This probably leaves room for refinements in several places, but should be enough to illustrate the basic principle.
function myFunction() {
var inputs, table, tr, i, j, inputValue, txtValue, showRow;
inputs = document.getElementsByTagName("input");
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
showRow = true;
for (j = 1; j < tr[i].cells.length; j++) {
inputValue = inputs[j - 1].value
txtValue = tr[i].cells[j].textContent || tr[i].cells[j].innerText;
if (inputValue != "" && txtValue.toUpperCase().indexOf(inputValue.toUpperCase()) == -1) {
showRow = false;
break;
}
}
tr[i].style.display = showRow ? "" : "none";
}
}
p.a {
white-space: nowrap;
}
h2 {
text-align: center;
font-family: Helvetica, Arial, sans-serif;
}
table {
margin-left: auto;
margin-right: auto;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
padding: 5px;
text-align: left;
font-family: Helvetica, Arial, sans-serif;
font-size: 90%;
white-space: nowrap;
}
table tbody tr:hover {
background-color: #dddddd;
}
.wide {
width: 90%;
}
<h2> Title here </h2>
<table border="1" class="dataframe wide" id="myTable">
<thead>
<tr style="text-align: right;">
<th></th>
<th><input type="text" onkeyup="myFunction()"><br>KEY</th>
<th><input type="text" onkeyup="myFunction()"><br>DEVREVSTEP</th>
<th><input type="text" onkeyup="myFunction()"><br>WW32</th>
<th><input type="text" onkeyup="myFunction()"><br>WW33</th>
<th><input type="text" onkeyup="myFunction()"><br>WW34</th>
<th><input type="text" onkeyup="myFunction()"><br>WW35</th>
<th><input type="text" onkeyup="myFunction()"><br>WW36</th>
<th><input type="text" onkeyup="myFunction()"><br>WW37</th>
<th><input type="text" onkeyup="myFunction()"><br>WW38</th>
<th><input type="text" onkeyup="myFunction()"><br>WW39</th>
<th><input type="text" onkeyup="myFunction()"><br>WW40</th>
<th><input type="text" onkeyup="myFunction()"><br>Rule</th>
<th><input type="text" onkeyup="myFunction()"><br>LINK</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>First</td>
<td>A</td>
<td>-0.64</td>
<td>6.47</td>
<td>23.14</td>
<td>3.51</td>
<td>0.13</td>
<td>-0.41</td>
<td>-0.59</td>
<td>-0.31</td>
<td>33.13</td>
<td>A</td>
<td>Google.com</td>
</tr>
<tr>
<th>1</th>
<td>Second</td>
<td>B</td>
<td>-18.04</td>
<td>-18.42</td>
<td>-17.44</td>
<td>-16.35</td>
<td>-19.06</td>
<td>-17.49</td>
<td>-18.62</td>
<td>-17.92</td>
<td>-18.23</td>
<td>C</td>
<td>Amazon.com</td>
</tr>
<tr>
<th>2</th>
<td>Third</td>
<td>C</td>
<td>NaN</td>
<td>NaN</td>
<td>-0.59</td>
<td>2.25</td>
<td>-0.33</td>
<td>0.55</td>
<td>-0.53</td>
<td>8.96</td>
<td>17.53</td>
<td>B</td>
<td>Ebay.com</td>
</tr>
<tr>
<th>3</th>
<td>Fourth</td>
<td>A</td>
<td>-0.18</td>
<td>3.25</td>
<td>7.63</td>
<td>1.90</td>
<td>-0.19</td>
<td>0.41</td>
<td>0.15</td>
<td>0.20</td>
<td>17.31</td>
<td>A</td>
<td>Yahoo.com</td>
</tr>
<tr>
<th>4</th>
<td>Fourth</td>
<td>A</td>
<td>0.24</td>
<td>-3.25</td>
<td>-6.42</td>
<td>-1.51</td>
<td>0.60</td>
<td>-0.01</td>
<td>0.25</td>
<td>-0.02</td>
<td>-15.13</td>
<td>A</td>
<td>MSN.com</td>
</tr>
<tr>
<th>5</th>
<td>First</td>
<td>D</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>5.06</td>
<td>NaN</td>
<td>1.27</td>
<td>-0.56</td>
<td>13.24</td>
<td>A</td>
<td>Google.com</td>
</tr>
</tbody>
</table>

Would like to know how to filter results from a specific (nested, table within table) table heading?

Have been dabbling around with this piece of code, only I could do with some input. Could really do with a follow up working examples altered code snippet if at all possible. Need to figure the filter/search - returning results being limited to a specified table heading ('th/tr' - tags), namely the Title heading and search within ONLY this area, though displaying the whole cells still (Title, Description and Date).Any questions I'll be pleased to help.
var input, table, rows, noMatches, markInstance;
$(document).ready(function init() {
input = document.getElementById('myInput');
noMatches = document.getElementById('noMatches');
table = document.getElementById('myTable');
rows = table.querySelectorAll('tr');
markInstance = new Mark(table);
input.addEventListener('keyup', _.debounce(ContactsearchFX, 250));
});
function ContactsearchFX() {
resetContent();
markInstance.unmark({
done: highlightMatches
});
}
function resetContent() {
$('.noMatchErrorText').remove();
//Remove this line to have a log of searches
//noMatches.textContent = '';
rows.forEach(function(row) {
$(row).removeClass('show');
});
}
function highlightMatches() {
markInstance.mark(input.value, {
each: showRow,
noMatch: onNoMatches,
})
}
function showRow(element) {
//alert(element);
$(element).parents('tr').addClass('show');
$(element).parents('tr').siblings('tr').addClass('show');
//Parents incase of several nestings
}
function onNoMatches(text) {
$('#myInput').after('<p class="noMatchErrorText">No records match: "' + text + '"</p>');
}
.input-wrap {
margin-bottom: 12px;
}
#myInput:invalid~.hints {
display: block;
}
#noMatches:empty,
#noMatches:empty+.hints {
display: none;
}
.style1 tr {
display: none;
}
.style1 .show {
display: table-row;
}
mark {
background: orange;
font-weight: bold;
color: black;
}
.style1 {
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js"></script>
<div class="input-wrap">
<label>
Search Titles:
<input id="myInput" type="text" required
placeholder="Search Titles" />
</label>
</div>
<div class="hintsWrap">
<p id="noMatches"></p>
<p class="hints">
Hints: type "Title1", "Title2", "Title3"...
</p>
</div>
<br />
<br />
<table id="myTable" style="width: 100%" class="style1">
<tr>
<td>
<br />
<br />
<br />
<table style="width: 100%">
<tr>
<th class="style1">Title</th>
<td>title1</td>
</tr>
<tr>
<th class="style1">Description</th>
<td>description1</td>
</tr>
<tr>
<th class="style1">Date</th>
<td>date1</td>
</tr>
</table>
<br />
<table style="width: 100%">
<tr>
<th class="style1">Title</th>
<td>title2</td>
</tr>
<tr>
<th class="style1">Description</th>
<td>description2</td>
</tr>
<tr>
<th class="style1">Date</th>
<td>date2</td>
</tr>
</table>
<br />
<br />
<table style="width: 100%">
<tr>
<th class="style1">Title</th>
<td>title3</td>
</tr>
<tr>
<th class="style1" style="height: 23px">Description</th>
<td style="height: 23px">description3</td>
</tr>
<tr>
<th class="style1">Date</th>
<td>date3</td>
</tr>
</table>
<br />
<br />
<table style="width: 100%">
<tr>
<td>
<table style="width: 100%">
<tr>
<th class="style1">Title</th>
<td>title4</td>
</tr>
<tr>
<th class="style1">Description</th>
<td>description4</td>
</tr>
<tr>
<th class="style1">Date</th>
<td>date4</td>
</tr>
</table>
</td>
</tr>
</table>
<br />
</td>
</tr>
</table>
As continuation from comments above, and since this was something basic that you would like to use, i posted it here.
I added some notes on the code but the essences are:
This is just a really basic approach without any use of libraries.
I play with classes in order to hide the table rows and also to mark the result
Although i leave the part on the script that display: none; the lines of the table, you can manipulate the CSS and delete it from the code.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.querySelectorAll("tbody > tr");
for (i = 0; i < tr.length; i++) { // Loop through all table rows, and hide those who don't match the search query
td = tr[i].getElementsByTagName("td")[0]; // this will search on the Title col. You can change this to search on other cols.
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) { // found
tr[i].style.display = "";
tr[i].classList.add("mark"); // mark result
}
else { // didn't found
tr[i].style.display = "none";
tr[i].classList.remove("mark"); // unmark result
}
}
if (input.value === '') { // case the input is clear
tr[i].classList.remove("mark"); // unmark result
tr[i].style.display = "none";
}
}
}
table {position: relative; min-width: 320px;} /* */
tbody tr {opacity: 0;} /* this will hide the table's info + will show the result under the headers */
tr.mark {opacity: 1;} /* this will show the result row */
/* basic style (markers) to the result row - just for demonstration purpose */
tr.mark td {background: yellow;} /* (second) col */
tr.mark td:first-child {background: blue;} /* first col */
tr.mark td:last-child {background: orange;} /* third col*/
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search Titles..">
<table id="myTable">
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr>
<td>bla bla bla</td>
<td>description1</td>
<td>date1</td>
</tr>
<tr>
<td>yada yada yada</td>
<td>description2</td>
<td>date2</td>
</tr>
<tr>
<td>Another Title</td>
<td>description3</td>
<td>date3</td>
</tr>
</tbody>
</table>
Hope that it is what you searched for, and Enjoy code!
Solution 1. you can play with css selectors to achieve your goal:
#myTable table tr:first-child td mark {
background: orange;
font-weight: bold;
color: black;
}
mark {
background: initial;
}
Solution 2. edit your init function for sibling only titles like this:
$(document).ready(function init() {
input = document.getElementById('myInput');
noMatches = document.getElementById('noMatches');
/************************************************
NOTE :: your last table element doesn't match your template
************************************************/
table = document.querySelectorAll('#myTable table tr:first-child td');
rows = document.querySelectorAll('#myTable table tr');
markInstance = new Mark(table);
input.addEventListener('keyup', _.debounce(ContactsearchFX, 250));
});
Have fun

Javascript delete a table tbody tag

I know I can use the following code to remove rows in vanilla Javascript:
var table = document.getElementById('table');
function deleteRow () {
table.deleteRow(1);
};
table { background: #ccc; width: 100%; }
table thead { background: #333; color: #fff; }
table tbody { background: magenta; color: #fff; }
<button onclick="deleteRow()">Delete Row</button>
<table id="table">
<thead>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
</thead>
<tbody>
<tr>
<td>lorem</td>
<td>ipsum</td>
</tr>
</tbody>
<tbody>
<tr>
<td>lorem</td>
<td>ipsum</td>
</tr>
</tbody>
</table>
But this code leaves an empty tbody tag behing. JS has methods for removing thead and tfoot elements, but it seems it's missing a deleteTbody one.
How am I supposed to remove a tbody and all it's contents by using pure javascript only? No jQuery, please!
Try using:
var tbl = document.getElementById("table"); // Get the table
tbl.removeChild(tbl.getElementsByTagName("tbody")[0]); // Remove first instance of body
https://jsfiddle.net/Ltdr2qv4/1/
Use querySelectorAll() to iterate through all TBODY elements, then remove those that have no children:
var table = document.getElementById('table');
function deleteRow() {
table.deleteRow(1);
var tb = document.querySelectorAll('tbody');
for (var i = 0; i < tb.length; i++) {
if (tb[i].children.length === 0) {
tb[i].parentNode.removeChild(tb[i]);
}
}
};
table {
background: #ccc;
width: 100%;
}
table thead {
background: #333;
color: #fff;
}
table tbody {
background: magenta;
color: #fff;
}
<button onclick="deleteRow()">Delete Row</button>
<table id="table">
<thead>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
</thead>
<tbody>
<tr>
<td>lorem</td>
<td>ipsum</td>
</tr>
</tbody>
<tbody>
<tr>
<td>lorem</td>
<td>ipsum</td>
</tr>
</tbody>
</table>
If you want to remove the tbody tag, you could select the row itself rather than the table, then use the removeChild function.
var table = document.getElementById('table');
var row = document.getElementsByTagName('tbody')[0];
function deleteRow () {
row.parentNode.removeChild(row);
};
There is no deleteTbody but there is removeChild:
var parent = document.getElementById("parent-id");
var child = document.getElementById("child-id");
parent.removeChild(child);
I hope it will help you. I am sorry. It is too late to answer.
tbody-data is tbody's id value.
$("#tbody-data tr").remove();

Categories