How to dynamically seach a mysql table client side with javascript - javascript

I know how to search a table with static data. I'd like to modify my script to search the table with dynamic data but I'm unsure how to do this. I'm opened to use Php but since the javascript I have written already works, I'd like help with making the script dynamic.
script
<script>
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("searchData");
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) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
</script>
dynamic table
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<table id="myTable">
<tr>
<th>ID</th>
<th>Name</th>
<th>Description</th>
<th>Type</th>
<th>Address</th>
<th>Country</th>
<th>Time Zone</th>
</tr>
<?php while($company=mysqli_fetch_array($result)){ ?>
<tr>
<td data-th="ID"><?=$company['id'];?></a></td>
<td data-th="Name"><?=$company['title'];?></td>
<td data-th="Description"><?=$company['description'];?></td>
<td data-th="Type"><?=$company['type'];?></td>
<td data-th="Address"><?=$company['address'];?></td>
<td data-th="Country"><?=$company['country'];?></td>
<td data-th="Time Zone"><?=$company['timezone'];?></td>
</tr>
<?php };?>
</table>

Related

Hide rows in a column with vanilla JavaScript according to text content

I have a table like this:
<table id="mytable" class="table">
<tr>
<th>Author</th>
<th>Title</th>
<th>Year</th>
<th>Digitised</th>
</tr>
</table
I'd like to have a button which, when clicked, hides or shows the rows which contain a 'Yes' (or a check, or a specific element) in the 'Digitised' column.
This is the JavaScript I've come up so far
let table, tr, td, i, t;
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for(t=0; t<tds.length; t1++) {
let td = tds[t][3];
if (td) {
if (td.innerHTML.indexOf('Yes') > -1) {
tr[i].style.display = 'none';
}
}
}
}
This doesn't work. How can I achieve what I want?
You have the wrong id in your Javascript, the table id is "mytable" (in lower case) but your js code is trying to find "myTable" which is camel case,
Anyways here is a sample of code that do what you need:
var areRowsDisplayed = true
function toggleRows() {
const rows = document.querySelectorAll('#mytable > tbody > tr')
Array.prototype.slice.call(rows).forEach(row => {
let dataField = row.querySelectorAll('td')[3]
if(dataField.innerText.toLowerCase() == 'yes') {
row.style.display = !areRowsDisplayed ? '': 'none'
}
})
areRowsDisplayed = !areRowsDisplayed
}
document.querySelector('#toggleRows').addEventListener('click',e => toggleRows())
<button id='toggleRows'>Hide/Show</button>
<table id="mytable" class="table">
<thead>
<tr>
<th>Author</th>
<th>Title</th>
<th>Year</th>
<th>Digitised</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pin Pon</td>
<td>The new song</td>
<td>1991</td>
<td>No</td>
</tr>
<tr>
<td>Cloudies</td>
<td>Fly with me</td>
<td>1986</td>
<td>Yes</td>
</tr>
</tbody>
</table>
This basically has a button that run a javascript function, and within that function we loop into each table row and hide/show the rows that meet certain criteria
I have added a global variable to check what is the current status (if the rows are hidden already) only for this sample purposes, you must be storing that in some context depending on the framework you are using

How do I get my search function work to filter searched items from table?

