A table by specific columns content - javascript

I have a table that should eventually have 5 columns which I want to be able to sort though only the value of one column, "Name". This is what my function looks like so far:
function RenderResultsByName() {
//Declaration of variables
var nameInput, nameFilter, ul, li, a, i;
//Set the variables accorging to matching id's
//Name
nameInput = document.getElementById('nameInput');
nameFilter = nameInput.value.toUpperCase();
ul = document.getElementById("UL");
li = document.getElementsByTagName('tr');
console.log(li[0]);
//Loop trough items and hide those who don't match the query-->
for (i = 0; i < li.length; i++) {
a = li[i].getElementsByTagName("td")[0];
if (a.innerHTML.toUpperCase().indexOf(nameFilter) > -1) {
li[i].style.display = "";
}
else {
li[i].style.display = "none";
}
}
}
The HTML looks like this
<div class="row">
<div class="col-md-3">
<label>Namn: </label><br />
<input type="text" id="nameInput" onkeyup="RenderResultsByName()" placeholder="Sök efter namn..." /> <br /> <br />
</div>
</div>
<br /><br />
<table id="UL" class="table table-bordered">
<tr>
<th>Name</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#item.visitor.FullName</td>
</tr>
}
</table>
I tried to apply a class "tdOfName" on all the 's in the Name column, but after that the sort stopped working because the a variable became undefined.
How would you solve this?

First, two things for your HTML code:
First a piece of advice, add thead and tbody to your tables to simplify jquery row selectors (and is a good practice, anyway).
You're creating 5 columns in the head row but only one in the rest. You have to add the rest or set a colspan.
<table id="UL" class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
<th>Yada</th>
</tr>
<thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>#item.visitor.FullName</td><td></td><td></td><td></td><td></td>
</tr>
}
<tbody>
</table>
Then, you say sort but your function is trying to show/hide rows attending at the input of the value. I can't see any sign of sorting. In case what you want is show/hide rows that has the input value in the first column, you can simplify it with this...
jQuery.expr[':'].icontains = function(a, i, m) {
return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};
$('input#nameInput').on('keyup',function() {
$('table#UL tbody tr').hide().filter(':has(td:first:icontains('+this.value+'))').show();
});
Here you have an fiddle example... https://fiddle.jshell.net/rigobauer/4rzf4wt7/
Is this what you're looking for?
I hope it helps.

Related

How do I keep buttons visible when searching table rows in javascript?

