Highlighting HTML table cells depending on value (jQuery) - javascript

There is a table that will populate depending on the selected dropdown element. Here is the code (I didn’t insert a line with dropdown elements):
<table id="myPlaneTable" class="table table-bordered">
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">450</td>
<td style="width: 15%">487</td>
<td style="width: 15%">450</td>
<td style="width: 15%">600</td>
</tr>
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">580</td>
<td style="width: 15%">490</td>
<td style="width: 15%">543</td>
<td style="width: 15%">742</td>
</tr>
</table
Here's what it looks like
Since I was just starting to learn jQuery, I tried the following code, but it does not work
$("#myPlaneTable tbody tr.data-in-table").each(function () {
$(this).find('td').each(function (index) {
var currentCell = $(this);
var nextCell = $(this).next('td').length > 0 ? $(this).next('td') : null;
if (index%2==0&&nextCell && currentCell.text() !== nextCell.text()) {
currentCell.css('backgroundColor', 'red');
nextCell.css('backgroundColor', 'green');
}
});
});
The result I'm trying to get
Highlighting if only the best and worst value (not between)
If the data matches in several cells, it is necessary to highlight them too
If there is no data, the cell should be without highlighting
Data should be compared within one <tr>, since there will be several lines

You can store all the values of each row in an array.
Then, store the minimum and maximum values, and finally apply the color to each <td> if the value match.
$("#myPlaneTable tbody tr").each(function () {
var values = [];
var tds = $(this).find('td');
tds.each(function () {
if ($.isNumeric($(this).text())) {
values.push($(this).text());
}
});
var min = Math.min.apply(Math, values);
var max = Math.max.apply(Math, values);
tds.each(function () {
if ($(this).text() == min) {
$(this).css('backgroundColor', 'red');
}
if ($(this).text() == max) {
$(this).css('backgroundColor', 'green');
}
});
});

you have to loop through all Table Rows and Table cells, throw them together in an array and compare the numbers then for the lowest and highest.
I will give you 2 Solutions for the styling, first one (better choice) via seperate css file styling, second one via inline jQuery Styling.
Here is an working example how it can be solved:
https://jsfiddle.net/efmkr08t/1/
$('#myPlaneTable').find('tr').not(':first').each(function(index, tr) {
var cols = [];
$(tr).find('td').not(':first').each(function(index, td) {
if ($(td).text() === '') {
return;
}
cols[index] = Number($(td).text());
});
var max = Math.max.apply(null, cols);
var min = Math.min.apply(null, cols);
$(tr).find('td').not(':first').each(function(index, td) {
if (Number($(td).text()) === min) {
// the way you should use it (styling is via css)
$(td).addClass('min')
// inline css
// $(td).css('background', 'red');
}
if (Number($(td).text()) === max) {
// the way you should use it (styling is via css)
$(td).addClass('max')
// inline css
// $(td).css('background', 'green');
}
});
});