I've made a table filled with data retreived from a JSON file. Now I'm trying to make a searchbar that filters searched items and only shows the table rows of the items searched for. The code of the function I'm using now is:
//Search function
function searchTable() {
var input, filter, found, table, tr, td, i, j;
input = document.getElementsByClassName("searchBar");
filter = input.value.toUpperCase();
table = document.getElementById("productTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td");
for (j = 0; j < td.length; j++) {
if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
found = true;
}
}
if (found) {
tr[i].style.display = "";
found = false;
} else {
tr[i].style.display = "none";
}
}
}
});
This is the HTML of the table I'm trying to apply the filter to:
<input class="form-control searchBar" type="text" name="search" placeholder="search">
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Product Name</th>
<th scope="col">Free Stock</th>
<th scope="col">Price</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody id="productTable">
<tr>
</tr>
</tbody>
</table>
Here is the best solution for searching inside HTML table while covering all of the table, (all td, tr in the table), pure javascript and as short as possible:
<body style="background:red;">
<input id='myInput' onkeyup='searchTable()' type='text'>
<table id='myTable'>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Product Name</th>
<th scope="col">Free Stock</th>
<th scope="col">Price</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Green</td>
<td>Lorem</td>
<td>Ipsum</td>
<td>button</td>
</tr>
<tr>
<td>2</td>
<td>Green</td>
<td>elit</td>
<td>Mumbai</td>
<td>button</td>
</tr>
<tr>
<td>3</td>
<td>Green</td>
<td>sud</td>
<td>Dummy</td>
<td>button</td>
</tr>
</tbody>
</table>
<script>
function searchTable() {
var input, filter, found, table, tr, td, i, j;
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");
for (j = 0; j < td.length; j++) {
if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
found = true;
}
}
if (found) {
tr[i].style.display = "";
found = false;
} else {
tr[i].style.display = "none";
}
}
}
</script>
</body>
The problem is getElementsByClassName does not return an element. Instead, it returns a NodeList. If you only have a single element with class=“searchBar” then you would reference as:
input = document.getElementsByClassName("searchBar")[0];
Updated script with your existing ID is
function searchTable() {
var input, filter, found, table, tr, td, i, j;
input = document.getElementsByClassName("searchBar")[0];
filter = input.value.toUpperCase();
table = document.getElementById("productTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td");
for (j = 0; j < td.length; j++) {
if (td[j].innerHTML.toUpperCase().indexOf(filter) > -1) {
found = true;
}
}
if (found) {
tr[i].style.display = "";
found = false;
} else {
tr[i].style.display = "none";
}
}
}
However, if you are only going to have one of these elements, I suggest giving it an id and use getElementById and then you will actually get an element.

Filter Table with CSS and JS

I have a dynamic table that I am displaying in the front end like this:
<table id ="tblRE">
<tr class="row">
<th ng-repeat="column in cols_re">{{column}}</th>
</tr>
<tr ng-repeat="row in data['dict_re']">
<td ng-repeat="column in cols_re">{{row[column]}}</td>
</tr>
</table>
I want to put a filter on one of the columns named OUT(my 2nd column from the table).
If I would have a fix column name I would do like this:
<tr class="row">
<td class="head" ng-click="sortData='OUT';sortOrder=!sortOrder"> OUT</td>
</tr>
<tr ng-repeat="item in data.table_df| orderBy:sortData:sortOrder | filter:filter ">
<td>{{ item.OUT}}</td>
</tr>
Is there an option on how I can put the filter with my initial option?
I also tried to add a search button which kind of works only for the first column. I want to be able to filter also on the second column.
The code for the search button:
js:
function searchre() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("tblRE");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
and in HTML:
<input class="myInput" type="text" id="myInput" onkeyup="searchre()" placeholder="Search.." title="Type in a name">
Any idea on how I can filter on the first and 2nd column?

How to filter/search columns in HTML table?

