Looking to replace all the "?" in the table below with the expected values.
Should I just add classes to the <th> that has a value in them and add them?
<table id="repair-invoice">
<tr>
<th>Item</th>
<th>Parts</th>
<th>Labor</th>
<th>Total</th>
</tr>
<tr>
<td>Automatic Transmission Replacement</td>
<td>$1,809.99</td>
<td>$830.00</td>
<td>?</td>
</tr>
<tr>
<td>Exhaust system replace</td>
<td>$279.99</td>
<td>$225.00</td>
<td>?</td>
</tr>
<tr>
<td>Replace air filter</td>
<td>$9.99</td>
<td>$0.00</td>
<td>?</td>
</tr>
<tr>
<td colspan="3">Total</td>
<td>?</td>
</tr>
</table>
You can iterate over the row/column combination and sum of the values like
var sum = 0;
$('#repair-invoice tr').slice(1, -1).each(function() {
var $tr = $(this),
total = 0;
$tr.find('td').slice(1, -1).each(function() {
total += +$(this).text().replace(/\$|,/g, '') || 0;
});
$tr.find('td:last-child').text(total);
sum += total;
});
$('#repair-invoice tr:last-child td:last-child').text(sum.toFixed(2)); //will have to format and display the value
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="repair-invoice">
<tr>
<th>Item</th>
<th>Parts</th>
<th>Labor</th>
<th>Total</th>
</tr>
<tr>
<td>Automatic Transmission Replacement</td>
<td>$1,809.99</td>
<td>$830.00</td>
<td>?</td>
</tr>
<tr>
<td>Exhaust system replace</td>
<td>$279.99</td>
<td>$225.00</td>
<td>?</td>
</tr>
<tr>
<td>Replace air filter</td>
<td>$9.99</td>
<td>$0.00</td>
<td>?</td>
</tr>
<tr>
<td colspan="3">Total</td>
<td>?</td>
</tr>
</table>
In case you want to follow D.R.Y :
function removeDollar(num) {
return num.substring(1, num.length);
}
function parseCurrency(num) {
return parseFloat(removeDollar(num).replace(/,/g, ''));
}
function addNumbers(num1, num2) {
return parseFloat(num1) + parseFloat(num2);
}
$(document).ready(function () {
var parts = [];
var labor = [];
for (var i = 0; i < 3; i++) {
parts[i] = $("#repair-invoice > tbody > tr:nth-child("+(2+i)+") > td:nth-child(2)").text();
labor[i] = $("#repair-invoice > tbody > tr:nth-child("+(2+i)+") > td:nth-child(3)").text();
$("#repair-invoice > tbody > tr:nth-child(" + (2 + i) + ") > td:nth-child(4)").html('$'+addNumbers(parseCurrency(parts[i]) , parseCurrency(labor[i])));
}
var Total = 0;
for (var i = 0; i <3; i++) {
var rowTotal = parseCurrency($("#repair-invoice > tbody > tr:nth-child(" + (2 + i) + ") > td:nth-child(4)").text());
Total = addNumbers(Total, rowTotal);
}
$("#repair-invoice > tbody > tr:nth-child(5) > td:nth-child(2)").html('$' + Total.toFixed(2));
});
Related
I want the first header of the table sorted after page load. I am new to Javascript and jQuery and I am not fully understanding the code. So I don't know where in the code I can select the first header. So far it is not running. (interesting would also be to hide the table until it is sorted and then show it).
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
</table>
jQuery(document).ready(function() {
sortLoad();
});
function sortLoad() {
var table = jQuery('table').eq(0)
var rows = table.find('tr:gt(0)').toArray().sort(comparer(jQuery(this).index()))
this.asc = !this.asc
if (!this.asc){rows = rows.reverse()}
for (var i = 0; i < rows.length; i++){table.append(rows[i])}
}
function comparer(index) {
return function(a, b) {
var valA = getCellValue(a, index), valB = getCellValue(b, index)
return jQuery.isNumeric(valA) && jQuery.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
}
}
function getCellValue(row, index){ return jQuery(row).children('td').eq(index).text() }
I made a universal sorter for one project. It is working. I hope it will help you somehow.
HTML
<table class="table table-bordered table-hover sortable" sort-id="UV68">
<thead class="thead-dark">
<tr class="sorter_row">
<th class="sorter" dir="-1">
<span>
Col 1
</span>
</th>
<th class="sorter active_up" dir="1">
<span>
Col 2
</span>
</th>
<th class="sorter" dir="-1">
<span>
Col 3
</span>
</th>
</tr>
</thead>
<tbody class="sorted_part">
<tr class="sorted_row">
<td>
<span class="sorted">
Alpha
</span>
</td>
<td>
<span class="table_user_id sorted">
1
</span>
</td>
<td>
<span class="sorted" sort-value="11273.67">
3
</span>
</td>
</tr>
<tr class="sorted_row">
<td>
<span class="sorted">
Beta
</span>
</td>
<td>
<span class="table_user_id sorted">
2
</span>
</td>
<td>
<span class="sorted" sort-value="5111">
2
</span>
</td>
</tr>
<tr class="sorted_row">
<td>
<span class="sorted">
Gamma
</span>
</td>
<td>
<span class="table_user_id sorted">
3
</span>
</td>
<td>
<span class="sorted" sort-value="0">
1
</span>
</td>
</tr>
</tbody>
</table>
JS (jQuery)
$(document).on ("click", ".sortable .sorter", function () {
var $me = $(this);
var $table = $me.parents (".sortable");
var tableIndex = $table.attr ("sort-id");
var col = $me.index (".sortable[sort-id='" + tableIndex + "'] .sorter"); //Number ($me.attr("sorter-col"));
var $rows = {};
var values = {};
var $sortedPart = $table.find (".sorted_part");
var $sortedRows = $table.find (".sorted_row");
var dir = $me.attr ("dir");
var rowIndex = 1;
var $row, $cell, rowValue, x, y, index, sorted;
dir = (dir == 1 ? -1 : 1);
$table.find (".sorter").removeClass ("active_up").removeClass ("active_down");
$table.find (".sorter").attr ("dir", "-1");
if (dir == 1) {
$me.addClass ("active_up");
$me.attr ("dir", "1");
}
else {
$me.addClass ("active_down");
$me.attr ("dir", "-1");
}
$sortedRows.each (function () {
$row = $(this);
$cell = $row.find(".sorted").eq(col);
rowValue = $cell.attr ("sort-value");
if (rowValue === undefined) {
rowValue = $cell[0].innerText;
}
if (rowIndex !== undefined && rowValue !== undefined) {
$rows[rowIndex] = $row;
values[rowIndex] = rowValue;
}
rowIndex ++;
});
sorted = Object.entries (values).sort(function (a, b) {
x = a[1];
y = b[1];
if (! isNaN (Number (x)) && ! isNaN (Number (y))) {
return (x - y);
}
else {
x = String (x).toLowerCase ();
y = String (y).toLowerCase ();
return (x < y ? -1 : x > y ? 1 : 0);
}
});
$sortedRows.each (function () {
$(this).remove ();
});
if (dir == -1) {
sorted.reverse ();
}
for (i in sorted) {
index = sorted[i][0];
$sortedPart.append ($rows[index]);
}
});
Are there any errors in the console? Make sure that jquery.js is connected before your code.
I have mockup like this
The HTML table to work with
The table above will calculate subtotal and total_harga using the entered value in jumlah. Calculations work fine, but my code is still using static JavaScript.
If there are a lot of rows in the table, it will be troublesome, if you have to write the getElementById code for all the inputs. How to use looping so that all the inputs can be handled without describing the table rows one by one. This is my HTML and JavaScript.
<div class="container">
<table class="tg" id="sales">
<thead>
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tg-0lax">1</td>
<td class="tg-0lax">MIE INSTAN</td>
<td class="tg-keyup"> <input type="text" id="input1" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan1">5000</td>
<td class="tg-0lax" id="diskon_satuan1">500</td>
<td class="tg-0lax" id="sub_total1"></td>
</tr>
<tr>
<td class="tg-0lax">2</td>
<td class="tg-0lax">SUSU UHT</td>
<td class="tg-keyup"><input type="text" id="input2" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan2">6000</td>
<td class="tg-0lax" id="diskon_satuan2">1000</td>
<td class="tg-0lax" id="sub_total2"></td>
</tr>
<tr>
<td class="tg-0lax">3</td>
<td class="tg-0lax">KERIPIK</td>
<td class="tg-keyup"> <input type="text" id="input3" name="fname" onkeyup="CalculationPrice()" placeholder="Masukan jumlah"><br></td>
<td class="tg-0lax" id="harga_satuan3">8000</td>
<td class="tg-0lax" id="diskon_satuan3">500</td>
<td class="tg-0lax" id="sub_total3"></td>
</tr>
<tr>
<td class="tg-0lax"></td>
<td class="tg-1lax" colspan="4">TOTAL HARGA</td>
<td class="tg-0lax" id="total_price"></td>
</tr>
</tbody>
</table>
this is my code javascript :
function CalculationPrice() {
let input1 = document.getElementById("input1").value;
let input2 = document.getElementById("input2").value;
let input3 = document.getElementById("input3").value;
let hargaSatuan1 = document.getElementById("harga_satuan1").innerText;
let hargaSatuan2 = document.getElementById("harga_satuan2").innerText;
let hargaSatuan3 = document.getElementById("harga_satuan3").innerText;
let diskonSatuan1 = document.getElementById("diskon_satuan1").innerText;
let diskonSatuan2 = document.getElementById("diskon_satuan2").innerText;
let diskonSatuan3 = document.getElementById("diskon_satuan3").innerText;
if(input1.length == 0){
let total1 = document.getElementById("sub_total1").innerHTML = 0;
}else if(input1.length > 0){
let subinput = (parseInt(hargaSatuan1) - parseInt(diskonSatuan1)) * parseInt(input1)
let total1 = document.getElementById("sub_total1").innerHTML = subinput;
}
if(input2.length == 0){
let total2 = document.getElementById("sub_total2").innerHTML = 0;
}
else if(input2.length > 0){
let subinput2 = (parseInt(hargaSatuan2) - parseInt(diskonSatuan2)) * parseInt(input2)
let total2 = document.getElementById("sub_total2").innerHTML = subinput2;
}
if(input3.length == 0){
let total3 = document.getElementById("sub_total3").innerHTML = 0;
}
else if(input3 !== null){
let subinput3 = (parseInt(hargaSatuan3) - parseInt(diskonSatuan3)) * parseInt(input3)
let total3 = document.getElementById("sub_total3").innerHTML = subinput3;
}
let total1 = document.getElementById("sub_total1").innerText
let total2 = document.getElementById("sub_total2").innerText
let total3 = document.getElementById("sub_total3").innerText
let total_price = parseInt(total1) + parseInt(total2) + parseInt(total3)
let totalPriceHtml = document.getElementById("total_price").innerHTML = formatRupiah(total_price, "Rp.");
}
function formatRupiah(angka, prefix) {
let number_string = angka.toString().replace(/[^,\d]/g, ""),
split = number_string.split(","),
sisa = split[0].length % 3,
rupiah = split[0].substr(0, sisa),
ribuan = split[0].substr(sisa).match(/\d{3}/gi);
if (ribuan) {
separator = sisa ? "." : "";
rupiah += separator + ribuan.join(".");
}
rupiah = split[1] != undefined ? rupiah + "," + split[1] : rupiah;
return prefix == undefined ? rupiah : rupiah ? "Rp. " + rupiah : "";
}
Using ids on a table makes a lot of unnecessary work, it's much easier to rely on the structure of a static table. And, instead of inline event handlers, we can benefit from event delegation. Here's an example of how to listen input event on tbody and a simple reduce loop to calculate the total sum of subtotals.
const tbody = document.querySelector('#sales'),
rows = Array.from(tbody.rows), // All the rows of the tbody
total = rows.pop().cells[2]; // The TOTAL HARGA cell
function calcTot(e) {
const value = +e.target.value || 0,
rowIndex = e.target.closest('tr').rowIndex - 1, // Constant 1 = the amount of the rows in thead
cells = Array.from(rows[rowIndex].cells),
harga = +cells[3].textContent,
diskon = +cells[4].textContent,
sub = cells[5];
sub.textContent = harga - diskon * value;
total.textContent = rows.reduce((acc, row) => {
return acc += +row.cells[5].textContent;
}, 0);
}
// Calculate the first sums
rows.forEach(row => {
// Call calcTot with a fake event object
calcTot({target: row.cells[2]});
});
tbody.addEventListener('input', calcTot);
<div class="container">
<table class="tg">
<thead>
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</thead>
<tbody id="sales">
<tr>
<td class="tg-0lax">1</td>
<td class="tg-0lax">MIE INSTAN</td>
<td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">5000</td>
<td class="tg-0lax">500</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax">2</td>
<td class="tg-0lax">SUSU UHT</td>
<td class="tg-keyup"><input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">6000</td>
<td class="tg-0lax">1000</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax">3</td>
<td class="tg-0lax">KERIPIK</td>
<td class="tg-keyup"> <input type="text" name="fname[]" placeholder="Masukan jumlah"></td>
<td class="tg-0lax">8000</td>
<td class="tg-0lax">500</td>
<td class="tg-0lax"></td>
</tr>
<tr>
<td class="tg-0lax"></td>
<td class="tg-1lax" colspan="4">TOTAL HARGA</td>
<td class="tg-0lax"></td>
</tr>
</tbody>
</table>
</div>
Notice also, that I've moved the sales id from the table tag to the tbody tag, and how the event handler function is used to calculate the subtotal and total sums without an actual event by passing an object which contains the needed information of the event object.
First, you should have the data source (in an array of objects). Such as:
var dataSource = [
{ id: 1, item: "MIE INSTAN", HargaSatuan: 5000, DiskonSatuan: 500 },
{ id: 2, item: "SUSU UHT", HargaSatuan: 6000, DiskonSatuan: 1000 },
{ id: 3, item: "KERIPIK", HargaSatuan: 8000, DiskonSatuan: 500 },
]
Then, you can loop through this array to construct your table, using either JQuery or JavaScript's "insertRow()".
Reference link for JavaScript's insertRow()
<html>
<head>
<style>
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid black
}
</style>
</head>
<body>
<table id="myTable">
<tr>
<th class="tg-0lax">No.</th>
<th class="tg-0lax">Item</th>
<th class="tg-0lax">Jumlah</th>
<th class="tg-0lax">Harga Satuan</th>
<th class="tg-0lax">Diskon Satuan</th>
<th class="tg-0lax">Sub-Total</th>
</tr>
</table>
<br>
<script>
function myFunction() {
var dataSource = [{
id: 1,
item: "MIE INSTAN",
hargaSatuan: 5000,
diskonSatuan: 500
},
{
id: 2,
item: "SUSU UHT",
hargaSatuan: 6000,
diskonSatuan: 1000
},
{
id: 3,
item: "KERIPIK",
hargaSatuan: 8000,
diskonSatuan: 500
},
]
var table = document.getElementById("myTable");
dataSource.forEach(function(data, index) {
var row = table.insertRow(index + 1);
var noCell = row.insertCell(0);
var itemCell = row.insertCell(1);
var jumlahCell = row.insertCell(2);
var hargaSatuanCell = row.insertCell(3);
var diskonSatuanCell = row.insertCell(4);
var subTotalCell = row.insertCell(5);
noCell.innerHTML = data.id;
itemCell.innerHTML = data.item;
hargaSatuanCell.innerHTML = data.hargaSatuan;
diskonSatuanCell.innerHTML = data.diskonSatuan
})
}
myFunction()
</script>
</body>
</html>
You only need to modify the datasource and refresh the table if there are any new data.
This might not be the best method of doing this, but this will give you a basic understanding on the algorithm and steps required for your needs.
i have a code that should do heatmap when applied to html table:
html table code:
<table class='table' id='js-datatable' cellspacing="0.9" cellpadding="8" border="1">
<tr>
<th align=center style="white-space: nowrap;" bgcolor=grey>product</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Jan</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Feb</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Mar</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Apr</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>May</th>
</tr>
<tr class='heatmap-stable'>
<td align=center>K22</td>
<td align=center>655$</td>
<td align=center>365$</td>
<td align=center>265$</td>
<td align=center>125$</td>
<td align=center>36$</td>
</tr>
<tr class='heatmap-stable'>
<td align=center>K52</td>
<td align=center>90</td>
<td align=center>50</td>
<td align=center>120</td>
<td align=center>80</td>
<td align=center>190</td>
</tr>
<tr class='heatmap-stable'>
<td align=center>J42</td>
<td align=center>1267</td>
<td align=center>1567</td>
<td align=center>347</td>
<td align=center>697</td>
<td align=center>70</td>
</tr>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/2.1.3/jquery.js'></script>
<script type='text/javascript' src='script.js'></script>
</table>
javŠ°script file code:
function clean_formatted_data(str) {
return parseFloat (str.replace (/([%,$,\,])+/g, ''));
}
function col_to_array(tbl_col, target) {
// Returns column `n` (zero indexed) in table id `target` as an array
var colArray = $ ('#' + target + ' td:nth-child(' + tbl_col + ')').map (function () {
return clean_formatted_data ($ (this).text ());
}).get ();
return colArray;
}
//------ new schtuff ------------------------//
function get_pos_of_max(col_data) {
return $.inArray (Math.max.apply (Math, col_data), col_data)
}
function generate_opacities(col_data, max) {
var opacity_array = [];
var increment = max / (col_data.length);
for (i = col_data.length; i >= 1; i--) {
opacity_array.push (i * increment / 100);
}
return opacity_array;
}
function process_col_best_performing(tbl_col, target) {
var col_data = col_to_array (tbl_col, target);
var opacity_array = generate_opacities (col_data, 50);
var row_count = col_data.length;
for (var i = 1; i <= row_count; i++) {
$ ('#' + target + ' tr:nth-child(' + (get_pos_of_max (col_data) + 1) + ') td:nth-child(' + tbl_col + ')').css ('background', 'rgba(0,0,255,' + opacity_array[0] + ')');
col_data[get_pos_of_max (col_data)] = null;
for (const spliceElement of opacity_array.splice (0, 1)) {
}
}
}
lets say i have 5 columns, so my javascript function can be applied in this way:
process_col_best_performing (tbl_col:1, target:'js-datatable');
process_col_best_performing (tbl_col:2, target:'js-datatable');
process_col_best_performing (tbl_col:3, target:'js-datatable');
But because this is only an example, real html table can have any amount of columns i want to make this with a for loop, i tried with code below, but its not working
var cols_qty = document.getElementById ('js-datatable').rows[0].cells.length
var i;
for(i = 1; i < 4; i++) {
console.log(i)
process_col_best_performing(tbl_col=i,'js-datatable');
}
*I'm totally new in javascript, so if you know the answer, please explain it in the simplest way as possible.
Not sure if this helps, but try the below code, the first thing do not declare as global var i; before the for loop, I am not sure if you are doing the same in your code, but the same i is getting changed inside the function and affecting the loop where you are calling process_col_best_performing. Check the below code and see if this make sense.
var cols_qty = document.getElementById ('js-datatable').rows[0].cells.length
for(var i = 1; i < 4; i++) {
console.log(i)
process_col_best_performing(i,'js-datatable');
}
function clean_formatted_data(str) {
return parseFloat (str.replace (/([%,$,\,])+/g, ''));
}
function col_to_array(tbl_col, target) {
// Returns column `n` (zero indexed) in table id `target` as an array
var colArray = $ ('#' + target + ' td:nth-child(' + tbl_col + ')').map (function () {
return clean_formatted_data ($ (this).text ());
}).get ();
return colArray;
}
//------ new schtuff ------------------------//
function get_pos_of_max(col_data) {
return $.inArray (Math.max.apply (Math, col_data), col_data)
}
function generate_opacities(col_data, max) {
var opacity_array = [];
var increment = max / (col_data.length);
for (var i = col_data.length; i >= 1; i--) {
opacity_array.push (i * increment / 100);
}
return opacity_array;
}
function process_col_best_performing(tbl_col, target) {
var col_data = col_to_array (tbl_col, target);
var opacity_array = generate_opacities (col_data, 50);
var row_count = col_data.length;
for (var i = 1; i <= row_count; i++) {
$ ('#' + target + ' tr:nth-child(' + (get_pos_of_max (col_data) + 1) + ') td:nth-child(' + tbl_col + ')').css ('background', 'rgba(0,0,255,' + opacity_array[0] + ')');
col_data[get_pos_of_max (col_data)] = null;
for (const spliceElement of opacity_array.splice (0, 1)) {
}
}
}
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/2.1.3/jquery.js'></script>
<table class='table' id='js-datatable' cellspacing="0.9" cellpadding="8" border="1">
<tr>
<th align=center style="white-space: nowrap;" bgcolor=grey>product</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Jan</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Feb</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Mar</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>Apr</th>
<th align=center style="white-space: nowrap;" bgcolor=grey>May</th>
</tr>
<tr class='heatmap-stable'>
<td align=center>K22</td>
<td align=center>655$</td>
<td align=center>365$</td>
<td align=center>265$</td>
<td align=center>125$</td>
<td align=center>36$</td>
</tr>
<tr class='heatmap-stable'>
<td align=center>K52</td>
<td align=center>90</td>
<td align=center>50</td>
<td align=center>120</td>
<td align=center>80</td>
<td align=center>190</td>
</tr>
<tr class='heatmap-stable'>
<td align=center>J42</td>
<td align=center>1267</td>
<td align=center>1567</td>
<td align=center>347</td>
<td align=center>697</td>
<td align=center>70</td>
</tr>
</table>
I would like to make a dynamic multicolumn table from a static 2D table, like the picture below (see solution):
The correct HTML-code as folows:
<div class="container">
<table border='1' id='theTable'>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Adam</td>
<td>AAA</td>
</tr>
<tr>
<td>Adam</td>
<td>BBB</td>
</tr>
<tr>
<td>Adam</td>
<td>CCC</td>
</tr>
<tr>
<td>Bert</td>
<td>AAA</td>
</tr>
<tr>
<td>Bert</td>
<td>CCC</td>
</tr>
<tr>
<td>Cesar</td>
<td>BBB</td>
</tr>
</tbody>
</table>
<br>
<table id='newTable' border='1'>
<thead></thead>
<tbody></tbody>
</table>
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(document).ready(function () {
var role_arr = [];
$("#theTable td:nth-child(2)").each(function() {
if ($.inArray($(this).text(), role_arr) == -1)
role_arr.push($(this).text());
});
role_arr.sort()
console.log(role_arr);
// create thead row and put Roles in it
var trow = "<tr>";
trow += '<th>Name</th>';
for (var i=0; i<role_arr.length; i++) {
trow +='<th>'+ role_arr[i] +'</th>';
}
trow += '</tr>';
$("#newTable").find("thead").append(trow);
// create all names array
var name_arr = [];
$("#theTable td:nth-child(1)").each(function() {
if ($.inArray($(this).text(), name_arr) == -1)
name_arr.push($(this).text());
});
console.log(name_arr);
for (var i=0; i<name_arr.length; i++) {
// create an array for each name's roles
var row_arr = [];
$("#theTable tr:has(td:contains('"+name_arr[i]+"'))").each(function () {
//console.log($(this).find('td:nth-child(2)').text());
row_arr.push($(this).find('td:nth-child(2)').text());
});
// create the table body row row
var trow = "<tr>";
trow += '<td>'+name_arr[i]+'</td>';
for(var j=0; j<role_arr.length; j++) {
if(row_arr.includes(role_arr[j])) {
trow += '<td> X </td>';
}
else {
trow += '<td> - </td>';
}
}
trow += '</tr>';
$("#newTable").find("tbody").append(trow);
}
});
</script>
I used jquery to iterate through the table. First created all different roles array and then individual names array. Then created individual rows for each names. I have added comments in the code.
<div class="container">
<table border='1' id='theTable'>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Adam</td>
<td>AAA</td>
</tr>
<tr>
<td>Adam</td>
<td>BBB</td>
</tr>
<tr>
<td>Adam</td>
<td>CCC</td>
</tr>
<tr>
<td>Bert</td>
<td>AAA</td>
</tr>
<tr>
<td>Bert</td>
<td>CCC</td>
</tr>
<tr>
<td>Cesar</td>
<td>BBB</td>
</tr>
</tbody>
</table>
<br>
<table id='newTable' border='1'>
<thead></thead>
<tbody></tbody>
</table>
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(document).ready(function () {
var role_arr = [];
$("#theTable td:nth-child(2)").each(function() {
if ($.inArray($(this).text(), role_arr) == -1)
role_arr.push($(this).text());
});
console.log(role_arr);
// create thead row and put Roles in it
var trow = "<tr>";
trow += '<th>Name</th>';
for (var i=0; i<role_arr.length; i++) {
trow +='<th>'+ role_arr[i] +'</th>';
}
trow += '</tr>';
$("#newTable").find("thead").append(trow);
// create all names array
var name_arr = [];
$("#theTable td:nth-child(1)").each(function() {
if ($.inArray($(this).text(), name_arr) == -1)
name_arr.push($(this).text());
});
console.log(name_arr);
for (var i=0; i<name_arr.length; i++) {
// create an array for each name's roles
var row_arr = [];
$("#theTable tr:has(td:contains('"+name_arr[i]+"'))").each(function () {
//console.log($(this).find('td:nth-child(2)').text());
row_arr.push($(this).find('td:nth-child(2)').text());
});
// create the table body row row
var trow = "<tr>";
trow += '<td>'+name_arr[i]+'</td>';
for(var j=0; j<role_arr.length; j++) {
if(row_arr.includes(role_arr[j])) {
trow += '<td> X </td>';
}
else {
trow += '<td> - </td>';
}
}
trow += '</tr>';
$("#newTable").find("tbody").append(trow);
}
});
</script>
I have the following html:
<table id='myTable'>
<tbody>
<tr>
<td id=col1">12</td>
<td id=col2">55</td>
<td id=col3">142</td>
<td id=col4">7</td>
</tr>
</tbody>
</table>
I would like to use JQuery to append everything after column 3 (col3) to a new row. Ideally I would end up with something like this:
<table id='myTable'>
<tbody>
<tr>
<td id=col1">12</td>
<td id=col2">55</td>
<td id=col3">142</td>
</tr>
<tr>
<td id=col4">7</td>
</tr>
</tbody>
</table>
Any ideas how this could be achieved? I have tried a few things but haven't been able to get it working.
You could define a generic redistribution function, that takes as argument the desired number of columns, and which just fills up the rows with content from top to bottom, using that number of columns.
It could even be a jQuery plugin:
$.fn.redistribute = function(maxNumCols) {
if (maxNumCols < 1) return;
$(this).each(function () {
let cells = Array.from($("td", this));
let $tr = $("tr", this);
let rowCount = Math.ceil(cells.length / maxNumCols);
for (let i = 0; i < rowCount; i++) {
let $row = i >= $tr.length ? $("<tr>").appendTo(this) : $tr.eq(i);
$row.append(cells.splice(0, maxNumCols));
}
});
}
// I/O management
function alignTable() {
let cols = +$("input").val(); // Get desired number of columns
$("#myTable").redistribute(cols); // Apply to table
}
// Refresh whenever input changes
$("input").on("input", alignTable);
// Refresh on page load
alignTable();
table { border-collapse: collapse; border: 2px solid }
td { border: 1px solid; padding: 4px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Desired number of columns: <input type="number" size="3" value="4" min="1">
<table id='myTable'>
<tbody>
<tr>
<td>12</td>
<td>55</td>
<td>142</td>
<td>7</td>
<td>20</td>
<td>410</td>
<td>99</td>
</tr>
</tbody>
</table>
Here is a version with one extra statement that sets the colspan on the very last td element so it occupies the remaining columns in the last row:
$.fn.redistribute = function(maxNumCols) {
if (maxNumCols < 1) return;
$(this).each(function () {
let cells = Array.from($("td", this));
let $tr = $("tr", this);
let rowCount = Math.ceil(cells.length / maxNumCols);
for (let i = 0; i < rowCount; i++) {
let $row = i >= $tr.length ? $("<tr>").appendTo(this) : $tr.eq(i);
$row.append(cells.splice(0, maxNumCols));
}
$("td", this).last().attr("colspan", rowCount * maxNumCols - cells.length + 1);
});
}
// I/O management
function alignTable() {
let cols = +$("input").val(); // Get desired number of columns
$("#myTable").redistribute(cols); // Apply to table
}
// Refresh whenever input changes
$("input").on("input", alignTable);
// Refresh on page load
alignTable();
table { border-collapse: collapse; }
td { border: 1px solid; padding: 4px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Desired number of columns: <input type="number" size="3" value="4" min="1">
<table id='myTable'>
<tbody>
<tr>
<td>12</td>
<td>55</td>
<td>142</td>
<td>7</td>
<td>20</td>
<td>410</td>
<td>99</td>
</tr>
</tbody>
</table>
It sounds like you're still new to jQuery. To give you an idea how to solve your described problem, I have written a solution here. I hope it helps you.
// parameters for splitting
var splitIndex = 3,
splitClass = '.split-columns';
// start the splitting
splitColumnsIntoRows();
function splitColumnsIntoRows() {
var $tables = $(splitClass),
numberTables = $tables.length;
if (numberTables == 0) {
return;
}
for (var i = 0; i < numberTables; i++) {
iterateSplittingRows($($tables[i]).find('tr'));
}
}
function iterateSplittingRows($currentRows) {
var $currentRow,
numberRows = $currentRows.length;
if (numberRows == 0) {
return;
}
for (var i = 0; i < numberRows; i++) {
$currentRow = $($currentRows[i]);
iterateSplittingFields($currentRow, $currentRow.find('th, td'));
}
}
function iterateSplittingFields($currentRow, $currentFields) {
var $newRow,
newRows = [],
childrenLength,
numberFields = $currentFields.length;
if (numberFields == 0) {
return;
}
for (var i = 0; i < numberFields; i++) {
if (i < splitIndex) {
continue;
}
if (i % splitIndex == 0) {
$newRow = $('<tr></tr>');
}
$newRow.append($currentFields[i]);
if (i == numberFields - 1) {
childrenLength = $newRow.children().length;
// fill the row with empty fields if the length does not fit the splitIndex
for (var j = splitIndex; j > childrenLength; j--) {
$newRow.append($('<td></td>'));
}
}
if (
(i >= splitIndex && i % splitIndex == splitIndex - 1)
||
i == numberFields - 1
){
newRows.push($newRow);
}
}
$currentRow.after(newRows);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable" class="split-columns">
<tbody>
<tr>
<td class="col_01">01</td>
<td class="col_02">02</td>
<td class="col_03">03</td>
<td class="col_04">04</td>
<td class="col_05">05</td>
<td class="col_06">06</td>
<td class="col_07">07</td>
<td class="col_08">08</td>
<td class="col_09">09</td>
</tr>
<tr>
<td class="col_10">10</td>
<td class="col_11">11</td>
<td class="col_12">12</td>
<td class="col_13">13</td>
<td class="col_14">14</td>
<td class="col_15">15</td>
<td class="col_16">16</td>
<td class="col_17">17</td>
</tr>
<tr>
<td class="col_19">19</td>
<td class="col_20">20</td>
<td class="col_21">21</td>
<td class="col_22">22</td>
<td class="col_23">23</td>
<td class="col_24">24</td>
<td class="col_25">25</td>
</tr>
</tbody>
</table>