Here I'm using jQuery map and toggleClass()
$(function(){
$('#myPlaneTable tr').each(function(index, tr) {
max = Math.max.apply(Math,$('td:not(:first)', tr).map(function(index, td) {
return parseInt($(td).text());
}));
min = Math.min.apply(Math,$('td:not(:first)', tr).map(function(index, td) {
return parseInt($(td).text());
}));
$(this).find('td').each( function(){
$(this).toggleClass('best',parseInt($(this).text())==max).toggleClass('worst', parseInt($(this).text())==min)
});
});
});
.best{
background-color:green;
}
.worst{
background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myPlaneTable" class="table table-bordered">
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">450</td>
<td style="width: 15%">487</td>
<td style="width: 15%">450</td>
<td style="width: 15%">600</td>
</tr>
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">580</td>
<td style="width: 15%">490</td>
<td style="width: 15%">543</td>
<td style="width: 15%">742</td>
</tr>
</table>

Related

Highlighting <td> column depending on value and row. Change existing jQuery script

The table that will populate depending on the selected dropdown element. There is an HTML code (I didn’t insert a line with dropdown and image)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="PlaneTable" class="table table-bordered">
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">450</td>
<td style="width: 15%">487</td>
<td style="width: 15%">450</td>
<td style="width: 15%">600</td>
</tr>
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">580</td>
<td style="width: 15%">490</td>
<td style="width: 15%">543</td>
<td style="width: 15%">742</td>
</tr>
<tr>
<td style="width: 20%">Climb</td>
<td style="width: 15%">52</td>
<td style="width: 15%">34</td>
<td style="width: 15%">23</td>
<td style="width: 15%">43</td>
</tr>
</table
<!-- And script what set green color to best value and red color to worse -->
<script>
$("#PlaneTable tbody tr").each(function() {
var values = [];
var tds = $(this).find('td');
tds.each(function() {
if ($.isNumeric($(this).text())) {
values.push($(this).text());
}
});
var min = Math.min.apply(Math, values);
var max = Math.max.apply(Math,
values);
tds.each(function() {
if ($(this).text() == min) {
$(this).css('backgroundColor', 'red');
}
if ($(this).text() == max) {
$(this).css('backgroundColor', 'green');
}
});
});
</script>
Finally i have this
I need to change my script for the next requirements:
Some data, for example, "Climb" row better if it has a lower value. IMHO better apply a script to row, not to the table. Also, some rows should not be highlighting.
If I add a label "km/h". For example 450 km/h highlighting don't work. Need to fix
If <td> have concrete value "null" (int nullable type), it should not be highlighting anytime
Consider the following.
$(function() {
function getNum(s) {
var n = false;
if (s.length) {
n = parseInt(s, 10);
}
return n;
}
function getRowData(t) {
var r = [],
n;
$("td", t).each(function(i, el) {
n = getNum($(el).text());
if (i > 0 && n) {
r.push(n);
}
});
return r;
}
$("#PlaneTable tbody tr").each(function(ind, row) {
var values = getRowData($(row));
var min = Math.min.apply(Math, values);
var max = Math.max.apply(Math, values);
console.log(values, min, max);
if ($("td", row).eq(0).text() == "Climb") {
$(row).addClass("low");
} else {
$(row).addClass("high");
}
$("td", row).each(function(j, cell) {
if ($(cell).text().indexOf(min) == 0 && $(".min", row).length < 1) {
$(this).addClass("min");
}
if ($(cell).text().indexOf(max) == 0 && $(".max", row).length < 1) {
$(cell).addClass("max");
}
});
});
});
.high .min {
background-color: red;
}
.high .max {
background-color: green;
}
.low .min {
background-color: green;
}
.low .max {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="PlaneTable" class="table table-bordered">
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">450 km/h</td>
<td style="width: 15%">487 km/h</td>
<td style="width: 15%">450 km/h</td>
<td style="width: 15%">600 km/h</td>
</tr>
<tr>
<td style="width: 20%">Max speed</td>
<td style="width: 15%">580 km/h</td>
<td style="width: 15%">490 km/h</td>
<td style="width: 15%">543 km/h</td>
<td style="width: 15%">742 km/h</td>
</tr>
<tr>
<td style="width: 20%">Climb</td>
<td style="width: 15%">52 km/h</td>
<td style="width: 15%">34 km/h</td>
<td style="width: 15%">23 km/h</td>
<td style="width: 15%"></td>
</tr>
</table>
References:
https://www.w3schools.com/jsref/jsref_indexof.asp
https://www.w3schools.com/jsref/jsref_parseint.asp
https://api.jquery.com/each/

filtering a html table based on a condition entered in textbox javascript

i have a html table that displays student name and the number of leaves he has taken.how do i filter giving a constraint on the no of leaves and display it
,like if enter 5 in the text box,students with leave of 5 or more should be filtered and displayed.
the code i have now display the records with the entered value
function myFunction1() {
var input, filter, table, tr, td, i;
input = document.getElementById("myInput1");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[6];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}
A jQuery version
var filter = $('#myInput1').val.toUpperCase();
$("#myTable tr td:eq(6)").each( function() {
var str = $(this).html().toUpperCase()
if( str.indexOf(filter) > -1)
$(this).parent('tr').css('display','')
else
$(this).parent('tr').css('display','none')
})
quick knock-together that does what you're looking for, from what I can understand. I have also used the same filter function to allow me to screen by name or by student-year. It's a flexible filter routine, wish I'd taken the time to avoid hard-wiring the handling of strings vs numbers, but for your purposes, that'd be overkill, I think.
A strange gotcha with table rows: you can't simply display="none" and display="block" them, it garbles the table structure. That's why it's display="none and display="" below. A few sources pointed that out, and I'm glad they did. I was beating my head on that wall for a while...
Best of luck!
// Store all the inputs...
var filterByName = document.getElementById("filter-by-name");
var filterByYear = document.getElementById("filter-by-year");
var filterByLeaves = document.getElementById("filter-by-leaves");
// And store the table itself.
var studentInfoTable = document.getElementsByClassName("student-info")[0];
// these functions will be called in the event listeners.
// By doing this, I only have a single filter function.
function byName() {
var filterString = filterByName.value;
filterBy("name", filterString);
};
function byYear() {
var filterString = filterByYear.value;
filterBy("year", filterString);
};
function byLeaves() {
var filterString = filterByLeaves.value;
filterBy("leaves", filterString);
};
/**
* The filter function itself, accepts the field to filter
* by and the string to use as the filter data.
* In essence, we take each row of the body, find the td
* to filter by, compare that with the filter data itself.
* There are two types of compare: either text or numeric.
*
**/
function filterBy(filter, filterString) {
var selector = ".student-" + filter;
var rows = studentInfoTable.querySelectorAll("tbody tr");
for (var i = 0; i < rows.length; i++) {
var filterEl = rows[i].querySelector(selector);
switch(filter) {
case "name":
if (filterEl.textContent.indexOf(filterString) == -1) {
rows[i].style.display = "none";
} else {
rows[i].style.display = "";
};
break;
case "year":
case "leaves":
if (parseInt(filterEl.textContent) >= parseInt(filterString) || filterString.length == 0) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
};
break;
}
}
};
// The event listeners for each input.
filterByName.addEventListener("keyup", byName);
filterByYear.addEventListener("keyup", byYear);
filterByLeaves.addEventListener("keyup", byLeaves);
.student-info {
font-family: Arial, sans-serif;
width: 100%;
table-layout: fixed;
}
thead {
font-weight: bold;
}
label {
display: block;
}
.student-name {
width: 40%;
}
.student-id,
.student-year,
.student-leaves {
width: 20%;
text-align: center;
}
<table class="student-info">
<thead>
<td class="student-name">Name</td>
<td class="student-id">S. Id</td>
<td class="student-year">Year</td>
<td class="student-leaves">Leaves</td>
</thead>
<tbody>
<tr>
<td class="student-name">Abraham Abas</td>
<td class="student-id">00141</td>
<td class="student-year">2018</td>
<td class="student-leaves">4</td>
</tr>
<tr>
<td class="student-name">Billy Bragg</td>
<td class="student-id">00143</td>
<td class="student-year">2018</td>
<td class="student-leaves">7</td>
</tr>
<tr>
<td class="student-name">Conor Chace</td>
<td class="student-id">00147</td>
<td class="student-year">2019</td>
<td class="student-leaves">5</td>
</tr>
<tr>
<td class="student-name">Daniel Daye</td>
<td class="student-id">00150</td>
<td class="student-year">2019</td>
<td class="student-leaves">0</td>
</tr>
<tr>
<td class="student-name">Edward Eppington</td>
<td class="student-id">00151</td>
<td class="student-year">2018</td>
<td class="student-leaves">6</td>
</tr>
<tr>
<td class="student-name">Frank Ford</td>
<td class="student-id">00153</td>
<td class="student-year">2020</td>
<td class="student-leaves">9</td>
</tr>
</tbody>
</table>
<div class="student-filter">
<h2>
Filter by...
</h2>
<label>Name:
<input type="text" id="filter-by-name">
</label>
<label>Year:
<input type="text" id="filter-by-year">
</label>
<label>Leaves:
<input type="text" id="filter-by-leaves">
</label>
</div>
Search Textbox:-
<label>Search:<input class="form-control input-sm" placeholder="" aria-controls="DataTables_Table_0" type="search" id="txtSearch" onkeyup="filter(this);"></label>
Script:-
function filter(element) {
var value = $(element).val();
$("#DataTables_Table_1 tr").each(function () {
if ($(this).text().search(value) > -1) {
$(this).show();
}
else {
$(this).hide();
}
});
}

Remove/Hide Table <tr>(s) which Their <td>(s) Does not Have Text

Can you please take a look at this demo and let me know how I can hide or remove all rows in a dynamic table that their <td> (if all of them in a row) are empty? This is mainly happend at the end of the table since I generated a table with 5 rows but some times I am getting only 3 or 4 rows data from the data source.
Please be informed that by empty I mean a text value not a html element like div.
<table style="width:100%">
<tr>
<td class="monBox">Jill</td>
<td class="monBox">Smith</td>
<td class="monBox">50</td>
</tr>
<tr>
<td class="monBox">Eve</td>
<td class="monBox">Jackson</td>
<td class="monBox">94</td>
</tr>
<tr>
<td class="monBox"></td>
<td class="monBox"></td>
<td class="monBox"></td>
</tr>
<tr>
<td class="monBox">Eve</td>
<td class="monBox">Jackson</td>
<td class="monBox">94</td>
</tr>
<tr>
<td class="monBox"></td>
<td class="monBox"></td>
<td class="monBox"></td>
</tr>
</table>
Thanks
Try going through each tr and checking if all td elements inside are empty like so
$('table').find('tr').each (function() {
var rows = 0;
var rows_empty = 0;
$(this).find('td').each (function() {
rows++;
if($(this).text().trim() == "")
rows_empty++;
});
if(rows === rows_empty)
$(this).remove();
});
jsfiddle
Try this, note I've given the table an ID of target:
//Loop through rows with empty cells
$("#target tr").has("td:empty").each(function(){
//hide the row if all cells are empty
if($(this).find("td").length === $(this).find("td:empty").length){
$(this).hide();
}
});
Fiddle
Or slightly simpler:
$("#target tr").has("td:empty").each(function(){
if($(this).find("td:not(:empty)").length === 0){
$(this).hide();
}
});
Or Better Still:
$('#target tr').not(':has(td:not(:empty))').remove();
Demo
$('#target tr').each(function(index,el).
{
if($.trim($(this).text()) == '')
{
$(this).remove();
}
}
);
It works without checking table cells at all

jquery dynamic for each loop issue

I have a table that has several tables in it for multiple users. These users can increase or decrease overtime, so I am trying to make it as dynamic as possible. I will attach two sample tables so you get the idea.
<div class="timecard">
<h3>tommytest</h3>
<table class="misc_items timecard_list" border="0" cellpadding="2" cellspacing="0" style="margin:0 auto;">
<tbody>
<tr class="display_row odd">
<td align="left" class="job_code" style="color:#000099">2400-Orchard</td>
<td align="right">9:47am</td>
<td align="right">5/19/2014</td>
<td align="right" class="hrs">01:00</td>
</tr>
<tr class="display_odd row">
<td align="left" class="job_code" style="color:#000099">1200-Duffy's</td>
<td align="right">12:37am</td>
<td align="right">5/17/2014</td>
<td align="right" class="hrs">2:00</td>
</tr>
</tbody>
</table>
</div>
<div class="timecard">
<h3>testtest</h3>
<table class="misc_items timecard_list" border="0" cellpadding="2" cellspacing="0" style="margin:0 auto;">
<tbody>
<tr class="display_row odd">
<td align="left" class="job_code" style="color:#000099">2400-Orchard</td>
<td align="right">9:47am</td>
<td align="right">5/19/2014</td>
<td align="right" class="hrs">01:00</td>
</tr>
<tr class="display_odd row">
<td align="left" class="job_code" style="color:#000099">1200-Duffy's</td>
<td align="right">12:37am</td>
<td align="right">5/17/2014</td>
<td align="right" class="hrs">2:00</td>
</tr>
</tbody>
</table>
</div>
<div id="total"></div>
I then have a jQuery script run through the table and then calculate the total of each individual job_code and display it underneath the table so that it looks like this:
job_code 1 = 2 hours
job_code 2 = 4 hours
I am having trouble making my below javascript calculate the first table, display the results, then move on to the next table and do the same thing. So on and so forth.
$(document).ready(function () {
var timeString = $(this).next('td.hrs').text();
var components = timeString.split(':');
var seconds = components[1] ? parseInt(components[1], 10) : 0;
var hrs = parseInt(components[0], 10) + seconds / 60;
total += hrs;
var temp = [];
$('.job_code').each(function (index, element) {
var text = $(this).text();
if (text != 'Out') {
temp.push(text);
}
});
// remove duplicates
var job_code = [];
$.each(temp, function (index, element) {
if ($.inArray(element, job_code) === -1) job_code.push(element);
});
var sum = {};
$.each(job_code, function (index, element) {
var total = 0;
$('.job_code:contains(' + element + ')').each(function (key, value) {
var timeString = $(this).siblings('td.hrs').text();
var components = timeString.split(':');
var seconds = components[1] ? parseInt(components[1], 10) : 0;
var hrs = parseInt(components[0], 10) + seconds / 60;
total += hrs;
sum[index] = {
'job_code': element,
'total': total
};
});
});
console.log(sum);
$.each(sum, function (index, element) {
$('#total').append('<p>Total for ' + element.job_code + ': ' + element.total + '</p>');
});
});
Any advice would be greatly appreciated as I am just starting to use javascript and am quickly reaching the end of my capabilities. Here is a link to a sample JSfiddle
Thanks in advance
First of all why not to make any calculations before formatting and layout generation? I would be much easier.
Anyway if you want to iterate tables then iterate some data in it, try to use something like this:
$('.timecard_list').each(function() {
$(this).find('.job_code').each(function() {
...
});
});

Highlight repeating strings

I have up to three almost-identical divs that contain tables of usernames. Some names may be repeated across the three divs. I'd like to highlight the names that are repeated. The first occurrence of the user should not be colored, the second occurrence should have an orange background and the third should have a red background. The divs go from left to right in order so the first div should not have any highlighted usernames.
My HTML looks like:
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/26/2014</th>
</tr>
<tr>
<td>user1</td>
</tr>
<tr>
<td>user2</td>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user17</td>
</tr>
</table>
</div>
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/27/2014</th>
</tr>
<tr>
<td>user13</td>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user7</td>
</tr>
</table>
</div>
<div class="col-md-4">
<table class="table table-striped">
<tr>
<th>2/28/2014</th>
</tr>
<tr>
<td>user5</td>
</tr>
<tr>
<td>user45</td>
</tr>
<tr>
<td>user1</td>
</tr>
</table>
</div>
I know that the username table cells will be selected with $('table.table td') (if I use jQuery) but I'm not sure what to do from there.
Please let me know if you have any questions.
Thank you.
Is this what you want?
I created a map to store text-occurrence pairs. Each time the text is repeated, the counter associated with it gets incremented. If the counter climbs to a certain value, the background will be set to another color. Give it a shot!
DEMO
var map = new Object();
$('td').each(function() {
var prop = $(this).text()
var bgColor = '#FFFFFF';
if (map[prop] > 1) {
bgColor = '#FF0000';
} else if (map[prop] > 0) {
bgColor = '#FF7F00';
}
$(this).css('background', bgColor);
if (map.hasOwnProperty(prop)) {
map[prop]++;
} else {
map[prop] = 1;
}
});
You could try something like this but I didn't test it
$('td').each(function(){
var text = this.html();
$('td:contains("'+text+'"):nth-child(2)').css({'background':'orange'});
$('td:contains("'+text+'"):nth-child(3)').css({'background':'red'});
});
Edit:
Not particularly elegant but it seems to work
http://jsfiddle.net/63L7L/1/
var second = [];
var third = [];
$('td').each(function(){
var text = $(this).html();
second.push($("td").filter(function() {
return $(this).text() === text;
})[1])
third.push($("td").filter(function() {
return $(this).text() === text;
})[2])
});
$(second).each(function(){
$(this).css({'background':'red'});
});
$(third).each(function(){
$(this).css({'background':'orange'});
});
With pure Javascript (ECMA5)
CSS
.orange {
background-color:orange;
}
.red {
background-color:red;
}
Javascript
Array.prototype.forEach.call(document.querySelectorAll('.table-striped td'), function (td) {
var textContent = td.textContent;
if (this.hasOwnProperty(textContent)) {
td.classList.add(++this[textContent] === 2 ? 'orange' : 'red');
} else {
this[textContent] = 1;
}
}, {});
On jsFiddle

Categories

Resources