I have followed this link on how to create/filter search a table. But I want to filter search for each column in my own table. Currently, it only searches for the First Name column. How can I do this?
This is the code:
myHTML:
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th> First Name </th>
<th> Last Name </th>
<th> Age </th>
<th> Language </th>
</tr>
<tr>
<td>John</td>
<td>Kole</td>
<td>18</td>
<td>English</td>
</tr>
<tr>
<td>Pearl</td>
<td>Shine</td>
<td>50</td>
<td>Hindi</td>
</tr>
<tr>
<td>Jacob</td>
<td>Pool</td>
<td>22</td>
<td>Arabic</td>
</tr>
<tr>
<td>David</td>
<td>Struff</td>
<td>30</td>
<td>German</td>
</tr>
</table>
<script>
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";
}
}
}
}
</script>
How can I filter all columns for searching? Currently, it searches the First Name column only.
Check each nodes of the table row instead of just checking tr[i].getElementsByTagName("td")[0]. The zeroth node corresponds to first name field, that's why the search result restricts to the first name field only.. Search for all the nodes instead.
Leave the tr node with class name of header while making the row hidden.
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];
alltags = tr[i].getElementsByTagName("td");
isFound = false;
for(j=0; j< alltags.length; j++) {
td = alltags[j];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
j = alltags.length;
isFound = true;
}
}
}
if(!isFound && tr[i].className !== "header") {
tr[i].style.display = "none";
}
}
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th> First Name </th>
<th> Last Name </th>
<th> Age </th>
<th> Language </th>
</tr>
<tr>
<td>John</td>
<td>Kole</td>
<td>18</td>
<td>English</td>
</tr>
<tr>
<td>Pearl</td>
<td>Shine</td>
<td>50</td>
<td>Hindi</td>
</tr>
<tr>
<td>Jacob</td>
<td>Pool</td>
<td>22</td>
<td>Arabic</td>
</tr>
<tr>
<td>David</td>
<td>Struff</td>
<td>30</td>
<td>German</td>
</tr>
</table>
Hope this is what you are looking for.
This line:
td = tr[i].getElementsByTagName("td")[0];
gets the first td which is the content for the first column in the table meaning the FirstName column.
Do a loop on all td tags instead of getting only the first one and you'll get the functionality you need.
Get all table rows. Loop through these rows. Put all the innerText from the <td>s in each row together into a string. Check the first occurrence of the search value in the string. If the value is not found, hide the row with display: none else show the row with display: table-row.
Example
const id = "myTable";
const selector = `#${id} tr:not(.header)`;
// Get all rows
const trs = document.querySelectorAll(selector);
function myFunction(event) {
let search = event.target.value.toLowerCase();
trs.forEach((tr) => {
// Get all cells in a row
let tds = tr.querySelectorAll("td");
// String that contains all td textContent from a row
let str = Array.from(tds).map((td) => {
return td.textContent.toLowerCase();
}).join("");
tr.style.display = (str.indexOf(search) > -1) ? "table-row" : "none";
});
}
<input type="text" id="myInput" onkeyup="myFunction(event)" placeholder="Search for names.." title="Type in a name">
<table id="myTable">
<tr class="header">
<th> First Name </th>
<th> Last Name </th>
<th> Age </th>
<th> Language </th>
</tr>
<tr>
<td>John</td>
<td>Kole</td>
<td>18</td>
<td>English</td>
</tr>
<tr>
<td>Pearl</td>
<td>Shine</td>
<td>50</td>
<td>Hindi</td>
</tr>
<tr>
<td>Jacob</td>
<td>Pool</td>
<td>22</td>
<td>Arabic</td>
</tr>
<tr>
<td>David</td>
<td>Struff</td>
<td>30</td>
<td>German</td>
</tr>
</table>

I'm trying to make a function in JS to search the <td> tags in an HTML table but it doesn't work if I use any <th></th> tags in it

