search result should appear after 3 characters - javascript

I have a problem showing the search result after 3 characters, it shows the result directly after the first character I type. I want it to show the result only after typing 3 characters at least. here is the code I used in HTML, CSS and Javascript
function myFunction() {
var input, filter, table, tr, td, i;
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")[1];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
#myInput {
width: 100%; /* Full-width */
font-size: 16px; /* Increase font-size */
padding: 12px 20px 12px 40px; /* Add some padding */
border: 1px solid #ddd; /* Add a grey border */
margin-bottom: 12px; /* Add some space below the input */
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Search</title>
<link rel="stylesheet" href="./assets/css/style.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<h1>Search for employees</h1>
<input class="container" type="text" id="myInput"
onkeyup="myFunction()" placeholder="search...">
<div class="table-responsive{-sm|-md|-lg|-xl}">
<table class="table" id="myTable">
<tr class="header">
<th>Picture</th>
<th>Name</th>
<th>Age</th>
<th>Active</th>
<th>Email</th>
<th>Phone</th>
<th>Company</th>
<th>Balance</th>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Smith Junior</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Linda Lindo</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Victoria Smith</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Jason Abraham</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
<tr>
<td><img src="http://placehold.it/32x32" alt=""></td>
<td>Ahmed Raquent</td>
<td>24</td>
<td>true</td>
<td>asd#ast.com</td>
<td>+8983287687</td>
<td>Company</td>
<td>$1000</td>
</tr>
</table>
</div>
</div>
</body>
<script src="./assets/js/main.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.js"></script>
</html>
can you help me with the code ? I would be more than thankful

Check for length of input , and when input length is less than 3 , dont do anything
function myFunction() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
if(filter.length < 3) {
return;
}
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[1];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}

