Merge table columns by index using jQuery - javascript

In the following code, how can I merge columns 2 and 4 into a single column having columnspan=2 using jquery?
<table id="Sample" border="1">
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
</tr>
</tbody>
</table>

Please try this
$(document).ready(function () {
var row = $("#Sample tr td");
for (var i = 0; i < row.length; i++) {
var num1 = parseInt(row[i].innerHTML);
var num2 = parseInt(row[i + 2].innerHTML);
if (num1 == num2) {
row[i].setAttribute("colspan", "2");
row[i + 2].parentElement.removeChild(row[i + 2])
}
}
});

Related

For loop inside for loop not working properly repeating same values multiple times Javascript

I'm wanting every <tbody> tag will be gone as object index like first <tbody>->1 and second <tbody>-> 2 then inside the <tbody> every <tr> will be another object and that will be store into the <tbody> object and last the last part every <td> should have object key ("eiin", "name") inside the <tr> object
I'm trying using for loop multiple times but the console.log showing me okay but first object repeated 2 times.
Html
<section class="institute_list">
<table class="table" border="1">
<thead>
<tr>
<th scope="col">EIIN</th>
<th scope="col">Institute</th>
</tr>
</thead>
<tbody>
<tr>
<td>000000</td>
<td>Name</td>
</tr>
</tbody>
<tbody>
<tr>
<td>111111</td>
<td>Name 2</td>
</tr>
</tbody>
</table>
</section>
Javascript & jQuery
<script>
var rows = '', the_row='', the_xrow={}, tr_values={}, xtd_obj={};
tbodys = ($(".institute_list .table tbody").length);
for( var x=0; tbodys > x; x++) {
rows = $('.institute_list .table tbody:nth-child('+(x+1)+') tr').length;
the_row = '.institute_list .table tbody:nth-child('+(x+1)+') tr:nth-child(';
for( var i=1; rows >= i; i++ ){
tr_values = {
'eiin' : $(the_row+i+') td:first-child').text(),
'name' : $(the_row+i+') td:nth-child(2)').text()
};
the_xrow[i] = tr_values;
}
xtd_obj[x] = the_xrow;
}
console.log(xtd_obj);
</script>
and i'm getting this output in console
here
You may try the code below. You can separate every <tbody>,<tr>,<td> tag as a loop then make them a array.
var target = $(".institute_list > table");
var output = [];
$(target).find("tbody").each(function(i){
output[i] = {};
$(this).children().each(function(j){
output[i][j] = {};
$(this).children().each(function(k, td){
if ( k == 0 ) {
output[i][j]["eiin"] = $(td).text();
} else if ( k == 1 ) {
output[i][j]["name"] = $(td).text();
} else {
output[i][j][k] = $(td).text();
}
});
});
});
console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="institute_list">
<table class="table" border="1">
<thead>
<tr>
<th scope="col">EIIN</th>
<th scope="col">Institute</th>
</tr>
</thead>
<tbody>
<tr>
<td>000000</td>
<td>Name</td>
</tr>
</tbody>
<tbody>
<tr>
<td>111111</td>
<td>Name 2</td>
</tr>
</tbody>
</table>
</section>
First, you need a closing </tbody> tag around the first element. Second I think you might be running into a scoping problem. You are defining the_xrow and tr_values outside of the for loops instead of inside of the for loops.
<script>
var xtd_obj={};
var tbodys = ($(".institute_list .table tbody").length);
for( var x=1; tbodys >= x; x++) {
var current_row = '.institute_list .table tbody:nth-child('+x+') tr';
var rows = $(current_row).length;
var the_row = current_row + ':nth-child(';
var the_xrow = {};
for( var i=1; rows >= i; i++ ){
the_xrow[i] = {
'eiin' : $(the_row+i+') td:first-child').text(),
'name' : $(the_row+i+') td:nth-child(2)').text()
};
}
xtd_obj[x] = the_xrow;
}
console.log(xtd_obj);
</script>
It's working for me
<script>
var rows = '', the_row='', xtd_obj={};
var tbodys = ($(".institute_list .table tbody").length)+1;
for( var x=1; tbodys > x; x++) {
rows = $('.institute_list .table tbody:nth-child('+(x+1)+') tr').length;
the_row = '.institute_list .table tbody:nth-child('+(x+1)+') tr:nth-child(';
var the_xrow = {};
for( var i=0; rows > i; i++ ){
var tr_values = {
'eiin' : $(the_row+i+1+') td:first-child').text(),
'name' : $(the_row+i+1+') td:nth-child(2)').text()
};
the_xrow[i] = tr_values;
}
xtd_obj[x] = the_xrow;
}
console.log(xtd_obj);
</script>
Here's the screenshot

Javascript sum table conditional