EDIT: Nevermind, I just fixed my problem by making the header a separate table to hold all of my tags
So I have a HTML table and I want to have a search bar to search the table because it's pretty large. I tried copying the code from this W3 schools tutorial (https://www.w3schools.com/howto/howto_js_filter_lists.asp) and I got it modified and working for the table, but only if I don't use any rows that include tags.
Here's my currently working code (I commented out the code segment that was giving me trouble):
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myUL" class="BuyBooksTable">
<!--<tr>
<th colspan="3">Books</th>
</tr>
<tr>
<th>Item</th>
<th>Price</th>
<th>Purchase Item</th>
</tr> -->
<div id="myULSmaller">
<tr>
<td>Alice</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Bob</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Carol</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
</div>
</table>
<script>
function myFunction() {
// Declare variables
var input, filter, ul, li, a, i, txtValue;
input = document.getElementById('myInput');
filter = input.value.toUpperCase();
ul = document.getElementById("myUL");
li = ul.getElementsByTagName('tr');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("td")[0];
txtValue = a.textContent || a.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
</script>
Using querySelectorAll.
Also, you can use <tbody> rather than to have a div inside your table.
function myFunction(e) {
let searchTerm = e.value.toLocaleLowerCase();
var trs = document.querySelectorAll('table tbody tr');
[].forEach.call(trs, function(tr) { // all trs
[].forEach.call(tr.children, function(td) { // all tds
if (td.getAttribute('search')) { // check if the td needs to be considers for search criteria
if (td.innerText.toLocaleLowerCase().includes(searchTerm)) {
tr.style.display = "";
} else {
tr.style.display = "none";
}
}
});
});
}
<input type="text" id="myInput" onkeyup="myFunction(this)" placeholder="Search for names.." title="Type in a name">
<table id="myUL" class="BuyBooksTable">
<tr>
<th colspan="3">Books</th>
</tr>
<tr>
<th>Item</th>
<th>Price</th>
<th>Purchase Item</th>
</tr>
<tbody>
<tr>
<td search="true">Alice</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td search="true">Bob</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td search="true">Carol</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
</tbody>
</table>
You need to check that the value a in the line a = li[i].getElementsByTagName("td")[0]; exists. Try this:
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names.." title="Type in a name">
<table id="myUL" class="BuyBooksTable">
<tr>
<th colspan="3">Books</th>
</tr>
<tr>
<th>Item</th>
<th>Price</th>
<th>Purchase Item</th>
</tr>
<div id="myULSmaller">
<tr>
<td>Alice</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Bob</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Carol</td>
<td>Price</td>
<td>Purchase Item</td>
</tr>
</div>
</table>
<script>
function myFunction() {
// Declare variables
var input, filter, ul, li, a, i, txtValue;
input = document.getElementById('myInput');
filter = input.value.toUpperCase();
ul = document.getElementById("myUL");
li = ul.getElementsByTagName('tr');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("td")[0];
//If a doesn't exist, carry on looping:
if (!a) {
continue;
}
txtValue = a.textContent || a.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
</script>
just use :nth-child(n+3) selector
document.querySelectorAll('#myUL tr:nth-child(n+3)')
or edit your code like
...
//ul = document.getElementById("myUL");
ul = document.getElementById("myULSmaller");
...
or use this
let trs = document.querySelectorAll('#myUL tr:nth-child(n+3)');
function myFunction() {
let filter = this.value.trim().toLowerCase();
let emptyStr = filter.length == 0;
trs.forEach(function(el) {
el.style.display = emptyStr || el.textContent.toLowerCase().includes(filter)?"":"none";
});
}
Nidhins answer is great but if you need to search all columns you need to modify it.
I include a variable to track if any cell in the row matches. Highlite that cell and display the row
//Set event listener
document.getElementById("myInput").addEventListener("keyup",function(){
var normalisedSearch = this.value.toLocaleLowerCase();
//Grab the search tr in the table body
var searchTrs = document.querySelectorAll("#myUL>tbody>tr");
//iterate the cells in the tr
[].forEach.call(searchTrs,function(tr){
var visible = false;
//iterate the cells in the row
var searchTds = tr.querySelectorAll("td");
[].forEach.call(searchTds, function(td){
if(td.innerText.toLocaleLowerCase().includes(normalisedSearch)){
visible = true;
td.style.backgroundColor = normalisedSearch !== "" ? "#CCC" : "";
}else{
td.style.backgroundColor = "";
}
});
//Sit vidibility of the row
tr.style.display = visible ? "" : "none";
});
});
<input type="text" id="myInput" placeholder="Search for names.." title="Type in a name">
<table id="myUL" class="BuyBooksTable">
<tr>
<th colspan="3">Books</th>
</tr>
<tr>
<th>Item</th>
<th>Price</th>
<th>Purchase Item</th>
</tr>
<tbody>
<tr>
<td>Alice</td>
<td>20</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Bob</td>
<td>15</td>
<td>Purchase Item</td>
</tr>
<tr>
<td>Carol</td>
<td>2</td>
<td>Purchase Item</td>
</tr>
</tbody>
</table>

Categories

Resources