I will suggest two things here one is please use oninput event for capturing value change (https://www.w3schools.com/jsref/event_oninput.asp) and second please wait until value length is three, as suggested in above answer.
`https://jsfiddle.net/poojanbedi/d5q3op0j/`

Related

HTML table filter with unique values only

I have a 300x11(rowXcolumn) html table that I wanted to filter exactly like Excel or Google Sheets's filter. However, after searching a bit I found out the following code below in a website. This works as I wanted but it has one major problem. It shows same value multiple times. For example in the 2nd column, there are 2 values same "Apple" and 2 whitespaces . In the current code, it displays Apple twice and whitespace twice. However, I want it should show the same values only once. For example, it will show "Apple" only once, and if I select apple it will filter both rows containing apple.
Thank you very much for your help.
index.html
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#2.0.3" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<table class="grid">
<thead>
<tr>
<td index=0>Name
<div class="filter"></div>
</td>
<td index=1>Address
<div class="filter"></div>
</td>
<td index=2>City
<div class="filter"></div>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>first</td>
<td>first add</td>
<td>SDF dfd</td>
</tr>
<tr>
<td>second</td>
<td></td>
<td>SDF dfd</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF dfd</td>
</tr>
<tr>
<td>third</td>
<td></td>
<td>SDF hello</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF hello</td>
</tr>
</tbody>
</table>
</body>
</html>
script.js
$(document).ready(function(){
$(".grid thead td").click(function(){
showFilterOption(this);
});
});
var arrayMap = {};
function showFilterOption(tdObject){
var filterGrid = $(tdObject).find(".filter");
if (filterGrid.is(":visible")){
filterGrid.hide();
return;
}
$(".filter").hide();
var index = 0;
filterGrid.empty();
var allSelected = true;
filterGrid.append('<div><input id="all" type="checkbox" checked>Select All</div>');
var $rows = $(tdObject).parents("table").find("tbody tr");
$rows.each(function(ind, ele){
var currentTd = $(ele).children()[$(tdObject).attr("index")];
var div = document.createElement("div");
div.classList.add("grid-item")
var str = $(ele).is(":visible") ? 'checked' : '';
if ($(ele).is(":hidden")){
allSelected = false;
}
div.innerHTML = '<input type="checkbox" '+str+' >'+currentTd.innerHTML;
filterGrid.append(div);
arrayMap[index] = ele;
index++;
});
if (!allSelected){
filterGrid.find("#all").removeAttr("checked");
}
filterGrid.append('<div><input id="close" type="button" value="Close"/><input id="ok" type="button" value="Ok"/></div>');
filterGrid.show();
var $closeBtn = filterGrid.find("#close");
var $okBtn = filterGrid.find("#ok");
var $checkElems = filterGrid.find("input[type='checkbox']");
var $gridItems = filterGrid.find(".grid-item");
var $all = filterGrid.find("#all");
$closeBtn.click(function(){
filterGrid.hide();
return false;
});
$okBtn.click(function(){
filterGrid.find(".grid-item").each(function(ind,ele){
if ($(ele).find("input").is(":checked")){
$(arrayMap[ind]).show();
}else{
$(arrayMap[ind]).hide();
}
});
filterGrid.hide();
return false;
});
$checkElems.click(function(event){
event.stopPropagation();
});
$gridItems.click(function(event){
var chk = $(this).find("input[type='checkbox']");
$(chk).prop("checked",!$(chk).is(":checked"));
});
$all.change(function(){
var chked = $(this).is(":checked");
filterGrid.find(".grid-item [type='checkbox']").prop("checked",chked);
})
filterGrid.click(function(event){
event.stopPropagation();
});
return filterGrid;
}
style.css
table thead tr td{
background-color : gray;
min-width : 100px;
position: relative;
}
.filter{
position:absolute;
border: solid 1px;
top : 20px;
background-color : white;
width:100px;
right:0;
display:none;
}
Maybe someone else will fix that limited JS for you but otherwise use DataTables. It has all you want with extensive documentation, and it's a popular plugin so it's not hard to find any answers to questions you might have about it. Here's an example with everything you desired in your post:
/* Range Search - https://datatables.net/examples/plug-ins/range_filtering.html */
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var min = parseInt($('#min').val(), 10);
var max = parseInt($('#max').val(), 10);
var age = parseFloat(data[3]) || 0;
if (
(isNaN(min) && isNaN(max)) ||
(isNaN(min) && age <= max) ||
(min <= age && isNaN(max)) ||
(min <= age && age <= max)
) {
return true;
}
return false;
});
$(document).ready(function() {
/* Init dataTable - Options[paging: off, ordering: off, search input: off] */
var table = $('#table').DataTable({
"paging": false,
"ordering": false,
dom: 'lrt'
});
/* Column Filters */
$(".filterhead").each(function(i) {
if (i != 4 && i != 5) {
var select = $('<select><option value="">Filter</option></select>')
.appendTo($(this).empty())
.on('change', function() {
var term = $(this).val();
table.column(i).search(term, false, false).draw();
});
table.column(i).data().unique().sort().each(function(d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
});
} else {
$(this).empty();
}
});
/* Range Search -> Input Listener */
$('#min, #max').keyup(function() {
table.draw();
});
});
.container {
max-width: 80%;
margin: 0 auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.13.1/datatables.min.css" />
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.13.1/datatables.min.js"></script>
<body>
<div class="container">
<input type="text" id="min" name="min" placeholder="Min Number">
<input type="text" id="max" name="max" placeholder="Max number">
<table id="table" class="display">
<thead>
<tr>
<th class="filterhead">Name</th>
<th class="filterhead">Address</th>
<th class="filterhead">City</th>
<th class="filterhead">Number</th>
</tr>
<tr>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tr>
<td>first</td>
<td>first add</td>
<td>SDF dfd</td>
<td>18</td>
</tr>
<tr>
<td>second</td>
<td>as</td>
<td>SDF dfd</td>
<td>50</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF dfd</td>
<td>2</td>
</tr>
<tr>
<td>third</td>
<td>as</td>
<td>SDF hello</td>
<td>25</td>
</tr>
<tr>
<td>third</td>
<td>Apple</td>
<td>SDF hello</td>
<td>10</td>
</tr>
</tbody>
</table>
</div>
</body>

Javascript Access to Only Header, Body or Footer Rows One at a Time

I have a need to traverse (using javascript) the sections of each table's rows individually. Meaning that I need to traverse the THEAD rows first, then the TBODY rows, and finally the TFOOT rows.
What I need to do requires far more complexity than just coloring the boxes, but for the purpose of this example i'm just trying to color the thead rows red, the tbody rows green and the tfoot rows yellow. If I can get these loops working for the rows for each section I can then take over from there to do the rest of the coding.
I've tried the below but it does not work (it tells me "rows is not defined"). Could someone fix the ColorBoxes() function code to get this to work? Just please do not give me CSS answers here because that does not solve the problem - I need to traverse through the rows of each section. Thanks!
<!DOCTYPE html>
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
}
</style>
<script language='javascript'>
function ColorBoxes()
{
var tbl = document.getElementById('MyTable');
for (var nRow = 0; nRow < tbl.tHead[0].rows; nRow++)
{
tbl.tHead[0].row[nRow].style.backgroundColor = 'red';
}
for (var nRow = 0; nRow < tbl.tBody[0].rows; nRow++)
{
tbl.tBody[0].row[nRow].style.backgroundColor = 'green';
}
for (var nRow = 0; nRow < tbl.tFoot[0].rows; nRow++)
{
tbl.tFoot[0].row[nRow].style.backgroundColor = 'yellow';
}
}
</script>
</head>
<body onLoad='ColorBoxes()'>
<h1>The thead, tbody, and tfoot elements</h1>
<table id='MyTable'>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
</body>
</html>
You could do something like this. Using explicit selectors might help you reason with your loops a little better.
function ColorBoxes() {
const table = document.querySelector('#MyTable')
const thead_tr = table.querySelectorAll('thead tr')
const tbody_tr = table.querySelectorAll('tbody tr')
const tfoot_tr = table.querySelectorAll('tfoot tr')
thead_tr.forEach(row => {
row.style.backgroundColor = 'red'
})
tbody_tr.forEach(row => {
row.style.backgroundColor = 'green'
})
tfoot_tr.forEach(row => {
row.style.backgroundColor = 'yellow'
})
}
ColorBoxes()
<!DOCTYPE html>
<html>
<head>
<style>
table,
th,
td {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>The thead, tbody, and tfoot elements</h1>
<table id='MyTable'>
<thead>
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<th>Name</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$100</td>
</tr>
<tr>
<td>February</td>
<td>$80</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Sum</td>
<td>$180</td>
</tr>
</tfoot>
</table>
</body>
</html>

Javascript Filtering by multiple columns

Borrowing code from the post below I am able to filter on 2 columns using the || (Or) operator.
However, I'd like to be able to filter using the && (And) operator.
I have been unsuccessful in my multiple attempts. I could use some help.
Filtering table multiple columns
function myFunction() {
var input0, input1, filter0, filter1, table, tr, td, cell, i, j;
document.getElementById("myInput0").value = 'Female';
document.getElementById("myInput1").value = 'Engineering';
input0 = document.getElementById("myInput0");
input1 = document.getElementById("myInput1");
filter0 = input0.value.toUpperCase();
filter1 = input1.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 1; i < tr.length; i++) {
// Hide the row initially.
tr[i].style.display = "none";
td = tr[i].getElementsByTagName("td");
for (var j = 0; j < td.length; j++) {
cell = tr[i].getElementsByTagName("td")[j];
if (cell) {
if (cell.textContent.toUpperCase().indexOf(filter0)>-1 ||
cell.textContent.toUpperCase().indexOf(filter1)>-1) {
tr[i].style.display = "";
break;
}
}
}
}
}
<body>
<input type="text" id="myInput0">
<input type="text" id="myInput1">
<input type='button' onclick='myFunction()' value='click me' />
<table id="myTable">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Gender</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>Anja</td>
<td>Ravendale</td>
<td>Female</td>
<td>Engineering</td>
</tr>
<tr>
<td>Thomas</td>
<td>Dubois</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Deidre</td>
<td>Masters</td>
<td>Female</td>
<td>Sales</td>
</tr>
<tr>
<td>Sean</td>
<td>Franken</td>
<td>Male</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
</body>
For each cell, you can check each filter separately, then only change the DOM for rows where all filter conditions are met.
(This example uses a restructured version of your code.)
document.getElementById("myInput0").value = 'Female';
document.getElementById("myInput1").value = 'Engineering';
const
input0 = document.getElementById("myInput0"),
input1 = document.getElementById("myInput1"),
table = document.getElementById("myTable"),
rows = table.getElementsByTagName("tr");
function myFunction() {
filter0 = input0.value.toUpperCase(),
filter1 = input1.value.toUpperCase();
for (let row of rows) {
row.classList.add("hidden");
const cells = row.getElementsByTagName("td");
let
filter0met = false,
filter1met = false;
for (let cell of cells) {
if (cell.textContent.toUpperCase().includes(filter0)) {
filter0met = true;
}
if (cell.textContent.toUpperCase().includes(filter1)) {
filter1met = true;
}
}
if (filter0met && filter1met) {
row.classList.remove("hidden");
}
}
}
.hidden {
display: none;
}
<body>
<input type="text" id="myInput0"><input type="text" id="myInput1"><input type='button' onclick='myFunction()' value='click me' />
<table id="myTable">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Gender</th>
<th>Department</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>Female</td>
<td>Service</td>
</tr>
<tr>
<td>Anja</td>
<td>Ravendale</td>
<td>Female</td>
<td>Engineering</td>
</tr>
<tr>
<td>Thomas</td>
<td>Dubois</td>
<td>Male</td>
<td>Sales</td>
</tr>
<tr>
<td>Deidre</td>
<td>Masters</td>
<td>Female</td>
<td>Sales</td>
</tr>
<tr>
<td>Sean</td>
<td>Franken</td>
<td>Male</td>
<td>Engineering</td>
</tr>
</tbody>
</table>
</body>
After much trial and error for I was able to put together some JQuery that will dynamically search the first input, and then search those results for the second input. Note, I am using SP2016. While I've included it here in my post, I could not get the call to "https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" to work. I found downloading and storing the file on my SharePoint site worked. For my requirement I wanted to display my list with grouped rows so I'm using a function to collapse the groups on load. The caveat is the groups in listview have to be configured as expanded.
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!DOCTYPE html>
<html>
<head>
<SCRIPT type="text/javascript"src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></SCRIPT>
<script>
//If rows are not grouped, remove this function
$(window).load(function () {
$(".ms-commentcollapse-icon").click();
});
$(document).ready(function() {
$("#myInput").on("keyup", function() {
var value = this.value.toLowerCase();
//If rows are not grouped, remove this line
$(".ms-commentexpand-icon").click();
$('.ms-listviewtable > tbody > tr').addClass('myInputMismatch').filter(function() {
return this.innerHTML.toLowerCase().indexOf(value) > -1;
}).removeClass('myInputMismatch');
});
$("#myInput1").on("keyup", function() {
var value = this.value.toLowerCase();
$('.ms-listviewtable > tbody > tr').addClass('myInput1Mismatch').filter(function() {
return this.innerHTML.toLowerCase().indexOf(value) > -1;
}).removeClass('myInput1Mismatch');
});
});
</script>
<style>
.myInputMismatch, .myInput1Mismatch { display: none; }
</style></head>
<input id="myInput" type="text" Placeholder="Search here 1st..."><input id="myInput1" type="text" Placeholder="Search here 2nd...">

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>