Basically where I have the 3 buttons 1, 2, and 3 in the second column first row if I type 3 the only button shows up is 3....removing buttons 1 and 2
for example if I'm looking for text with "2" in it it should still show
I want all buttons to stay regardless if they show up in the search or not...can this be achieved?
I have atleast 4 columns visible at all times and I want to search ONLY the text in the < TD > not the element text in the < TD > so radio buttons, buttons, check boxes....I want those to be immune from searches always show them as long as that particular row has the text snippet in one of the columns of that row just search the text in < TD >
Googling the right phrase has led me here because google assumes I want a checkbox to search a table....NO....I want a search to only focus on text not element text if that makes sense
Thanks
function myFunction() {
const input = document.getElementById("myInput");
const inputStr = input.value.toUpperCase();
const search_length = inputStr.length;
//alert(search_length);
document.querySelectorAll('#myTable tr:not(.header)').forEach((tr) => {
const anyMatch = [...tr.children]
.some(td => td.textContent.toUpperCase().includes(inputStr));
//fix the button issue here
if (anyMatch) tr.style.removeProperty('display');
else tr.style.display = 'none';
});
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Type to search">
<table id="myTable" border="2">
<thead><tr>
<th>Col1</th>
<th>Col2</th>
</tr></thead>
<tbody>
<tr><td>2</td><td>
<table>
<tr><td>2<button type="button">1</button></td></tr>
<tr><td>5<button type="button">2</button></td></tr>
<tr><td>9<button type="button">3</button></td></tr>
</table></td></tr>
<tr><td>test4</td><td><button type="button">5</button></td></tr>
</tbody>
</table>
If you do not want to hide the sub table rows your selector needs to only touch the outside table.
function myFunction() {
const input = document.getElementById("myInput");
const inputStr = input.value.toUpperCase();
const search_length = inputStr.length;
//alert(search_length);
document.querySelectorAll('#myTable > tbody > tr:not(.header)').forEach((tr) => {
const anyMatch = [...tr.children]
.some(td => td.textContent.toUpperCase().includes(inputStr));
//fix the button issue here
if (anyMatch) tr.style.removeProperty('display');
else tr.style.display = 'none';
});
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Type to search">
<table id="myTable" border="2">
<thead>
<tr>
<th>Col1</th>
<th>Col2</th>
</tr>
</thead>
<tbody>
<tr>
<td>2</td>
<td>
<table>
<tr>
<td>2<button type="button">1</button></td>
</tr>
<tr>
<td>5<button type="button">2</button></td>
</tr>
<tr>
<td>9<button type="button">3</button></td>
</tr>
</table>
</td>
</tr>
<tr>
<td>test4</td>
<td><button type="button">5</button></td>
</tr>
</tbody>
</table>

How to empty table in javascript?

I cant delete the row contents of a table, but what if I want to delete the rows too?
My Javascript code: (I want all the rows to disappear except the first one.)
function deleteAll() {
for ( var i = 0; i <= table.rows.length; i++){
table.rows[i].cells[0].innerHTML = "";
table.rows[i].cells[1].innerHTML = "";
table.rows[i].cells[2].innerHTML = "";
}
}
My HTML table:
<body>
<div class="container">
<div class="tab tab-1">
<table id="table" border="1">
<th>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</th>
<tr>
<td>Frank</td>
<td>Nenjim</td>
<td>19</td>
</tr>
<tr>
<td>Alex</td>
<td>Ferreira</td>
<td>23</td>
</tr>
</table>
</div>
<div class="tab tab-2">
First Name :<input type="text" name="fname" id="fname">
Last Name :<input type="text" name="lname" id="lname">
Age :<input type="number" name="age" id="age">
<button onclick="deleteAll()">Delete All</button>
</div>
</div>
<script src="tableEdit.js"></script>
</body>
So, the Javascript code above doesn't satisfy me because I want only the first row to remain. I don't want empty rows.
You can use the jQuery remove() function as described in this example to delete all rows except the (first) header row:
$('#table tr:not(:first)').remove();
You may instead want to delete just the rows of body section (inside <tbody>) as mentioned in this post:
$('#table > tbody > tr').remove();
for(var i = 1;i<table.rows.length;){
table.deleteRow(i);
}
If you want to remove data rows only then use
$("#table tr").remove();
And if you want to empty table with header then use
$("#table").empty();

JavaScript Search Table by Index

I have a table with multiple columns (for this question I only made two columns) and I want the user to be able to search through a column by the index depending on an option that the user can select. I have working code, but in order to change the search option, I had to copy the function for each input.
How can I search by the index? If a user selects an option like (name), then the javascript function will change the index that it is searching to [0]. if the user selects (location), the function will change the index to [1] and search through that column.
Is this possible? Any help would be appreciated.
const searchName = document.getElementById('searchName');
const searchLoc = document.getElementById('searchLoc');
custSelect.addEventListener('click', () => {
if (custSelect.value == 'custname') {
searchName.style.display = 'block';
searchLoc.style.display = 'none';
} else {
searchName.style.display = 'none';
searchLoc.style.display = 'block';
}
});
// Search for customer, or search for location, index will change based on option selected.
function tableSearch(id, index) {
// Declare variables
var filter, input, table, tr, td, i;
input = document.getElementById(id);
filter = input.value.toUpperCase();
table = document.getElementById(id);
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]; // index will change based on option selected.
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="custDiv">
<div class="addBtns">
<input id="searchName" onkeyup="tableSearch('searchName','custList'[0])" type="text" placeholder="search name" />
<!-- this searches through the first index or [0] -->
<input id="searchLoc" onkeyup="tableSearch('searchLoc','custList'[1])" style="display: none;" type="text" placeholder="search location" />
<!-- this searches through the second index or [1] -->
<div id="custSelectDiv" style="width: 175px; height: 35px; max-height: 35px; margin: 0 auto;">
<select id="custSelect" style="position: absolute;">
<option value="custname">name</option> <!-- if user selects this, the corresponding input is displayed, which changes the index to search through -->
<option value="location">location</option> <!-- if user selects this, the corresponding input is displayed, which changes the index to search through -->
</select>
</div>
</div>
<table id="custListTop" contenteditable="false">
<tr>
<td style="border-top-left-radius: 5px;">Customers</td>
<td style="border-top-right-radius: 5px;">Main Location</td>
</tr>
</table>
<table id="custList" contenteditable="true">
<tr>
<td>josh</td>
<td>hawkins</td>
</tr>
<tr>
<td>hanna</td>
<td>big sandy</td>
</tr>
<tr>
<td>bonne</td>
<td>big sandy</td>
</tr>
<tr>
<td>thomas</td>
<td>big sandy</td>
</tr>
</table>
</div>
<script src="test.js"></script>
</body>
</html>
This should get you on track
var table = document.getElementById('tab'),
col = document.getElementById('col'),
val = document.getElementById('val');
col.max = table.rows[0].cells.length - 1;
function search() {
var regex = new RegExp(val.value || '', 'i');
for (var i = table.rows.length; i-- > 1;) {
if (regex.test(table.rows[i].cells[+col.value].innerHTML)) {
table.rows[i].style.display = 'table-row';
} else
table.rows[i].style.display = 'none';
}
}
table {
border-collapse: collapse;
}
table,
th,
td {
border: 1px solid;
}
<label for="col">Column :</label>
<input type="number" id="col" placeholder="column" onkeyup="search()" min="0" step="1" />
<br>
<label for="val">Find :</label>
<input type="text" id="val" placeholder="cell" onkeyup="search()" />
<table id="tab">
<tr>
<th>Customers</th>
<th>Main Location</th>
</tr>
<tr>
<td>josh</td>
<td>hawkins</td>
</tr>
<tr>
<td>hanna</td>
<td>big sandy</td>
</tr>
<tr>
<td>bonne</td>
<td>big sandy</td>
</tr>
<tr>
<td>thomas</td>
<td>big sandy</td>
</tr>
</table>
I think they are two simplier ways to do that research :
Use an object array to search what you need, reorganize it at each research and re-make your html table each time the table changes.
Or use dataTable, which is a very simple tool to sort table.

JavaScript single input search multiple html table columns

I am using PHP and MySQL to build an HTML table. I am trying to use JavaScript to filter/search the table and only display the rows with the results I need. I want the JavaScript input to search multiple <td>s of the table. I was able to get this to work, but it is not going to be an elegant solution to put in place with larger tables.
I am sure there is a better way to choose what is being searched, but have not been able to find anything. Does anybody know a way for me to make this code more flexible for varying column width tables?
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")[0];
td1 = tr[i].getElementsByTagName("td")[1];
if (td+td1) {
if ((td.innerHTML.toUpperCase().indexOf(filter)+td1.innerHTML.toUpperCase().indexOf(filter)) > -2) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search" title="Type in anything">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
There's a lot you can improve. Start by remembering to explicitly declare your variables, otherwise they become global.
This solution doesn't rely on any specific number of columns. It will work no matter how many there are.
See comments inline for more:
// Get DOM references just once:
var input = document.getElementById("myInput");
var table = document.getElementById("myTable");
// Do event binding in JavaScript, not HTML
input.addEventListener("keyup", filter);
input.addEventListener("search", filter);
// Get all rows, except the header and convert to array so .forEach() can be used to loop
var rows = Array.prototype.slice.call(table.querySelectorAll("tr:not(.header)"));
function filter() {
// Always trim user input
var filter = input.value.trim().toUpperCase();
// Loop the rows
rows.forEach(function(row) {
// You really don't need to know if the search criteria
// is in the first or second cell. You only need to know
// if it is in the row.
var data = "";
// Loop over all the cells in the current row and concatenate their text
Array.prototype.slice.call(row.getElementsByTagName("td")).forEach(function(r){
// Don't use .innerHTML unless there is HTML. Use textContent when there isn't.
data += r.textContent;
});
// Check the string for a match and show/hide row as needed
// Don't set individual styles. Add/remove classes instead
if(data.toUpperCase().indexOf(filter) > -1){
// show row
row.classList.remove("hidden");
} else {
// hide row
row.classList.add("hidden");
}
});
}
input[type=search]{
border-radius:10px;
outline:0;
padding:3px;
}
input[type=search]:focus{
box-shadow:0 0 4px blue;
}
.hidden { display:none; }
.leftHeader { width:60%; }
.rightHeader { width:40%; }
<!-- Use the actual "search" input type and don't do inline CSS or JavaScript -->
<input type="search" id="myInput" placeholder="Search" title="Type in anything">
<table id="myTable">
<tr class="header">
<th class="leftHeader">Name</th>
<th class="rightHeader">Country</th>
</tr>
<tr>
<td>North/South</td>
<td>UK</td>
</tr>
<tr>
<td>Paris specialites</td>
<td>France</td>
</tr>
</table>
All what you have to do is to get the td content and then match it with the search input.
function search(value) {
$('table tr').each(function () {
var content = $(this).find('td').text();
if (content.toUpperCase().includes(value.trim().toUpperCase())) {
$(this).show();
} else {
$(this).hide();
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<body>
<input type="search" placeholder="Search..." id="search_account" onkeyup="search(this.value)">
<table>
<tr>
<td>Cell1</td>
<td>Cell2</td>
<td>Cell3</td>
</tr>
<tr>
<td>Cell4</td>
<td>Cell5</td>
<td>Cell6</td>
</tr>
</table>
</body>
</html>

How can I get the corresponding table column (td) from a table header (th)?

I want to get the entire column of a table header.
For example, I want to select the table header "Address" to hide the address column, and select the "Phone" header to show the correspondent column.
<table>
<thead>
<tr>
<th id="name">Name</th>
<th id="address">Address</th>
<th id="address" class='hidden'>Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td class='hidden'>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td class='hidden'>3456</td>
</tr>
</tbody>
I want to do something like http://www.google.com/finance?q=apl (see the related companies table) (click the "add or remove columns" link)
Something like this would work -
$('th').click(function() {
var index = $(this).index()+1;
$('table td:nth-child(' + index + '),table th:nth-child(' + index + ')').hide()
});
The code above will hide the relevant column if you click on the header, the logic could be changed to suit your requirements though.
Demo - http://jsfiddle.net/LUDWQ/
With a couple simple modifications to your HTML, I'd do something like the following (framework-less JS):
HTML:
<input class="chk" type="checkbox" checked="checked" data-index="0">Name</input>
<input class="chk" type="checkbox" checked="checked" data-index="1">Address</input>
<input class="chk" type="checkbox" checked="checked" data-index="2">Phone</input>
<table id="tbl">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td>Freddy</td>
<td>Nightmare Street</td>
<td>123</td>
</tr>
<tr>
<td>Luis</td>
<td>Lost Street</td>
<td>3456</td>
</tr>
</tbody>
Javascript:
var cb = document.getElementsByClassName("chk");
var cbsz = cb.length;
for(var n = 0; n < cbsz ; ++n) {
cb[n].onclick = function(e) {
var idx = e.target.getAttribute("data-index");
toggleColumn(idx);
}
}
function toggleColumn(idx) {
var tbl = document.getElementById("tbl");
var rows = tbl.getElementsByTagName("tr");
var sz = rows.length;
for(var n = 0; n < sz; ++n) {
var el = n == 0 ? rows[n].getElementsByTagName("th")[idx] : rows[n].getElementsByTagName("td")[idx];
el.style.display = el.style.display === "none" ? "table-cell" : "none";
}
}
http://jsfiddle.net/dbrecht/YqUNz/1/
I added the checkboxes as it doesn't make sense to bind the click to the column headers as you won't be able to toggle the visibility, only hide them.
You can do something with CSS, like:
<html>
<head>
<style>
.c1 .c1, .c2 .c2, .c3 .c3{
display:none;
}
</style>
</head>
<body>
<table class="c2 c3">
<thead>
<tr>
<th id="name" class="c1">Name</th>
<th id="address" class="c2">Address</th>
<th id="phone" class="c3">Phone</th>
</tr>
</thead>
<tbody>
<tr>
<td class="c1">Freddy</td>
<td class="c2">Nightmare Street</td>
<td class="c3">123</td>
</tr>
<tr>
<td class="c1">Luis</td>
<td class="c2">Lost Street</td>
<td class="c3">3456</td>
</tr>
</tbody>
</table>
</body>
</html>
To hide a column, you add with Javascript the corresponding class to the table. Here c2 and c3 are hidden.
You could add dynamically the .c1, .c2,... in a style tag, or define a maximum number.
The easiest way to do this would be to add a class to each td that matches the class of the header. When you click the , it checks the class, then hides every td with that class. Since only the s in that column would hide that class, it would effectively hide the column.
<table>
<thead>
<th>Name</th>
<th>Address</th>
</thead>
<tbody>
<tr>
<td class="Name">Joe</td>
<td class="Address">123 Main St.
</tbody>
</table>
And the script something like:
$('th').click( function() {
var col = $(this).html(); // Get the content of the <th>
$('.'+col).hide(); // Hide everything with a class that matches the col value.
});
Something like that, anyway. That's probably more verbose than it needs to be, but it should demonstrate the principle.
Another way would be to simply count how many columns over the in question is, and then loop through each row and hide the td that is also that many columns over. For instance, if you want to hide the Address column and it is column #3 (index 2), then you would loop through each row and hide the third (index 2).
Good luck..
Simulating the Google Finance show/hide columns functionality:
http://jsfiddle.net/b9chris/HvA4s/
$('#edit').click(function() {
var headers = $('#table th').map(function() {
var th = $(this);
return {
text: th.text(),
shown: th.css('display') != 'none'
};
});
var h = ['<div id=tableEditor><button id=done>Done</button><table><thead><tr>'];
$.each(headers, function() {
h.push('<th><input type=checkbox',
(this.shown ? ' checked ' : ' '),
'/> ',
this.text,
'</th>');
});
h.push('</tr></thead></table></div>');
$('body').append(h.join(''));
$('#done').click(function() {
var showHeaders = $('#tableEditor input').map(function() { return this.checked; });
$.each(showHeaders, function(i, show) {
var cssIndex = i + 1;
var tags = $('#table th:nth-child(' + cssIndex + '), #table td:nth-child(' + cssIndex + ')');
if (show)
tags.show();
else
tags.hide();
});
$('#tableEditor').remove();
return false;
});
return false;
});
jQuery('thead td').click( function () {
var th_index = jQuery(this).index();
jQuery('#my_table tbody tr').each(
function(index) {
jQuery(this).children('td:eq(' + th_index + ');').each(
function(index) {
// do stuff here
}
);
}
);
});
here's a working fiddle of this behaviour:
http://jsfiddle.net/tycRW/
of course, hiding the column with out hiding the header for it will have some strange results.

Categories