I need to sum values in a two column table, where for each row if col2 is not blank, add it to the total, else instead add col1. Then publish the total to a div
Below is what I've tried but it outputs blank.
var table = document.getElementById("PLTable");
var cost_est = document.getElementsByClassName("cost_estimate");
var act_cost = document.getElementsByClassName("act_cost");
var sum2 = 0;
for (var i = 0, row; row = table.rows[i]; i++) {
if (act_cost[i].innerText>0) {
sum2 += act_cost[i].innerText;
}
else {
sum2 += cost_est[i].innerText;
}
}
document.getElementById("cost_projected_total").innerHTML = sum2
<!--HTML data looks like this:-->
<table id="PLTable">
<thead>
<tr>
<th>cost estimate</th>
<th>cost actual</th>
</tr>
</thead>
<tr>
<td class = "cost_estimate">100</td>
<td class = "act_cost"></td>
</tr>
<tr>
<td class = "cost_estimate">100</td>
<td class = "act_cost">50</td>
</tr>
</table>
<div id="cost_projected_total">
</div>
Correct output should be sum2 = 150 & that result should be output inside the div.
Any ideas?
There are some points to address in your code.
I will try to summarize what was wrong and how it should be change:
table.rows actually loops the head as well, so your index would go out of bounds.
innerText returns a text, so you first need to conver that value to a Number first, otherwise it will concatenate the strings.
So, basically, what I did to keep your code as it currently was is:
added a tbody
changed table.rows to the count of the tbody rows.
Acquired both numeric values of the looped items.
Below is the working code with the mentioned changes and fixes, it could've been way shorted, I just want to keep the code as close to your so that you can understand where and what was wrong, without necessarely relying on an optimal solution.
var table = document.getElementById("PLTable");
var tbody = table.getElementsByTagName('tbody')[0];
var cost_est = document.getElementsByClassName("cost_estimate");
var act_cost = document.getElementsByClassName("act_cost");
var sum2 = 0;
for (var i = 0; i < tbody.getElementsByTagName('tr').length; i++) {
var row_act_cost = Number(act_cost[i].innerText);
var row_cost_est = Number(cost_est[i].innerText);
if (row_act_cost > 0) {
sum2 += row_act_cost;
}
else {
sum2 += row_cost_est;
}
}
document.getElementById("cost_projected_total").innerHTML = sum2;
<table id="PLTable">
<thead>
<tr>
<th>cost estimate</th>
<th>cost actual</th>
</tr>
</thead>
<tbody>
<tr>
<td class = "cost_estimate">100</td>
<td class = "act_cost"></td>
</tr>
<tr>
<td class = "cost_estimate">100</td>
<td class = "act_cost">50</td>
</tr>
</tbody>
</table>
<div id="cost_projected_total">
</div>
Loop through act_cost and check if the text in each cell is a valid and > 0 number then add it to sum2 otherwise add the cost_est at that index to sum2.
const table = document.getElementById("PLTable"),
cost_est = document.querySelectorAll(".cost_estimate"),
act_cost = document.querySelectorAll(".act_cost"),
total = document.getElementById("cost_projected_total");
let sum2 = 0;
/** loop through the "act_cost" (2nd column) **/
/**
* el: current td from "act_cost".
* i: its index in "act_cost"
**/
act_cost.forEach((el, i) => sum2 += +el.textContent > 0 ? +el.textContent:+cost_est[i].textContent);
/** "+" transforms the text into a number if possible **/
total.textContent = 'Total: ' + sum2;
<table id="PLTable">
<thead>
<tr>
<th>cost estimate</th>
<th>cost actual</th>
</tr>
</thead>
<tr>
<td class="cost_estimate">100</td>
<td class="act_cost"></td>
</tr>
<tr>
<td class="cost_estimate">100</td>
<td class="act_cost">50</td>
</tr>
</table>
<div id="cost_projected_total"></div>

How to highlight a table row with the smallest value in a certain column using javascript

