How can i remove content and give background in table - javascript

So, i want to achieve this
Here is what i do so far
$('.table tbody tr').each(function() {
var tr = $(this);
var th = tr.find('td:first-child').attr('class');
var td = tr.find('td').attr('class');
//the match box will be red, only the the td of row
if (th == td) {
//important background red
tr.find('td').attr('style', 'background-color: red !important');
}
});
with my script above, i can't achieve the result. Here is the result
Here is my table in html
<table class="table table-bordered table-auto text-center">
<thead>
<tr>
<th>#</th>
<th class="COL1">COL1</th>
<th class="COL2">COL2</th>
<th class="COL3">COL3</th>
<th class="COL4">COL4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="COL1">COL1</td>
<td>0 %</td>
<td>13.5 %</td>
<td>18.9 %</td>
<td>5.4 %</td>
</tr>
<tr>
<td class="COL2">COL2</td>
<td>29.7 %</td>
<td>0 %</td>
<td>2.7 %</td>
<td>0 %</td>
</tr>
<tr>
<td class="COL3">COL3</td>
<td>18.9 %</td>
<td>8.1 %</td>
<td>0 %</td>
<td>2.7 %</td>
</tr>
<tr>
<td class="COL4">COL4</td>
<td>0 %</td>
<td>0 %</td>
<td>0 %</td>
<td>0 %</td>
</tr>
</tbody>
</table>
So how can i achieve it ? thanks in advance

Iterate the nodelist and check its index
Given a table cell of row index i and column index j, you'd like to change the cell background to red if i===j, correct?
In the snippet below, I did:
Select all table rows (i.e. tr)
Iterate each table row, and select all of its child cells (i.e. td)
Change the background color of the td cell of ith index to red.
No HTML markup has been changed, but a few simple CSS lines are added just to make it a bit nicer. This should work even if the table's column and row counts change.
const rows = document.querySelectorAll('tr');
rows.forEach((row, i) => {
const children = row.querySelectorAll('td');
return i === 0 ? null : children[i].style.background = "red";
});
th, td {
padding: 10px;
}
th, td:first-of-type {
background: #ddf;
}
td {
background: #eee;
}
td:first-of-type {
}
<table class="table table-bordered table-auto text-center">
<thead>
<tr>
<th>#</th>
<th class="COL1">COL1</th>
<th class="COL2">COL2</th>
<th class="COL3">COL3</th>
<th class="COL4">COL4</th>
</tr>
</thead>
<tbody>
<tr>
<td class="COL1">COL1</td>
<td>0 %</td>
<td>13.5 %</td>
<td>18.9 %</td>
<td>5.4 %</td>
</tr>
<tr>
<td class="COL2">COL2</td>
<td>29.7 %</td>
<td>0 %</td>
<td>2.7 %</td>
<td>0 %</td>
</tr>
<tr>
<td class="COL3">COL3</td>
<td>18.9 %</td>
<td>8.1 %</td>
<td>0 %</td>
<td>2.7 %</td>
</tr>
<tr>
<td class="COL4">COL4</td>
<td>0 %</td>
<td>0 %</td>
<td>0 %</td>
<td>0 %</td>
</tr>
</tbody>
</table>

Related

Get all tr in table between tr with table-primary class and push in array