Mechanism binding click event handler to massive <td> elements

I'm writing a big HTML table which has same-data-coloring feature by user's double-clicking on a certain cell, the table has over 8000 cells and cells will be increased.
At this point, I thought it could be a burdened working to a web-browser.
Yes, I want to know the in-depth mechanism and burdening degree of attaching event-handler to massive <td> elements.
The code:
<script>
var otable = document.getElementById("htbl_drawresult");
var irIndex = 0;
var icIndex = 0;
var sintxt = "";
for(var i = 1; i < otable.rows.length; i++)
{
for(var j = 0; j < otable.rows[i].cells.length; j++)
{
otable.rows[i].cells[j].ondblclick = function()
{
irIndex = this.parentElement.rowIndex;
icIndex = this.cellIndex+1;
sintxt = this.innerText;
f_colorcell(sintxt, otable);
};
}
}
function f_colorcell(stxt, otbl){
var irow = otbl.rows.length;
var icol = otbl.rows[1].cells.length;
var i,j=0;
for(i=1; i<irow; i++)
{
for(j=0; j<icol; j++)
{
if (otbl.rows[i].cells[j].innerText == stxt){
otbl.rows[i].cells[j].style.background=\"red\";
}
}
}
}
</script>
Just summarising #C.RaysOfTheSun's answer:
Yes, it would be burdensome to attach an event each on every cell of the table.
However, you could structure your HTML in such a way that the cells (TDs) can each be uniquely identified. And when events propagate from a target to an ancestor (TABLE element for instance) where a listener is *commonly* attached, it's simple to determine the actual target in the listener.
document.addEventListener("DOMContentLoaded", main, false);
function main() {
var table = document.getElementsByTagName("TABLE")[0];
table.addEventListener("dblclick", handleDoubleClickOnTable, false);
}
function handleDoubleClickOnTable( /* event => */ e) {
var target = e.target;
var row, column;
var rowNumber, columnNumber;
if ("TD" !== target.tagName) {
return;
}
row = target.parentNode;
column = target;
rowNumber = row.dataset.rowNumber;
columnNumber = column.dataset.columnNumber;
alert(`You clicked on ( row[ ${ rowNumber } ], column[ ${ columnNumber } ] )`);
}
* {
font-family: monospace;
box-sizing: border-box;
}
table {
width: 100%;
margin-bottom: 1rem;
background-color: transparent;
border-collapse: collapse;
}
td {
vertical-align: bottom;
border-bottom: 2px solid #dee2e6;
border-top: 1px solid #dee2e6;
padding: 2rem;
}
<!-- Sample 3 x 3 table -->
<table>
<tr data-row-number="1">
<td data-column-number="1">( 1, 1 )</td>
<td data-column-number="2">( 1, 2 )</td>
<td data-column-number="3">( 1, 3 )</td>
</tr>
<tr data-row-number="2">
<td data-column-number="1">( 2, 1 )</td>
<td data-column-number="2">( 2, 2 )</td>
<td data-column-number="3">( 2, 3 )</td>
</tr>
<tr data-row-number="3">
<td data-column-number="1">( 3, 1 )</td>
<td data-column-number="2">( 3, 2 )</td>
<td data-column-number="3">( 3, 3 )</td>
</tr>
</table>
If you're talking about assigning an event handler for the cells (<td>) inside your table, you can do it in two ways:
1. Event Propagation
A shorter and much simpler way of doing it. You can assign an event handler to the parent (the <table> element itself) and everything inside it will have the event handler as well. Simply put, what the parent gets, the child will also get.
Recommended if you don't need a specific thing to happen when a given element is clicked. Although, you can always narrow things down by utilizing Event.Target.
In the example below, I have assigned a click event listener to the table (parent) so that when you click on anything inside it, an alert saying "You clicked on a cell and it had the value of [cell value]" will show up
Here's a working example for event propagation.
window.onload = ()=>{
// get our table
let tb = document.getElementById('main-table');
// assign a click event to it
tb.addEventListener('click', (e)=>{
alert(`You clciked on a cell and it had the value of ${e.target.innerHTML}`)
})
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="main-table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
</tr>
</tbody>
</table>
2. Manually assigning a specific event handler to each element
You can always set an event handler for each cell (<td>) specifically by grabbing them using JavaScript's built-in functions (i.e. querySelector, querySelectorAll, getElementById, etc...) then assigning a function to be called on a specific event using addEventListener
Not recommended for a large collection of elements.
You can play around with the snippet below here :)
window.onload = ()=>{
// get our table
let table = document.getElementById('main-table');
// get all the cells in the table element above
let tableCells = table.querySelectorAll('td');
// assign an event listener to each cell <td> element inside that table specifically
for(let i = 0; i < tableCells.length; i++){
tableCells[i].addEventListener('click', function(e){
alert(`You clicked on cell index ${i} and it had the value of ${this.innerHTML}`);
})
}
}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="main-table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
</tr>
</tbody>
</table>
:)
If you want to add click event listeners, you can use jQuery. You can use this for any HTML element.
$("#button").click(function() {
$("#result").css("background-color", "yellow");
});
$("#button").dblclick(function() {
$("#result").css("background-color", "red");
});
body {
font-family: Arial, sans-serif;
}
td {
width: 20px;
height: 20px;
text-align: center;
margin: 0;
border: .5px solid black;
}
#button {
background-color: white;
}
#result {
background-color: blue;
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
If you click the <code>div</code> once, the square will turn yellow.<br>
If you double click the <code>div</code>, the square will turn red.<br>
CM = Click Me
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td>6</td>
<td>7</td>
<td id="button">CM</td>
<td>9</td>
<td>10</td>
</tr>
<tr>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
</tr>
</table>
<div id="result"></div>

Categories

Resources