Supposed that I have a table like this on a webpage with the id ='table':
Name Age Money(USD) DATE
A 19 4 2019-03-11 16:15:35
B 20 0 2019-03-11 16:16:37
C 27 3 2019-03-13 04:15:43
D 34 0 2019-03-13 04:16:57
Could you help me find the FIRST SMALLEST VALUE IN THE MONEY COLUMN, which is 0 for B in the Column1 and HIGHLIGHT the whole table row for B, using javascript without using any library and any button onClicking?
Note: I have searched around and just been unlucky enough to find the correct answer to my problem.
Thanks.
UPDATE:I just got a piece of javacript like this to get the first smallest value and print it out, but not be able to highlight the whole row with it
var table = document.getElementById("table"), minVal;
for(var i = 1; i < table.rows.length; i++)
{
// if its the first row get the value
if(i === 1){minVal = table.rows[i].cells[2].innerHTML; }
// test with the other values
else if(minVal > table.rows[i].cells[2].innerHTML){
minVal = table.rows[i].cells[2].innerHTML;
}
}
document.getElementById("val").innerHTML = " Minimum Value = "+minVal;
console.log(maxVal);
var table = document.getElementById("table"), minVal, minI;
for(var i = 1; i < table.rows.length; i++){
if(i === 1){
minVal = table.rows[i].cells[2].innerHTML;
}
else if(minVal > table.rows[i].cells[2].innerHTML){
minVal = table.rows[i].cells[2].innerHTML;
minI = i;
}
}
table.rows[i].cells[2].innerHTML = '<span style="background:red">' + table.rows[minI].cells[2].innerHTML + '</span>';
Something like that.
var table = document.getElementById("table");
var minVal = undefined;
for(var i = 1; i < table.rows.length; i++)
{
if(i === 1){
minVal = table.rows[i].cells[2];
}
else if(minVal.innerHTML > table.rows[i].cells[2].innerHTML){
minVal = table.rows[i].cells[2];
}
}
minVal.parentElement.style.background="yellow";
There are two things you need to do:
Convert innerHTML to a number using +
Keep track of the row number while looping.
This is the code
var table = document.getElementById("table"), minVal;
let minRow = 1;
for(var i = 1; i < table.rows.length; i++)
{
// if its the first row get the value
if(i === 1){
minVal = +table.rows[i].cells[2].innerHTML;
}
// test with the other values
else if(minVal > table.rows[i].cells[2].innerHTML){
minVal = table.rows[i].cells[2].innerHTML;
minRow = i;
}
}
let row = table.rows[minRow];
row.style.backgroundColor = 'red';
This simply keeps track of the minimum row, and lets you hang your formatting off of that:
const highlightLowest = () => {
var rows = table.rows;
var minRow = rows[0]
for (var i = 1; i < rows.length; i++){
rows[i].classList.remove('highlight')
if (Number(rows[i].cells[2].innerHTML) < Number(minRow.cells[2].innerHTML)) {
minRow = rows[i]
}
}
minRow.classList.add('highlight')
}
tr.highlight td {background-color: yellow}
<table id="table">
<tr><td>A</td><td>19</td><td>4</td><td>2019-03-11 16:15:35</td></tr>
<tr><td>B</td><td>20</td><td>0</td><td>2019-03-11 16:16:37</td></tr>
<tr><td>C</td><td>27</td><td>3</td><td>2019-03-13 04:15:43</td></tr>
<tr><td>D</td><td>34</td><td>0</td><td>2019-03-13 04:16:57</td></tr>
</table>
<hr />
<button onClick="highlightLowest()">Highlight</button>
Here you go. The function 'highlight' takes the column that you want to base your highlighting upon as an argument.
// Get your table's headers
headers = document.querySelectorAll('#table tbody tr th')
// Get your table's headers
rows = document.querySelectorAll('#table tbody tr')
// Declaring function that takes wanted column as argument
highlight = (colName) =>{
let min = 0;
for(i=0;i<headers.length;i++){
if(headers[i].innerText == colName){
for(j=1;j<rows.length;j++){
value = parseInt(rows[j].children[i].innerHTML);
if(j == 1){
min = value;
}
if(value < min){
rows[j].style.backgroundColor = "yellow"
break;
}
}
}
}
}
<table id="table">
<tbody><tr>
<th>Test 1</th>
<th>Test 2</th>
<th>Test 3</th>
</tr>
<tr>
<td>7</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>3</td>
<td>5</td>
<td>5</td>
</tr>
<tr>
<td>12</td>
<td>1</td>
<td>5</td>
</tr>
<tr>
<td>15</td>
<td>89</td>
<td>4</td>
</tr>
<tr>
<td>3</td>
<td>6</td>
<td>6</td>
</tr>
<tr>
<td>2</td>
<td>4</td>
<td>8</td>
</tr>
</tbody></table>
<input type='text' id='col'>
<button onclick=highlight(document.getElementById('col').value)>Highlight based on input column</button>

move the row/s up when data matched with the inputted string

