Search html table row with min and max values using javascript - javascript

I want to search the HTML table with its min and max column values and display the searched row in the table. I have made a code for this and it is working fine to some extent. But even when I am searching 2, 4, 7 in the table search, it is still searching for 10-20, 30-40 and 60-70 respectively.
Please take a look and suggest me what should I change so that it should work perfect.
function myFunction() {
var input, filter, table, tr, td, i, txtValue;
input = document.getElementById("myInput").value;
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
td2 = tr[i].getElementsByTagName("td")[1];
if (td) {
txtValue = td.textContent || td.innerText;
txtValue2 = td2.textContent || td2.innerText;
if (input >= txtValue && input <= txtValue2) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search by min-max values" title="Type in a name">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Min</th>
<th style="width:40%;">Max</th>
<th style="width:40%;">Output</th>
</tr>
<tr>
<td>10</td>
<td>20</td>
<td>Germany</td>
</tr>
<tr>
<td>30</td>
<td>40</td>
<td>Sweden</td>
</tr>
<tr>
<td>60</td>
<td>70</td>
<td>UK</td>
</tr>
</table>

All you need is parseInt() when you're comparing data.
Normally when you get values using JS tags, they returns String, so it's pretty obvious you need to covert those to Integer before start using them for comparisons.
Here's a working jsfiddle for your answer - https://jsfiddle.net/exnak6vj/1/
Alternatively, just one more if condition and all the data in the table will be displayed if there's no text in search text area. I've implemented that too in the above jsfiddle.
Off-topic - this is good as long as you're doing it for your own learnings, but to implement something like this in actual project, there are whole lot of JS plugins available in market that too for free like Datatables... etc. Use those, they provides you great flexibility.

In your code the variables txtValue, txtValue2 and input are all strings. Use Number() function to make sure input and txtValue variables are Numbers.
a = "20" //this is how number as string is input
aNum = Number(a)
OR
aNum = parseInt(a, 10)
then you can properly do min and max comparison operations and you will not get 20 when you input 2.

Related

Javascript filtering on multiple table columns

I've tried using the below js code to filter table rows. The code is originally from w3schools but I've done some modification to target all my input values. The filtering works great for one column but as fast as I try to input a value on a second column, it overwrites the previous filter.
For exampe if I filter for "Test" in column 1 it works great and hides the second row. If I after that also filter column 2 for id "2" it will hide the first row and instead display the second row for id 2. Is it possible to modify the code so that it only filters on the rows that are left and shown, not all the rows all together. Ive tried several hours trying to target only tr[i].style.display != "none"; but no success. My goal is something like this: DataTables. I've seen and read tons of other threads on here regarding this issue but nothing seems to work. Appreciate all the help and guidance.
Name
ID
Test
1
Another test
2
[Input field for filter]
[Input field for filter]
$(document).ready(function() {
document.querySelectorAll('.search').forEach(item => {
item.addEventListener('keyup', event => {
var input, filter, table, tr, td, i, txtValue;
input = event.target;
filter = input.value.toUpperCase();
table = document.getElementById("example");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[event.target.getAttribute('data-value')];
if (td) {
txtValue = td.textContent || td.innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
})
})
} );
Your code was a mix of vanillaJS and jQuery, and tagged for both, so I went with jquery since it's a little more concise and easier to read.
Basically, you need to check both cells in each row against both search filters every time the key is pressed. To do so, I made things a tiny bit easier by giving the data TR rows a class so we're not searching the header or the cells with the search boxes. Then, I just compare filter 1 with cell 1 and filter 2 with cell 2 for each row. If there is a match for either, that row stays visible, otherwise it's hidden. I had to add in some logic in case there wasn't a value in either filter input.
Couple other notes:
$('.search').eq(0) is the same as the FIRST element with the class search
$(el).find('td').eq(0).text().trim().toLowerCase() is the same as find the FIRST TD tag's text, trim off the extra whitespace and convert to lowercase
$(document).ready(function() {
$('.search').keyup(function() {
let search1 = $('.search').eq(0).val().toLowerCase();
let search2 = $('.search').eq(1).val().toLowerCase();
$('.s-table tr.data').each(function(i, el) {
let val1 = $(el).find('td').eq(0).text().trim().toLowerCase()
let val2 = $(el).find('td').eq(1).text().trim().toLowerCase()
let ok = (search1 && val1.indexOf(search1) !== -1) || (search2 && val2.indexOf(search2) !== -1)
if (ok) $(el).closest('tr').show();
else $(el).closest('tr').hide();
})
return
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="s-table">
<thead>
<tr>
<th>Name</th>
<th>ID</th>
</tr>
</thead>
<tbody>
<tr class='data'>
<td>Test</td>
<td>1</td>
</tr>
<tr class='data'>
<td>Another test</td>
<td>2</td>
</tr>
<tr>
<td><input data-col='0' class='search' placeholder='filter'></td>
<td><input data-col='1' class='search' placeholder='filter'></td>
</tr>
</tbody>
</table>

Filter multiple tables using query string with javascript

first I'm sorry if at some point I express myself badly, English is not my native language. I am developing an application in which the user sends 2 values through a form and in another page I use one of those data (string with comma separated options) to show a specific table and hide the others, and with the second data (Integer) I show one of the rows of that table.
What I already have:
I have the form and send the data through the Query String, I capture that data, I assign a variable to the integer and to the text string I separate it by commas and create an array.
URL Example: app.tables.example/?id=123&ops=option1%2c+option2
//Read parameters sent by form
const param = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop)
});
//Assign integer to a variable
let num = param.id;
//Assign options to a variable
let op = param.ops;
//Separate string with commas
let opsplit = op.split(',');
Up to here everything is perfect, I can print all the variables without any problem, now I need to compare the array with the id of each table, show the one that corresponds and hide the others. (The id of the tables is the same that user passes with the text string).
The tables look something like this:
<div id="option1" class="table-1">
<table width="100%">
<thead>
<tr>
<th align="left">Option1</th>
<th align="left">Integer</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Number</td>
<td align="left">Info</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">textblock</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">textblock</td>
</tr>
</tbody>
</table>
</div>
//As you can see the id of each table corresponds to what the user chose
<div id="option2" class="table-1">
<table width="100%">
<thead>
<tr>
<th align="left">Option2</th>
<th align="left">Integer</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Number</td>
<td align="left">Info</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">textblock</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">textblock</td>
</tr>
</tbody>
</table>
</div>
The problem:
I'm supposed to use the array elements in a "for" loop and compare them with the id of each table, then show that table and hide others, but I don't know exactly how to do it.
function myFunction() {
var input, filter, table, tr, td, i, y, txtValue;
for (r = 0; r<opsplit.length; r++){
input = opsplit[r];
filter = function(x){
return x.toUpperCase();
};
opsplit = opsplit.map(filter);
}
//When I test this, it does not return any value,
//innerHTML error
for(y = 0; y<opsplit.length; y++){
table = document.getElementById(opsplit[y]).innerHTML;
//I use this section to test, it should show me the row,
//but since the previous loop failed, it does nothing.
// What I really need is to show the whole
// table where this data is located and hide the other tables.
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";
}
}
}
}
}
myFunction();
I am really stuck at the moment and would appreciate any help. What is the correct way to use the string array, and how can I hide the tables that the user does not need?
Ok, thanks to those who took the time to write a comment, but I found the solution, I had to convert the form data to a string and an integer. Then I was able to compare that string to the classes id. I am writing the answer in case anyone finds it useful.
//Read parameters sent by form
const param = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop)
});
//Assign number to a variable
let num = param.id;
//Convert to integer
let numint = parseInt(num);
//Assign options to a variable
let op = param.ops;
//Convert to String
let opstr = op.string();
//Separate string with commas
let opsplitstr = opstr.split(',');
//Assign class to a variable
tableclass = document.getElementsByClassName('table-1');
//Compare table class ids with string array
if (opsplitstr[0] == tableclass[0].id{
}
//We need a loop if we need compare all elements
TLDR: The URL does not send information about the data type, so I had to read it and convert it according to my need.

Getting a checkbox from a table field

Good afternoon, below is the code in it I am getting fields from my table. The 0 field contains a checkbox, how can I find out if it is checked or not(true or false)? You need to change this line: console.log (td.item (f));
var table = document.getElementsByClassName("table-sm");
for (var i = 0; i < table.length; i++) {
var tr = table.item(i).getElementsByTagName("tr");
for (var j = 0; j < tr.length; j++) {
var trr = tr.item(j);
var td = tr.item(j).getElementsByTagName("td");
for (var f = 0; f < td.length; f++) {
if (f === 0) console.log(td.item(f));
console.log(td.item(f).innerText);
}
}
}
Firstly, please learn about JavaScript Table API is much better than just making complex for-loops.
Next time please add full code (HTML/JavaScript) so people can help you.
Now let's fix your code.
Suppose we have this table
<table class="table-sm" id="myTable">
<thead>
<tr>
<th>Checkbox</th>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="selected[]" checked /></td>
<td>1</td>
<td>Mohammed</td>
</tr>
<tr>
<td><input type="checkbox" name="selected[]" /></td>
<td>2</td>
<td>Ali</td>
</tr>
</tbody>
</table>
and we want to get the first item of each rows, and check whether the checkbox is checked or not.
We can do it easly using JS Table APIs.
Get the table by it's ID.
var table = document.getElementById("myTable");
Get the table rows
I use Array.from() to convert HTMLCollection to normal array, so I can use Array APIs (Like .forEach).
var rows = Array.from(table.rows);
Loop into table rows, and get cells of each row.
rows.map((row) => {
var cells = Array.from(row.cells);
// TODO add logic here.
});
Get the firstChild of first cell.
rows.map((row) => {
var cells = Array.from(row.cells);
if (Array.isArray(cells) && cells.length > 0) {
var firstChild = cells[0].firstChild;
console.log(firstChild.checked);
}
});
Live Example

How can I make sure a specific string exists in every table row using JavaScript?

I'm a beginner at JavaScript and haven't been able to figure this out...
I need to check each row of a table to see if the string "Business Cards" exists in each row. If EVERY row contains this string, I'll proceed with option A, but if even one row doesn't contain the string, I'll stop checking and proceed with option B.
Here is an idea of what the table looks like in HTML (although the number of rows and products in each row will vary, since they're dynamically generated):
<table class="rgMasterTable" border="0" id="ctl00_cphMainContent_dgShippingItems_ctl00" style="width:100%;table-layout:auto;empty-cells:show;">
<thead>
<tr>
<th scope="col" class="rgHeader" style="text-align:center;">Name</th>
<th scope="col" class="rgHeader" style="text-align:center;">No. of Units</th>
</tr>
</thead>
<tbody>
<tr class="rgRow" id="ctl00_cphMainContent_dgShippingItems_ctl00__0" style="text-align:center;">
<td style="width:250px;">
Business Cards - TEST - CA Back
</td>
<td style="width:100px;">
250 Business Cards
</td>
</tr>
<tr class="rgAltRow" id="ctl00_cphMainContent_dgShippingItems_ctl00__1" style="text-align:center;">
<td style="width:250px;">
Business Cards - Joint Venture - TEST
</td>
<td style="width:100px;">
250 Business Cards
</td>
</tr>
</tbody>
</table>
And here's my attempt at the code. I'm trying to make use of the fact that the tr id will always have the index (eg: "ctl00_cphMainContent_dgShippingItems_ctl00__0" for the first row, "ctl00_cphMainContent_dgShippingItems_ctl00__1" for the second, etc), but maybe there's an easier way to do this?
var businessCardItem = 'Business Cards';
var orderItemCount = $('#ctl00_cphMainContent_dgShippingItems_ctl00 tr').length;
var onlyBusinessCards = true;
for (var i = 0; i <= orderItemCount; i++) {
if($('#ctl00_cphMainContent_dgShippingItems_ctl00__' + i).text().indexOf(businessCardItem) >= 0) {
return onlyBusinessCards;
}
else {
onlyBusinessCards = false;
return onlyBusinessCards;
break;
}
}
if (onlyBusinessCards == true) {
//Option A
}
else {
//Option B
}
Any help would be appreciated! Let me know if any more detail or clarification is needed!
Count how many rows contain "Business Cards" and compare to the number of rows:
Note: only count rows within tbody
var table = $("#ctl00_cphMainContent_dgShippingItems_ctl00");
var rows = $("tbody tr",table).length;
var rowsWithBC = $("tbody tr:contains(Business Cards)",table).length;
if( rows == rowsWithBC ) {
// Option A
} else {
// Option B
}

Javascript To Add Up And Compare Two Table Column Totals

Im trying to achieve the following: Add the numbers from two table columns, perform the following operation on them ($price2 - $price1)/$price1 * 100 and then add the result to the top of the table in a special div.
<div id="mydiv">Percentage Gain/Loss</div>
<table id="mytable">
<tbody>
<tr>
<th>price1</th><th>price2</th>
</tr>
<tr>
<td>10</td><td>30</td>
</tr>
<tr>
<td>5</td><td>10</td>
</tr>
<tr>
<td>15</td><td>5</td>
</tr>
</tbody>
</table>
So the desired operation would populate #mydiv with the results of ((30+10+5) - (10+5+15))/(10+5+15)*100 What would be the best way to achieve this? Also, if price2 should happen to be lower than price1 the output should be negative (I guess something like -Math.abs would work).
You can use getElementsByTagName to get the html elements that contain your prices and then do the computations.
var sum1 = 0, sum2 = 0;
var table = document.getElementById('mytable');
var rows = table.getElementsByTagName('tr'); // restrict the search to one table
for (var i=0, length = rows.length; i<length; i++) {
var tds = rows[i].getElementsByTagName('td');
if (tds.length >= 1) {
var val1 = +tds[0].innerHTML; // unary plus converts the value to Number
var val2 = +tds[1].innerHTML;
sum1 += val1;
sum2 += val2;
}
}
document.getElementById('mydiv').innerHTML = (sum2 - sum1) / sum1 * 100 + '';
Working JsFiddle: http://jsbin.com/IqARONE/1/edit
I would just put classes to each td, something like:
<tr>
<th>price1</th><th>price2</th>
</tr>
<tr>
<td class="price1">10</td><td class="price2">30</td>
</tr>
<tr>
<td class="price1">5</td><td class="price2">10</td>
</tr>
<tr>
<td class="price1">15</td><td class="price2">5</td>
</tr>
Then, in your JavaScript, use the getElementsByClassName method to get an array of price1 tags and a second array of price2 tags, then use the parseInt method to get the actual value inside each tag and compute the wanted value. You then put this value using something like $('#mydiv').html(total). Hope this helps.

Categories

Resources