At the click of the button #create-arrays I need to create multiple arrays. Each array will contain the set of tr (not .table-primary) present between the two tr (previous and next) with class table primary. this set of tr will be called context. Using jquery, how can I identify any such context and place it in an array? Thanks to everyone who will help.
HTML part (for testing):
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<table class="table table-sm">
<thead>
</thead>
<tbody>
<tr class="table-primary">
<td colspan="2">Group 1</td>
</tr>
<tr>
<td>Name: Jonh</td>
<td>Surname: Doe</td>
</tr>
<tr>
<td>Name: Mark</td>
<td>Surname: Lon</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 2</td>
</tr>
<tr>
<td>Name: Will</td>
<td>Surname: Man</td>
</tr>
<tr>
<td>Name: Ben</td>
<td>Surname: Harper</td>
</tr>
<tr>
<td>Name: Mitch</td>
<td>Surname: Collins</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 3</td>
</tr>
<tr>
<td>Name: Serena</td>
<td>Surname: Mellin</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 4</td>
</tr>
<tr>
<td>Name: Nickolas</td>
<td>Surname: Malinof</td>
</tr>
<tr>
<td>Name: David</td>
<td>Surname: Benner</td>
</tr>
<tr>
<td>Name: Lenny</td>
<td>Surname: Doe</td>
</tr>
<tr>
<td>Name: Micheal</td>
<td>Surname: Pitzford</td>
</tr>
<tr>
<td>Name: Melania</td>
<td>Surname: Bebant</td>
</tr>
</tbody>
</table>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</body>
</html>
the jquery script that i use to get all the tr inside tbody.
$('#create-arrays').on('click', function(){
var context = [];
var a = $('#file_table_available tbody tr');
console.log(a);
for (let i = 0; i < a.length; i++) {
const element = a[i];
}
})
You're off to a good start looping over all rows in the table.
You could check each row (element in your snippet) for the existance of the table-primary class. If the row has this class, you know you have to create a new group.
Here's a vanilla javascript example. It outputs an array of groups. Each group contains 1 or more rows that belong together.
const rows = document.querySelectorAll("tr");
const groups = [];
let group = null;
for (const row of rows) {
if (row.classList.contains("table-primary")) {
group = [];
groups.push(group);
} else {
group.push(row);
}
}
console.log(groups);
<table class="table table-sm">
<thead>
</thead>
<tbody>
<tr class="table-primary">
<td colspan="2">Group 1</td>
</tr>
<tr>
<td>Name: Jonh</td>
<td>Surname: Doe</td>
</tr>
<tr>
<td>Name: Mark</td>
<td>Surname: Lon</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 2</td>
</tr>
<tr>
<td>Name: Will</td>
<td>Surname: Man</td>
</tr>
<tr>
<td>Name: Ben</td>
<td>Surname: Harper</td>
</tr>
<tr>
<td>Name: Mitch</td>
<td>Surname: Collins</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 3</td>
</tr>
<tr>
<td>Name: Serena</td>
<td>Surname: Mellin</td>
</tr>
<tr class="table-primary">
<td colspan="2">Group 4</td>
</tr>
<tr>
<td>Name: Nickolas</td>
<td>Surname: Malinof</td>
</tr>
<tr>
<td>Name: David</td>
<td>Surname: Benner</td>
</tr>
<tr>
<td>Name: Lenny</td>
<td>Surname: Doe</td>
</tr>
<tr>
<td>Name: Micheal</td>
<td>Surname: Pitzford</td>
</tr>
<tr>
<td>Name: Melania</td>
<td>Surname: Bebant</td>
</tr>
</tbody>
</table>

Change background of entire table row

