I have implement search on table and it works fine. But there is one problem after I update the table row. Search always show the edited row even if it does not match the search.
eg. steps -
1.enter "user3" in search box then result - user3
2.edit "user3"
3.enter "user1" in search box then result - user1,user3
HTML
<table>
<tbody id="list">
<tr id="o1">
<td class="txtclass">user</td>
<td><a>edit</a></td>
</tr>
<tr id="o2">
<td class="txtclass">user2</td>
<td><a>edit</a></td>
</tr>
<tr id="o3">
<td class="txtclass">user3</td>
<td><a>edit</a></td>
</tr>
<tr id="o4">
<td class="txtclass">user4</td>
<td><a>edit</a></td>
</tr>
</tbody>
</table>
script
// function to replace table row
// d- table row html
function updateRow(d)
{
$("#o3").before(d).remove();
}
// search in table row list
$("#textsearch").change(function () {
var filter = $(this).val().toLowerCase();
var li;
list = list of table rows;
len = list.length;
for (var i = 0; i < len; i++) {
li = list[i];
txt = $(li).find(".txtclass").text();
if ((txt || "").toLowerCase().indexOf(filter) >= 0) {
if (li.style.display == "none") { li.style.display = "block"; }
} else {
if (li.style.display != "none") { li.style.display = "none"; }
}
}
return false;
}
Related
I'm trying to filter on my html table by inputting two dates(From and To) and then it should filter the data in the html table column[0] "Date Column" accordingly.
The inputs on my page::
<input type="date" id="date-start" onselect="searchDate()" />
<input type="date" id="date-stop" onselect="searchDate()" />
The java script I have together so far is:
function searchDate() {
var input_startDate, input_stopDate, table, tr, i;
input_startDate = document.getElementById("date-start");
input_stopDate = document.getElementById("date-stop");
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td_date = tr[i].getElementsByTagName("td")[0];
if (td_date) {
if (td_date >= input_startDate && td_name <= input_stopDate) {
??? - Display Rows;
}
else {
??? - Hide Rows;
}
}
}
}
I know this might be pretty straight forward but I have no idea what to do as I can't seem to get it working.
My table gets created as follows:
#if (employees is null)
{
<p style="color:white;"><em>Loading . . .</em></p>
}
else
{
<table class="table" id="myTable">
<thead>
<tr>
<th style="border: none;">Entry Date</th>
<th style="border: none;">Employee</th>
</tr>
</thead>
<tbody>
#foreach (var employee in employees)
{
<tr>
<td style="vertical-align: middle; border: none;">#employee.EntryDate</td>
<td style="vertical-align: middle; border: none;">#employee.POI</td>
</tr>
}
</tbody>
</table>
}
Any help would be appreciated.
Database format is: 2020-06-05 10:57:10
Thanks.
You have multiple issues in the sample:
you are not getting the actual values from the table td cells or
inputs
you need to convert the values to dates to compare
correctly
you can then hide/show a row by setting the display
property on the style
See the commented demo below:
function searchDate() {
var input_startDate, input_stopDate, table, tr, i;
// get the values and convert to date
input_startDate = new Date(document.getElementById("date-start").value);
input_stopDate = new Date(document.getElementById("date-stop").value);
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
// you need to get the text and convert to date
let td_date = new Date(tr[i].getElementsByTagName("td")[0].textContent);
// now you can compare dates correctly
if (td_date) {
if (td_date >= input_startDate && td_date <= input_stopDate) {
// show the row by setting the display property
tr[i].style.display = 'table-row;';
} else {
// hide the row by setting the display property
tr[i].style.display = 'none';
}
}
}
}
function searchDateAlternative() {
// get the values and convert to date
const input_startDate = new Date(document.getElementById("date-start").value);
const input_stopDate = new Date(document.getElementById("date-stop").value);
// only process table body rows, ignoring footer/headers
const tr = document.querySelectorAll("#myTable tbody tr")
for (let i = 0; i < tr.length; i++) {
// ensure we have a relevant td
let td = tr[i].getElementsByTagName("td");
if (!td || !td[0]) continue;
// you need to get the text and convert to date
let td_date = new Date(td[0].textContent);
// now you can compare dates correctly
if (td_date) {
if (td_date >= input_startDate && td_date <= input_stopDate) {
// show the row by setting the display property
tr[i].style.display = 'table-row;';
} else {
// hide the row by setting the display property
tr[i].style.display = 'none';
}
}
}
}
#myTable td {
border: 1px solid;
border-collapse: collapse;
}
<input id="date-start" type="text" value="2020-01-01"></input>
<input id="date-stop" type="text" value="2020-01-02"></input>
<button type="button" onclick="searchDateAlternative()">Go</button>
<hr/>
<table id="myTable">
<thead>
<tr>
<td>Date</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr>
<td>2020-01-01</td>
<td>Foo</td>
</tr>
<tr>
<td>2020-01-02</td>
<td>Bar</td>
</tr>
<tr>
<td>2020-01-03</td>
<td>Baz</td>
</tr>
</tbody>
</table>
You can use style.display to hide/show your rows. Set it to 'none' to hide the rows or 'block' to view them.
function searchDate() {
var input_startDate, input_stopDate, table, tr, i;
input_startDate = document.getElementById("date-start");
input_stopDate = document.getElementById("date-stop");
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td_date = tr[i].getElementsByTagName("td")[0];
if (td_date) {
if (td_date >= input_startDate && td_name <= input_stopDate) {
tr[i].style.display = "block";
}
else {
tr[i].style.display = "none";
}
}
}
}
It is a room type selection. Here I want to select room type on this selection I want to show only that row which I was selected from dropdown and other row should be hide at same time.
<select onChange="onSelect(this)" class="col-Room" name="ACRoom">
<option value="optionAC" >AC-Room</option>
<option value="optionNAC">Non AC-Room</option>
</select>
This is javascript code which I am using for selection. But it is not working properly. Only second option is working on select and first option is not working properly on selection.
Please help me out.
<script>
function onSelect(thisselect) {
var selected = thisselect.options[thisselect.selectedIndex].value;
toggleRow(selected);
}
function toggleRow(id) {
var row = document.getElementById(id);
if (row.style.display == '') {
row.style.display = 'none';
}
else {
row.style.display = '';
}
}
function showRow(id) {
var row = document.getElementById(id);
row.style.display = '';
}
function hideRow(id) {
var row = document.getElementById(id);
row.style.display = 'none';
}
function hideAll() {
hideRow('optionAC');
hideRow('optionNAC');
}
</script>
You should hide other rows while showing some particular rows. While selecting first option, you are not hiding nonac rows. Also I suggest you to use classs names instead of ID, since table can have multiple ac/non-ac rows. The below code could help you.
<!DOCTYPE html>
<table id="table">
<thead>
<tr>
<th>Rooms</th>
</tr>
</thead>
<tbody>
<tr class="ac">
<td>AC room</td>
</tr>
<tr class="nonac">
<td>Non Ac room</td>
</tr>
<tr class="ac">
<td>AC room</td>
</tr>
<tr class="nonac">
<td>Non Ac room</td>
</tr>
</tbody>
</table>
<select onChange="onSelect(this)">
<option value="ac">AC</option>
<option value="nonac">NON AC</option>
</select>
<script>
var ac = document.getElementsByClassName("ac");
var nonac = document.getElementsByClassName("nonac");
function onSelect(thisselect) {
var selected = thisselect.options[thisselect.selectedIndex].value;
toggleRow(selected);
}
function toggleRow(id) {
if (id == "ac") {
showac();
} else {
shownonac();
}
}
function showac() {
for (var i = 0; i < nonac.length; i += 1) {
nonac[i].style.display = 'none';
}
for (var i = 0; i < ac.length; i += 1) {
ac[i].style.display = 'block';
}
}
function shownonac() {
for (var i = 0; i < ac.length; i += 1) {
ac[i].style.display = 'none';
}
for (var i = 0; i < nonac.length; i += 1) {
nonac[i].style.display = 'block';
}
}
</script>
I'm wondering if there is a way for this search bar that I'm using to display multiple elements. As it is right now if I search for "123" in a pool with "321" "1234" "123" "12345" The only displayed value would be the first one: "1234". I'd like for all values that match my search to be displayed, therefore this would be the correct search result: "1234" "123" "12345".
Any answer is appreciated.
Here's the current code that I have:
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
if (search.value.length > 0 && search.value != '') {
for (var i = 0; i < cells.length; ++i) {
if (cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === 0) {
cells.forEach(function(element) {
element.style.display = "none";
});
cells[i].style.display = "table-cell";
break;
} else {
cells.forEach(function(element) {
if (cells[i] !== element) {
element.style.display = "table-cell";
}
});
}
}
} else {
cells.forEach(function(element) {
if (cells[i] !== element) {
element.style.display = "table-cell";
}
});
}
});
<input id="myInput">
<table id="myTable">
<tr>
<td>321</td>
<td>123</td>
</tr>
<tr>
<td>1234</td>
<td>abc</td>
</tr>
<tr>
<td>12345</td>
<td>abcde</td>
</tr>
</table>
Your cells selector returns a nodelist this is an arrayish object. That doesn't have the forEach function.
However we can borrow from the Array object:
Array.prototype.forEach
What I did to solve the other problem is create an indexArray as a lookup array. that keeps track of the indices that contained the search string. Then when we loop all the cells we can turn the ones of that don't show up in the lookup array
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
var indexArray = []; //look up array
for (var i = 0; i < cells.length; ++i) {
//restore the cells:
cells[i].style.display = "table-cell";
//if search value is found the value will be 0 if it starts a the beginning
if (cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === 0) {
indexArray.push(i); //push index into lookup
}
}
//loop over all cells
Array.prototype.forEach.call(cells, function(element, index) {
if (indexArray.indexOf(index) === -1) //if index is not present in look up, set display to none
element.style.display = "none";
});
});
<input id="myInput">
<table id="myTable">
<tr>
<td>321</td>
<td>123</td>
</tr>
<tr>
<td>1234</td>
<td>abc</td>
</tr>
<tr>
<td>12345</td>
<td>abcde</td>
</tr>
</table>
below code is enough if you want to show which cell has contain that search; also you can test on jsfiddle https://jsfiddle.net/bzcdomjs/
var cells = document.querySelectorAll("#myTable td");
var search = document.getElementById("myInput");
search.addEventListener("keyup", function() {
for (var i = 0; i < cells.length; ++i) {
cells[i].style.display = "table-cell";
if (search.value.length > 0 && search.value != '') {
if(cells[i].textContent.toLowerCase().indexOf(search.value.toLowerCase()) === -1) {
cells[i].style.display = "none";
}
}
});
This is my follow-up question of this... See here. I have a jscript(courtesy of hex494D49), searching values from first column.
All I need is, when the values is searching by the user, the table headers will also displayed and if the values is not store. There's a message will display like this "No results found". How to do that?
Here's the JSfiddle file with html
Here's the JScript:
document.getElementById('term').onkeyup = function(){
var term = this.value;
var column = 0;
var pattern = new RegExp(term, 'g');
var table = document.getElementById('dataTable');
var tr = table.getElementsByTagName('TR');
for(var i = 0; i < tr.length; i++){
var td = tr[i].getElementsByTagName('TD');
for(var j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML == term){
console.log('Found it: ' + td[j].innerHTML);
tr[i].style.display = 'block';
return;
alert('Found it: ' + td[j].innerHTML);
}else{
tr[i].style.display = 'none';
}
}
}
};
This would be the table markup. As you can see, I added thead, tbody and tfoot groups
<!-- search box -->
<input type="text" name="term" id="term" autocomplete = "off" />
<!-- table results -->
<table id="dataTable">
<thead>
<tr>
<th>Example No.</th>
<th>Column 1</th>
<th>Column 2</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="3"></th>
</tr>
</tfoot>
<tbody>
<tbody>
<tr>
<td>345678917</td>
<td>Test 1</td>
<td>one_test1#gmail.com</td>
</tr>
<tr>
<td>3512376894</td>
<td>Test 2</td>
<td>two.test2#hotmail.com</td>
</tr>
</tbody>
</table>
Default CSS for the markup above. Next step would be merging the following with the rest of your CSS.
table thead {
display: table-row-group;
}
table tbody {
display: table-row-group;
}
table tbody tr {
display: none;
}
And finally the JavaScript snippet using getElementsByTagName() method
// JavaScript
document.getElementById('term').onkeyup = function(){
var term = this.value;
var column = 0;
var msg = 'No results found!';
var pattern = new RegExp(term, 'g');
var table = document.getElementById('dataTable');
var tr = table.getElementsByTagName('TR');
for(var i = 0; i < tr.length; i++){
var td = tr[i].getElementsByTagName('TD');
for(var j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML == term){
tr[i].style.display = 'table-row';
table.tFoot.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
table.tFoot.innerHTML = msg;
}
}
}
};
Working jsFiddle | Version without tfoot jsFiddle
The same as above but using rows[] and cells[] collection
HTML
<!-- Search box -->
<input type="text" id="search" autocomplete = "off" />
<!-- Table -->
<table id="table">
<thead>
<tr>
<th>Product</th>
<th>Manufacturer</th>
<th>Price</th>
<th>InStock</th>
</tr>
</thead>
<tbody>
<tr>
<td>MacBook Air</td>
<td>Apple</td>
<td>$456</td>
<td>85</td>
</tr>
<tr>
<td>Arc GIS</td>
<td>ESRI</td>
<td>$4556</td>
<td>15</td>
</tr>
<tr>
<td>3ds MAX</td>
<td>Aurodesk</td>
<td>$6556</td>
<td>359</td>
</tr>
<tr>
<td>Windows 7</td>
<td>Micorsoft</td>
<td>$256</td>
<td>2567</td>
</tr>
</tbody>
</table>
<!-- Message -->
<div id="message"></div>
CSS
table thead {
display: table-row-group;
}
table tbody tr {
display: none;
}
JavaScript
document.getElementById('search').onkeyup = function(){
var table = document.getElementById('table'),
tr = table.rows, td,
term = this.value.toLowerCase(), column = 0, i, j,
message = document.getElementById('message');
for(i = 1; i < tr.length; i++){
td = tr[i].cells;
for(j = 0; j < td.length; j++){
if(j == column && td[j].innerHTML.toLowerCase() == term){
tr[i].style.display = 'table-row';
message.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
message.innerHTML = 'No results found!';
}
}
}
};
Working jsFiddle If you won't use thead and tbody in your table here is another version jsFiddle
I case you want to search all columns, just change this line
if(j == column && td[j].innerHTML.toLowerCase() == term){
to this one
if(td[j].innerHTML.toLowerCase() == term){
And finally, if you want to have more flexible search try the version below
document.getElementById('search').onkeyup = function(){
var table = document.getElementById('table'),
tr = table.rows, td,
term = this.value.toLowerCase().trim(), column = 0, i, j,
message = document.getElementById('message'),
pattern = new RegExp(term, 'gi');
for(i = 1; i < tr.length; i++){
td = tr[i].cells;
for(j = 0; j < td.length; j++){
if(j == column && term.length > 0 && td[j].innerHTML.match(pattern)){
tr[i].style.display = 'table-row';
message.innerHTML = '';
return;
}else{
tr[i].style.display = 'none';
message.innerHTML = 'No results found!';
}
}
}
};
Working jsFiddle
I have a dynamically generated table that I am trying to change the background color of certain rows in. Sometimes there are rows with rowspans and I cant figure out how to get all of the rows that correspond to the one "row." I've googled my brains out and found this jsfiddle which is pretty close to what i need (in a logic sense)
http://jsfiddle.net/DamianS1987/G2trb/
basically i have something like this:
and I want to be able to highlight full rows at a time like this:
but the only highlighting i can achieve on rowspan rows is this:
Here is my code (different from jsfiddle but essentially same logic)
CSS:
.highlightedClass{
background-color: #AEAF93;
}
HTML:
<table border="1" class="altTable">
<th>ID</th>
<th>NAME</th>
<th>Miles</th>
<th>WORK</th>
<tbody>
<tr>
<td class="td_id">999B</td>
<td class="td_name ">John</td>
<td class="td_cumMiles">702.4</td>
<td class="td_workEvent">Y</td>
</tr><tr>
<td class="td_id" rowspan="2">111A</td>
<td class="td_name">Tom</td>
<td class="td_cumMiles">446.5</td>
<td class="td_workEvent">Y</td>
</tr><tr>
<td class="td_name">Becky</td>
<td class="td_cumMiles">446.5</td>
<td class="td_workEvent">A</td>
</tr>
</tbody>
JAVASCRIPT:
for(var j=0; j < inspection.length; j++){
var $tr = $('<tr></tr>');
var $td_id = $('<td></td>').addClass('td_id').html(inspection.id);
$tr.append($td_id);
$table.append($tr);
$.each(inspection[i], function(index, value){
var $td_name, $td_miles,$td_workEvent;
if(index > 0){
var $2nd_tr = $('<tr></tr>');
$td_name = $('<td></td>').addClass('td_name').html(value.stationSt);
$td_miles = $('<td></td>').addClass('td_miles').html(value.miles);
$td_workEvent = $('<td></td>').addClass('td_workEvent').html(value.code);
$2nd_tr.append($td_name);
$2nd_tr.append($td_miles);
$2nd_tr.append($td_workEvent);
$table.append($2nd_tr);
$td_id.attr('rowSpan',index+1);
if($td_id.text() === content().id){
$2nd_tr.addClass("highlightedClass");
}else{
if($2nd_tr.hasClass("highlightedClass")){
$2nd_tr.removeClass('highlightedClass');
}
}
$('#workevent').on('click', function(){
$tr.removeClass('highlightedClass');
});
}else{
$td_name = $('<td></td>').addClass('td_name').html(value.stationSt);
$td_miles = $('<td></td>').addClass('td_miles').html(value.miles);
$td_workEvent = $('<td></td>').addClass('td_workEvent').html(value.code);
$tr.append($td_name);
$tr.append($td_miles);
$tr.append($td_workEvent);
$table.append($tr);
if($td_id.text() === content().id){
$tr.addClass("highlightedClass");
}else{
if($tr.hasClass("highlightedClass")){
$tr.removeClass('highlightedClass');
}
}
$('#workevent').on('click', function(){
$tr.removeClass('highlightedClass');
});
}
});
You need to look for any rowspan= attribute in the selected tds and if present, select the subsequent row(s) as well. This example should support any rowspan value (it appends subsequent rows based on the rowspan count):
Final version: JSFiddle: http://jsfiddle.net/TrueBlueAussie/G2trb/22/
$('td').bind('click', function () {
var $row = $(this).closest('tr');
// What row index is the clicked row?
var row = $row.index(); // Subtract heading row
// Does the clicked row overlap anything following?
var rowspan = ~~$row.find('td[rowspan]').attr('rowspan') || 0;
// Get all rows except the heading, up to the last overlapped row
var $rows = $row.parent().children().slice(1, row + rowspan);
row--; // Subtract the heading row we excluded
// Now see if any preceding rows overlap the clicked row
$rows.each(function (i) {
var $tr = $(this);
// Only check first rowspan of a row
var rowspan = ~~$tr.find('td[rowspan]').attr('rowspan') || 0;
// If the rowspan is before the clicked row but overlaps it
// Or it is a row we included after the selection
if ((i < row && ((rowspan + i) > row)) || i > row) {
$row = $row.add($tr);
}
});
$row.toggleClass('green');
});
First attempt JSFiddle: http://jsfiddle.net/TrueBlueAussie/G2trb/18/
$('td').bind('click', function () {
var $td = $(this);
var $row = $td.closest('tr');
var $tds = $row.find('td');
$tds.each(function(){
var rowspan = ~~$(this).attr('rowspan');
while (--rowspan > 0){
$row = $row.add($row.next());
}
});
$row.toggleClass('green');
});
It needs to be tweaked for the child row that sits under a previous rowspan, but am working on that too.
Notes:
~~ is a shortcut to convert a string to an integer.
the || 0 converts undefined values to 0.
$row = $row.add($tr) is appending row elements to a jQuery collection/object.
In fixing my issue (going off what TrueBlueAussie gave me) I came up with the following solution.
CSS:
.highlightedClass{
background-color: #AEAF93;
}
HTML:
<table border="1" class="altTable">
<th>ID</th>
<th>NAME</th>
<th>Miles</th>
<th>WORK</th>
<tbody>
<tr>
<td class="td_id">999B</td>
<td class="td_name ">John</td>
<td class="td_cumMiles">702.4</td>
<td class="td_workEvent">Y</td>
</tr><tr>
<td class="td_id" rowspan="2">111A</td>
<td class="td_name">Tom</td>
<td class="td_cumMiles">446.5</td>
<td class="td_workEvent">Y</td>
</tr><tr>
<td class="td_name">Becky</td>
<td class="td_cumMiles">446.5</td>
<td class="td_workEvent">A</td>
</tr>
</tbody>
JAVASCRIPT:
for(var j=0; j < inspection.length; j++){
var $tr = $('<tr></tr>');
var $td_id = $('<td></td>').addClass('td_id').html(inspection.id);
$tr.append($td_id);
$table.append($tr);
$.each(inspection[i], function(index, value){
var $td_name, $td_miles,$td_workEvent;
if(index > 0){
var $2nd_tr = $('<tr></tr>');
$td_name = $('<td></td>').addClass('td_name').html(value.stationSt);
$td_miles = $('<td></td>').addClass('td_miles').html(value.miles);
$td_workEvent = $('<td></td>').addClass('td_workEvent').html(value.code);
$2nd_tr.append($td_name);
$2nd_tr.append($td_miles);
$2nd_tr.append($td_workEvent);
$table.append($2nd_tr);
$td_id.attr('rowSpan',index+1);
if($td_id.text() === content().td_id){
$2nd_tr.addClass("highlightedClass");
}else{
if($2nd_tr.hasClass("highlightedClass")){
$2nd_tr.removeClass('highlightedClass');
}
}
$('#workevent').on('click', function(){
if($td_id.text() === content().td_id){
$2nd_tr.addClass("highlightedClass");
}else{
if($2nd_tr.hasClass("highlightedClass")){
$2nd_tr.removeClass("highlightedClass");
}
}
});
}else{
$td_name = $('<td></td>').addClass('td_name').html(value.stationSt);
$td_miles = $('<td></td>').addClass('td_miles').html(value.miles);
$td_workEvent = $('<td></td>').addClass('td_workEvent').html(value.code);
$tr.append($td_name);
$tr.append($td_miles);
$tr.append($td_workEvent);
$table.append($tr);
if($td_id.text() === content().id){
$tr.addClass("highlightedClass");
}else{
if($tr.hasClass("highlightedClass")){
$tr.removeClass('highlightedClass');
}
}
}
});
This was in a nested if statement. below like three if statements, i put this:
$('#workevent').on('click', function(){
var flag= false;
$('#altTable > tbody > tr').each(function() {
$td_id= $(this).find('.td_id');
if($td_id.text() === ''){
if(flag === true){
$(this).addClass("highlightedClass");
flag = true;
}
}else{
if(if($td_id.text() === content().idtd_id{){
if($(this).hasClass("highlightedClass")){
flag = true;
}else{
$(this).addClass("highlightedClass");
flag = true;
}
}else{
flag = false;
if($(this).hasClass("highlightedClass")){
$(this).removeClass("highlightedClass");
}
}
}
});
});
This is what worked for me. I selected TrueBlueAussie's answer because it helped get me my specific answer. Hopefully both answers can help someone else in the future.