I need to move the row/s that is matched with the inputted string.
on the code below you need to click first the row before you can move that particular row to the top.
Instead of clicking the row, I just wanted to input a string or char then onclick, if there's a match on the html table, the row that matched or like on the string inputted will be moved on the top of the table grid.
var index;
function getSelectedRow() {
var table = document.getElementById("table");
for (var i = 1; i < table.rows.length; i++) {
table.rows[i].onclick = function() {
if (typeof index !== "undefined") {
table.rows[index].classList.toggle("selected");
}
index = this.rowIndex;
this.classList.toggle("selected");
};
}
}
getSelectedRow();
function upNdown(direction) {
var rows = document.getElementById("table").rows,
parent = rows[index].parentNode;
if (direction === "up") {
if (index < rows.length) {
parent.insertBefore(rows[index], rows[index - index + 1]);
index--;
}
}
}
<table id="table" border="1">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
<tr>
<td>A3</td>
<td>B3</td>
<td>C3</td>
</tr>
</table>
<input type="text" id="txt">
<button onclick="upNdown('up');">&ShortUpArrow;</button>
what I need to do is upon click of the button, find the matching data and move the row to the top.
If I correctly understand you problem, Think this is your answer. This code find the first match of input and move that to first row. If the input be empty, it will do nothing.
var index = 0;
function findMatchRow(rows, str) {
if (!str.length) {
return null;
}
for (var i = 1; i < rows.length; i++) {
for (var j = 0; j < rows[i].children.length; j++) {
if (rows[i].children[j].textContent.match(str)) {
return i;
}
}
}
return 0;
}
function getSelectedRow() {
var table = document.getElementById("table");
for (var i = 1; i < table.rows.length; i++) {
table.rows[i].onclick = function() {
if (typeof index !== "undefined") {
table.rows[index].classList.toggle("selected");
}
index = this.rowIndex;
this.classList.toggle("selected");
};
}
}
getSelectedRow();
function upNdown(direction) {
var rows = document.getElementById("table").rows,
parent = rows[index && index > -1 ? index : 0].parentNode,
inpt = document.getElementById("txt").value;
var matchedRow = findMatchRow(rows, inpt);
if (matchedRow) {
if (direction === "up") {
index = matchedRow;
parent.insertBefore(rows[index], rows[index - index + 1]);
index--;
if (index < 0) {
index = rows.length - 1;
}
}
}
}
<table id="table" border="1">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Age</th>
</tr>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
<tr>
<td>A3</td>
<td>B3</td>
<td>C3</td>
</tr>
</table>
<input type="text" id="txt">
<button onclick="upNdown('up');">&ShortUpArrow;</button>

Loop through table not working

I am new to Javascript and am having problems with looping my function.
I am trying to loop through a table and convert the numbers in the second column to a rating in the third column. I have defined a function to convert the numerical rating into text ("Good", "Bad", ...) which I then want to use in my loop. For some reason, the conversion works for the first row but stops at the second.
I couldn't find a answer on here, could anyone help? Thanks
function convert(number) {
if (number == 1) {
return convert = "Bad";
} else if (number == 2) {
return convert = "Satisfactory";
} else if (number == 3) {
return convert = "Moderate Good";
} else if (number == 4) {
return convert = "Good";
} else {
return convert = "Excellent";
}
}
var table = document.getElementById("results");
var rows = table.rows;
var rowcount = rows.length;
console.log(rowcount);
var num = [];
var txt = [];
for(var i = 1; i < rowcount ; i++) {
num[i] = parseInt(table.rows[i].cells.item(1).innerHTML);
txt[i] = convert( num[i] );
table.rows[i].cells.item(2).innerHTML = txt[i];
}
<table id="results">
<thead>
<tr>
<th>Question number</th>
<th>Assessment value</th>
<th>Output text</th>
</tr>
</thead>
<tr>
<td>Q1</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>Q2</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>Q3</td>
<td>3</td>
<td></td>
</tr>
<tr>
<td>Q4</td>
<td>2</td>
<td></td>
</tr>
<tr>
<td>Q5</td>
<td>5</td>
<td></td>
</tr>
</table>
The return statement usage was incorrect. In your code while returning value, it also changing the convert function reference to string "Good", so it was stoping in 2nd time execution. Please check the below corrected version.
function convert(number) {
if (number == 1) {
return "Bad";
} else if (number == 2) {
return "Satisfactory";
} else if (number == 3) {
return "Moderate Good";
} else if (number == 4) {
return "Good";
} else {
return "Excellent";
}
}
var table = document.getElementById("results");
var rows = table.rows;
var rowcount = rows.length;
console.log(rowcount);
var num = [];
var txt = [];
for(var i = 1; i < rowcount ; i++) {
num[i] = parseInt(table.rows[i].cells.item(1).innerHTML);
txt[i] = convert( num[i] );
table.rows[i].cells.item(2).innerHTML = txt[i];
}
<table id="results">
<thead>
<tr>
<th>Question number</th>
<th>Assessment value</th>
<th>Output text</th>
</tr>
</thead>
<tr>
<td>Q1</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>Q2</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>Q3</td>
<td>3</td>
<td></td>
</tr>
<tr>
<td>Q4</td>
<td>2</td>
<td></td>
</tr>
<tr>
<td>Q5</td>
<td>5</td>
<td></td>
</tr>
</table>
It's your convert function assigning return values to a variable rather than just returning them, and the fact that variable has the same name as the function.
When it does return convert = "whatever" it destroys itself, as the function itself is really just a variable.
Just use return "whatever" instead.

Categories