I'm looking to make the entire row of a table change colour (either the background colour or text colour) based on the value of the column labelled "Status". If the value in the "Status" column is "Expired" the background of the entire row should change.
(Edit: The data is going to be pulled dynamically from a database).
Any suggestions?
HTML Code
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>
Thanks in advance.
If you can change how the table is rendered than I would just add the text as a class. This will be the best performance option and requires no JavaScript and the content will not flash.
tr.Expired td {
background-color: red;
}
tr.Active td {
background-color: green;
}
<table>
<thead>
<tr>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr class="Active">
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr class="Expired">
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</tbody>
</table>
Or you will need to run JavaScript code that reads the cell value and adds the class.
$("tr:has(td:last:contains('Expired'))").addClass("Expired");
tr.Expired td {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</tbody>
</table>
try using CSS only adding a class to the tr.
tr.active > td {
background-color: green;
}
tr.expired > td {
background-color: red;
}
https://jsfiddle.net/jt717mL8/
In your case the status column is the 5th. So you may do something like:
$('table tr:gt(0)').each(function(idx, ele) {
if ($(ele).find('td:eq(4)').text() == 'Expired') {
$(ele).css('backgroundColor', 'yellow');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>
You can first get index of status th and then check each td with same index and check its text.
var i = $('th:contains(Status)').index();
$('tr').each(function() {
var td = $(this).find('td').eq(i);
if (td.text() == 'Expired') td.css('background', 'red')
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<th>Bonus Competitions</th>
<th>Value</th>
<th>Link</th>
<th>Expires</th>
<th>Status</th>
<tr>
<td>Cash</td>
<td>£500</td>
<td>Link
</td>
<td>18-Feb-17</td>
<td>Active</td>
</tr>
<tr>
<td>Sports Car</td>
<td>£5000</td>
<td>Link
</td>
<td>18-Jan-17</td>
<td>Expired</td>
</tr>
</table>

jsPDF - Header table with rowspan and colspan attributes

Based in this example I need to export the respective table but for some reason the pdf file generated doesn't recognize the rowspan and colspan attributes and the generated table looks different.
HTML view
<table id="table" border="1">
<thead>
<tr>
<th rowspan="2">ID</th>
<th colspan="2">Names</th>
<th rowspan="2">Email</th>
<th colspan="2">Addresses</th>
</tr>
<tr>
<th>First name</th>
<th>Last name</th>
<th>IP-address1</th>
<th>IP-address2</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">1</td>
<td>Donna</td>
<td>Moore</td>
<td>dmoore0#furl.net</td>
<td>211.56.242.221</td>
<td>211.56.242.221</td>
</tr>
<tr>
<td align="right">2</td>
<td>Janice </td>
<td>Henry</td>
<td>jhenry1#theatlantic.com</td>
<td>38.36.7.199</td>
<td>38.36.7.199</td>
</tr>
<tr>
<td align="right">3</td>
<td>Ruth</td>
<td>Wells</td>
<td>rwells2#constantcontact.com</td>
<td>19.162.133.184</td>
<td>19.162.133.184</td>
</tr>
<tr>
<td align="right">4</td>
<td>Jason</td>
<td>Ray</td>
<td>jray3#psu.edu</td>
<td>10.68.11.42</td>
<td>10.68.11.42</td>
</tr>
<tr>
<td align="right">5</td>
<td>Jane</td>
<td>Stephens</td>
<td>jstephens4#go.com</td>
<td>47.32.129.71</td>
<td>47.32.129.71</td>
</tr>
<tr>
<td align="right">6</td>
<td>Adam</td>
<td>Nichols</td>
<td>anichols5#com.com</td>
<td>18.186.38.37</td>
<td>18.186.38.37</td>
</tr>
<tr>
<td align="right">6</td>
<td>Adam</td>
<td>Nichols</td>
<td>anichols5#com.com</td>
<td>18.186.38.37</td>
<td>18.186.38.37</td>
</tr>
<tr>
<td align="right">6</td>
<td>Adam</td>
<td>Nichols</td>
<td>anichols5#com.com</td>
<td>18.186.38.37</td>
<td>18.186.38.37</td>
</tr>
</tbody>
Script
function createPDF(){
var doc = new jsPDF('p', 'pt', 'letter');
var IDtable = document.getElementById('table');
var tableSource = doc.autoTableHtmlToJson(IDtable);
doc.autoTable(tableSource.columns, tableSource.data, {startY: doc.autoTableEndPosY() + 40, theme: 'grid'});
doc.save("file.pdf")
}
In the latest version rowspans and colspans are automatically handled so this should be enough.
var doc = new jsPDF();
doc.autoTable({html: '#table'});
doc.save("file.pdf")

Aligning data vertically in td elements for horizontally connected rows using jquery

I've html in the below format.
<head><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script></head>
<script type="text/javascript">
$(document).ready(function(){
var dups = $('.comps + .comps');
dups.remove();
});
var list1 = [1,2,3,4,5,6];
var list2 = [6,5,4,3,2,1];
</script>
<div class="serverSet">
<h2>JH Storefront servers</h2>
<table border="1" class="CSSTableGenerator" class="myTable">
<tr>
<th>Component</th>
<th>Properties</th>
<th class="servers"> lqwasc10 </th>
<th class="servers"> lqwasc11 </th>
</tr>
<tr>
<td class="comps">DeliveryMethodsRepository</td>
<td class="props">externalCacheBatchInfoSize</td>
<tr/>
<tr/>
<td class="comps">InventoryManager</td>
<td class="comps">InventoryManager</td>
<td class="props">itemType</td>
</tr>
<tr>
<td class="comps">InventoryManager</td>
<td class="props">maxConcurrentUpdateRetries</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="comps">CatalogTools</td>
<td class="props">queryASAFFabrics</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="props">loggingDebug</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="props">outOfStockCode</td>
</tr>
<tr>
</table>
</div>
In the above jquery function, list1 and list2 are horizontally connected to lqwasc10 and lqwasc11 respectively. Is there a way I can align list1 and list2 vertically along with existing td elements of Components and Properties in their respective orders.
I've tried a lot and couldn't get hold of the logic. It would be great if someone can answer.
I'm expecting data in the format as shown in the screenshot.
You can merely add the desired <td>s just after removing duplicates, like this:
var list1 = [1,2,3,4,5,6];
var list2 = [6,5,4,3,2,1];
$(document).ready(function(){
$('.comps + .comps').remove();
$('.myTable tr').each(function(i) {
if (i > 0) {
$(this)
.append('<td>' + list1[i - 1] + '</td>')
.append('<td>' + list2[i - 1] + '</td>');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="serverSet">
<h2>JH Storefront servers</h2>
<table border="1" class="myTable">
<tr>
<th>Component</th>
<th>Properties</th>
<th class="servers"> lqwasc10 </th>
<th class="servers"> lqwasc11 </th>
</tr>
<tr>
<td class="comps">DeliveryMethodsRepository</td>
<td class="props">externalCacheBatchInfoSize</td>
</tr>
<tr>
<td class="comps">InventoryManager</td>
<td class="comps">InventoryManager</td>
<td class="props">itemType</td>
</tr>
<tr>
<td class="comps">InventoryManager</td>
<td class="props">maxConcurrentUpdateRetries</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="comps">CatalogTools</td>
<td class="props">queryASAFFabrics</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="props">loggingDebug</td>
</tr>
<tr>
<td class="comps">CatalogTools</td>
<td class="props">outOfStockCode</td>
</tr>
</table>
</div>
Please note that this snippet works only after correcting HTML errors: <tr> inconsistency (already noticed by comments), duplicate class attribute on <table>.

How can I get the relative header of a cell?

I have a very unusual table. I am struggling to be able to return the relative header of a specific element, as per this http://jsfiddle.net/yh6C6/
The table structure is similar to the following:
<table border>
<tbody>
<tr>
<th></th>
<th></th>
<th colspan="3">Parameter 1</th>
<th colspan="2">Parameter 2</th>
</tr>
<tr>
<td></td>
<td></td>
<td>
<div>
<div>State 1.1</div>
</div>
</td>
<td>
<div>
<div>State 1.2</div>
</div>
</td>
<td>
<div>
<div>State 1.3</div>
</div>
</td>
<td>
<div>
<div>State 2.1</div>
</div>
</td>
<td>
<div>
<div>State 2.2</div>
</div>
</td>
</tr>
<tr>
<th rowspan="2">Parameter 2</th>
<td>State 2.1</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
</tr>
<tr>
<td>State 2.2</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
</tr>
<tr>
<th rowspan="3">Parameter 3</th>
<td>State 3.1</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
</tr>
<tr>
<td>State 3.2</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
</tr>
<tr>
<td>State 3.3</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
<td contenteditable="true">-</td>
</tr>
</tbody>
</table>
Assuming you click on the 'contenteditable' cells, how can I return the row and column headers? Please check the jsfiddle provided above.
I've edited the fiddle to get the horizontal parameter.
Needed to add a class to each tr that contained a parameter name. Also coloured the selected tr to make it easier to visualize and debug what is being selected. Getting the vertical parameter name will be a different problem.
I was able to get it by doing the following:
$(document).ready(function () {
$('table').on('click', 'td[contenteditable]', function (e) {
// Horizontal Parameter
if ($(this).parent().has('th').length > 0) {
hParameter = $(this).parent().find('th').text();
} else {
hParameter = $(this).parent().prevAll('tr').has('th').first().find('th').text();
}
$('#horizontal-parameter').text('H: ' + hParameter);
// Vertical Parameter
var thLocator = [],
colCount = 1;
$table = $('table');
$table.find('tr:first th').each(function () {
for (var i = 0; i < this.colSpan; i++) {
thLocator.push(colCount);
}
colCount++;
});
vParameter = $table.find('tr:first th:nth-child(' + thLocator[$(this).index()] + ')').text();
$('#vertical-parameter').text('V: ' + vParameter);
});
});

Categories