It's part of the larger task. Why is the problem Nan and how to solve it? The table is added together elements from several pools <input> which elemenatymi table. All code is summed up in the table of size k / d.
Why is the problem Nan and how to solve it?
function licz(tableID){
var table = document.getElementById(tableID);
var k, d, s=0, temp;
var i = table.rows.length;
for(k=1; k<=i; k++){
for(d=0; d<2; d++){
temp = parseFloat(document.getElementById(tableID).rows[k].cells[d].innerHTML);
alert(temp);
s=s+temp;
}
document.getElementById(tableID).rows[k].cells[d].innerHTML = s;
}
}
<form name="roz" action="">
<table id="tyg" class="product_values" style="width: 20%" border=1>
<tr>
<td> Pon </td>
<td> Wt </td>
<td> Sum </td>
</tr><tr>
<td> <input type="number" name="inp_a" ></td>
<td> 4 </td>
<td></td>
</table>
</form>
<button onclick="licz('tyg')">go</button>
This is not right way for getting value from child elements you should do something like this :
JavaScript:
function licz(tableID){
var table = document.getElementById(tableID);
var k, d, temp;
var i = table.rows.length;
for (k = 1; k <= i; k++) {
for (d = 0; d < 2; d++) {
if (d == 0) {
temp = parseFloat(document.getElementById(tableID).rows[k].cells[d].childNodes[1].value);
}
if (d == 1) {
temp = temp + parseFloat(document.getElementById(tableID).rows[k].cells[d].innerHTML);
}
}
document.getElementById(tableID).rows[k].cells[d].innerHTML = temp;
document.getElementById('num').v
}
}
HTML:
<table id="tyg" class="product_values" style="width: 20%" border=1>
<tr>
<td> Pon </td>
<td> Wt </td>
<td> Sum </td>
</tr>
<tr>
<td> <input id = 'num' type="number" name="inp_a" ></td>
<td> 4 </td>
<td></td>
</tr>
</table>
well... it's a good question. You should read DOM for knowing more about this.
Related
Here's another problem encountered with js/html code. I typed some numbers at the top of the page, then after I pressed the button First Line, it will display the numbers I inputted in the first table row accordingly. If I press the button Last Line, I'd like it to display some numbers after getting done with some arithmetics, which is in the btn2 part in the js file, in the last table row of the page. I'd like to find out if it is the problem of innerHTML or valueAsNumber in the if statements, or the variables declared in the for loop not applicable in the later if statements, that caused the numbers in the last row cannot be displayed eventually.
The for loop and the if statement is intended for the page to scan the numbers inputted in the first row, do some arithmetics with them, and display them in the last row, in each respective cell. Is there any other way out to do so?
Thank you very much!
const tab = document.getElementById("tab");
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
var R1 = [R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7, R1C8,
R1C9, R1C10, R1C11, R1C12, R1C13, R1C14, R1C15, R1C16];
var R2 = [R2C1, R2C2, R2C3, R2C4, R2C5, R2C6, R2C7, R2C8,
R2C9, R2C10, R2C11, R2C12, R2C13, R2C14, R2C15, R2C16];
btn1.addEventListener('click', () => {
for (var i = 0; i <= 15; i++) {
let row = tab.rows[1];
let c = row.cells[i];
let inpId = 'inp' + (i + 1);
let inpEl = document.getElementById(inpId);
c.innerHTML = inpEl.value;
}
});
btn2.addEventListener('click', () => {
for (var i = 0; i <= 15; i++) {
var r1c = R1[i].id;
var r2c = R2[i].id;
var r1El = document.getElementById(r1c);
var r2El = document.getElementById(r2c);
}
if (r1El.innerHTML > 0) {
var choices = [0, (r1El.valueAsNumber) % 7, (r1El.valueAsNumber + 2) % 7, (r1El.valueAsNumber - 2) % 7];
var x = Math.floor(Math.random() * choices.length);
if (choices[x] == choices.at(0)) {
r2El.innerHTML = choices[x];
} else if (choices[x] <= 0) {
r2El.innerHTML = choices[x] + 7;
}
}
});
th,
tr,
td {
border: 1px solid black;
padding: 5px;
width: 40px;
text-align: center;
}
<div class="container">
<div id="data">
<table id="inpdata">
<tr>
<td id="inpb1">Group 1</td>
<td id="inpb2">Group 2</td>
<td id="inpb3">Group 3</td>
<td id="inpb4">Group 4</td>
</tr>
<tr>
<td>
<input type="number" id="inp1" title="inp1">
<input type="number" id="inp2" title="inp2">
<input type="number" id="inp3" title="inp3">
<input type="number" id="inp4" title="inp4">
</td>
<td>
<input type="number" id="inp5" title="inp5">
<input type="number" id="inp6" title="inp6">
<input type="number" id="inp7" title="inp7">
<input type="number" id="inp8" title="inp8">
</td>
<td>
<input type="number" id="inp9" title="inp9">
<input type="number" id="inp10" title="inp10">
<input type="number" id="inp11" title="inp11">
<input type="number" id="inp12" title="inp12">
</td>
<td>
<input type="number" id="inp13" title="inp13">
<input type="number" id="inp14" title="inp14">
<input type="number" id="inp15" title="inp15">
<input type="number" id="inp16" title="inp16">
</td>
</tr>
</table>
<br>
<button id="btn1">First line</button>
<button id="btn2">Last line</button>
</div>
<div id="tables">
<table id="tab">
<tr>
<th colspan="4">Group 1</th>
<th colspan="4">Group 2</th>
<th colspan="4">Group 3</th>
<th colspan="4">Group 4</th>
</tr>
<tr>
<td id="R1C1"></td>
<td id="R1C2"></td>
<td id="R1C3"></td>
<td id="R1C4"></td>
<td id="R1C5"></td>
<td id="R1C6"></td>
<td id="R1C7"></td>
<td id="R1C8"></td>
<td id="R1C9"></td>
<td id="R1C10"></td>
<td id="R1C11"></td>
<td id="R1C12"></td>
<td id="R1C13"></td>
<td id="R1C14"></td>
<td id="R1C15"></td>
<td id="R1C16"></td>
</tr>
<tr>
<td id="R2C1"></td>
<td id="R2C2"></td>
<td id="R2C3"></td>
<td id="R2C4"></td>
<td id="R2C5"></td>
<td id="R2C6"></td>
<td id="R2C7"></td>
<td id="R2C8"></td>
<td id="R2C9"></td>
<td id="R2C10"></td>
<td id="R2C11"></td>
<td id="R2C12"></td>
<td id="R2C13"></td>
<td id="R2C14"></td>
<td id="R2C15"></td>
<td id="R2C16"></td>
</tr>
</table>
</div>
So you can Iterate the td by iterating the elements HTMLCollection property of the tr. Iterate two Iterables by using the index from one.
const tab = document.getElementById("tab");
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
const firstRow = tab.firstElementChild.children[1].children;
const secondRow = tab.firstElementChild.children[2].children;
btn1.addEventListener('click', () => {
for (var i = 0; i <= 7 /* <- This is a magic value - avoid these */; i++) {
let row = tab.rows[1];
let c = row.cells[i];
let inpId = 'inp' + (i + 1);
let inpEl = document.getElementById(inpId);
c.innerHTML = inpEl.value;
}
});
btn2.addEventListener('click', () => {
[...secondRow].forEach((el,index)=>{
//let group = Math.floor(index / 4);
let inp = parseInt(firstRow[index].innerText, 10);
if (!inp) return;
let choices = [0, inp, (inp + 2), (inp - 2)];
let x = (Math.floor(Math.random() * choices.length) + 7) % 7;
el.innerText = x;
})
});
th,
tr,
td {
border: 1px solid black;
padding: 5px;
width: 40px;
height: 1.5em;
text-align: center;
}
<div class="container">
<div id="data">
<table id="inpdata">
<tr>
<td id="inpb1">Group 1</td>
<td id="inpb2">Group 2</td>
</tr>
<tr>
<td>
<input type="number" id="inp1" title="inp1">
<input type="number" id="inp2" title="inp2">
<input type="number" id="inp3" title="inp3">
<input type="number" id="inp4" title="inp4">
</td>
<td>
<input type="number" id="inp5" title="inp5">
<input type="number" id="inp6" title="inp6">
<input type="number" id="inp7" title="inp7">
<input type="number" id="inp8" title="inp8">
</td>
</tr>
</table>
<br>
<button id="btn1">First line</button>
<button id="btn2">Last line</button>
</div>
<div id="tables">
<table id="tab">
<tr>
<th colspan="4">Group 1</th>
<th colspan="4">Group 2</th>
</tr>
<tr>
<td></td><td></td><td></td><td></td>
<td></td><td></td><td></td><td></td>
</tr>
<tr>
<td></td><td></td><td></td><td></td>
<td></td><td></td><td></td><td></td>
</tr>
</table>
</div>
Some additional advice:
I couldn't be bothered to clean up all of your code, next time please provide a Minimal Example, tree fields would have been plenty to ask the question.
Further please avoid magic numbers, like you use in your loops. Get the size of what you are iterating when you use it. This makes your code more flexible and reusable.
In the same vein: Please do not throw ids everywhere. They just beg to break your code if you ever try to reuse it somehow.
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>
I am in the process of writing a webpage. I have everything done that is needed, however, when you enter any quantity over 30 it will make the id = "shipping" color red. It does this but it does it for anything less than 30 as well. Also I am having trouble with my submit button sending off to a server/url. Any help is appreciated! I will attach my code!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Widgets R' Us </title>
<style>
table,
td {
border: 1px solid black;
}
</style>
<script type="text/javascript">
//Check if non -number or a negative number
function realNumber() {
var qty1 = document.getElementById("Quantity1").value;
var qty2 = document.getElementById("Quantity2").value;
var qty3 = document.getElementById("Quantity3").value;
//isNaN is a predetermined function
if ((isNaN(qty1) || qty1 < 0) || (isNaN(qty2) || qty2 < 0) || (isNaN(qty3) || qty3 < 0)) {
alert("The quantity given is not a real number or is a negative number!");
return false; //Will not allow for data to go to server.
} else {
return true;
}
}
function total() {
var p1 = document.getElementById("Price1").value; //Value is referenced to the input tag
var p2 = document.getElementById("Price2").value;
var p3 = document.getElementById("Price3").value;
var qty1 = document.getElementById("Quantity1").value;
var qty2 = document.getElementById("Quantity2").value;
var qty3 = document.getElementById("Quantity3").value;
var over = qty1 + qty2 + qty3;
if (realNumber()) {
var totals = (p1 * qty1) + (p2 * qty2) + (p3 * qty3);
var yes = (totals).toFixed(2);
document.getElementById("ProductTotal").innerHTML = "$" + yes;
if (over > 30) {
document.getElementById("shipping").style.color = "red";
} else {
document.getElementById("shipping").style.color = "black";
}
}
}
function checkOut() {
if (total()) {
if ((document.getElementById("shipping").style.color == "red") &&
(document.getElementById("extra").checked)) {
return true;
}
}
return false;
}
</script>
</head>
<body>
<div>
<h1><b><big> Widgets R' Us </b></strong>
</h1>
<h2><b> Order/Checkout </b></h2>
<form name "widgets" onsubmit="return checkOut();" action="https://www.reddit.com/" method="get">
<div id="mainTable">
<table>
<tr>
<td>Widget Model:</td>
<td>37AX-L
<td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$12.45 <input type="hidden" id="Price1" name="Price1" value="12.45" /</td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity1" name="Quantity1" value="0" /</td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Widget Model:</td>
<td>42XR-J</td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$15.34 <input type="hidden" id="Price2" name="Price2" value="15.34" /></td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity2" name="Quantity2" value="0" /></td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Widget Model:</td>
<td>93ZZ-A</td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$28.99 <input type="hidden" id="Price3" name="Price3" value="28.99" /></td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity3" name="Quantity3" value="0" /></td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Product Total:</td>
<td>
<p id="ProductTotal"> 0 </p>
</td>
</tr>
<tr>
<td> <input type="checkbox" id="extra" name="extra"> </td>
<td>
<p id="shipping">If the quantity exceeds 30 units, there will be extra shipping!</p>
</td>
</tr>
</table>
</div>
<tr>
<td> <input type="Submit" value="Submit" /> </td>
<td> <input type="button" value="Calculate" onClick="total()" /> </td>
</tr>
</form>
</body>
</html>
Problem with your values qty1,qty2,qty3. these values are reading as string. so instead of addding these values , its concatinating the strings. replace
var qty1 = document.getElementById("Quantity1").value;
var qty2 = document.getElementById("Quantity2").value;
var qty3 = document.getElementById("Quantity3").value;
with
var qty1 = parseInt(document.getElementById("Quantity1").value);
var qty2 = parseInt(document.getElementById("Quantity2").value);
var qty3 = parseInt(document.getElementById("Quantity3").value);
It will Solve your problem with 'Red'.
For the submit button, function total() is not returning anything. so change something like
function total() {
var p1 = document.getElementById("Price1").value; //Value is referenced to the input tag
var p2 = document.getElementById("Price2").value;
var p3 = document.getElementById("Price3").value;
var qty1 = parseInt(document.getElementById("Quantity1").value);
var qty2 = parseInt(document.getElementById("Quantity2").value);
var qty3 = parseInt(document.getElementById("Quantity3").value);
var over = qty1 + qty2 + qty3;
if (realNumber()) {
var totals = (p1 * qty1) + (p2 * qty2) + (p3 * qty3);
var yes = (totals).toFixed(2);
document.getElementById("ProductTotal").innerHTML = "$" + yes;
if (over > 30) {
document.getElementById("shipping").style.color = "red";
return true;
} else if(over>0) {
document.getElementById("shipping").style.color = "black";
return true;
}else{
document.getElementById("shipping").style.color = "black";
return false;
}
}
}
and checkout() as
function checkOut() {
if (total()) {
if (((document.getElementById("shipping").style.color == "red") &&
(document.getElementById("extra").checked))||
(document.getElementById("shipping").style.color != "red")) {
return true;
}
}
return false;
}
Replace
var over = qty1 + qty2 + qty3;
With
var over = parseInt(qty1) + parseInt(qty2) + parseInt(qty3);
There were some minor HTML errors but the real issue is that numeric strings were being concatenated. So, to get the quantity values you need to use parseInt() to extract the integer value so that math is performed instead of string concatenation. Also, it's a little odd that the user has to click the Calculate Button in order to see a total. The button does work correctly, but is this what you really want?
One more thing, as tempting as it may be to directly alter the color of elements with JavaScript, in terms of keeping the code more robust, it is preferable to simply change the class name as the code does in this example since I created two classes in the CSS for this purpose.
The form now submits as long as the checkbox is unchecked and the units do not exceed 30. I changed the method to "post" and adjusted the true/false return statements in checkOut(). Note when data is submitted using the POST method, then no form data appears appended to the URL; for more info see here. I also altered the totals() function so that now it returns a value, namely the total price.
var d = document;
d.g = d.getElementById;
var qty = [0, 0, 0, 0];
var shipping = d.g("shipping");
function realNumber() {
var qtyInvalid = [0, 0, 0, 0];
for (let i = 1, max = qtyInvalid.length; i < max; i++) {
qtyInvalid[i] = (isNaN(qty[i]) || qty[i] < 0);
}
if (qtyInvalid[1] || qtyInvalid[2] || qtyInvalid[3]) {
console.log("The quantity given is not a real number or is a negative number!");
return false;
}
return true;
}
function total() {
var over = 0;
var price = [0, 0, 0, 0];
for (j = 1, max = price.length; j < max; j++) {
price[j] = d.g("Price" + j + "").value;
qty[j] = d.g("Quantity" + j + "").value;
}
var totals = 0;
var yes = 0;
const radix = 10;
for (q = 1, max = qty.length; q < max; q++) {
over += parseInt(qty[q], radix)
}
//console.log(over);
if (!realNumber()) {
return false;
}
for (let k = 1, max2 = price.length; k < max2; k++) {
totals += (price[k] * qty[k]);
}
yes = (totals).toFixed(2);
d.g("ProductTotal").innerHTML = "$" + yes;
shipping.className = (over > 30) ? "red" : "black";
return totals;
} // end total
function checkOut() {
var retval = false;
var shippingIsRed = (shipping.className == "red");
var extraChecked = d.g("extra").checked;
if ( total() ) {
retval = (!shippingIsRed && !extraChecked)? true : false;
}
return retval;
} //end checkout
h1 {
font: 200% Arial, Helvetica;
font-weight: bold;
}
h2 {
font-weight: bold;
}
table,
td {
border: 1px solid black;
}
p.red {
color: #f00;
}
p.black {
color: #000;
}
<div>
<h1>Widgets R' Us</h1>
<h2>Order/Checkout</h2>
<form name="widgets" onsubmit="return checkOut()" action="https://www.example.com/" method="post">
<div id="mainTable">
<table>
<tr>
<td>Widget Model:</td>
<td>37AX-L
<td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$12.45 <input type="hidden" id="Price1" name="Price1" value="12.45" </td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity1" name="Quantity1" value="0" </td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Widget Model:</td>
<td>42XR-J</td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$15.34 <input type="hidden" id="Price2" name="Price2" value="15.34"></td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity2" name="Quantity2" value="0"></td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Widget Model:</td>
<td>93ZZ-A</td>
</tr>
<tr>
<td>Price per Unit:</td>
<td>$28.99 <input type="hidden" id="Price3" name="Price3" value="28.99"></td>
</tr>
<tr>
<td>State:</td>
<td>Regular</td>
</tr>
<tr>
<td>Quantity:</td>
<td> <input type="text" id="Quantity3" name="Quantity3" value="0"></td>
</tr>
</table>
<tr>
<td> </td>
<td> </td>
</tr>
<table>
<tr>
<td>Total Price:</td>
<td>
<p id="ProductTotal"> 0 </p>
</td>
</tr>
<tr>
<td> <input type="checkbox" id="extra" name="extra"> </td>
<td>
<p id="shipping" class="black">If the quantity exceeds 30 units, there will be extra shipping!</p>
</td>
</tr>
</table>
</div>
<tr>
<td> <input type="Submit" value="Submit" /> </td>
<td> <input type="button" value="Calculate" onClick="total()"> </td>
</tr>
</form>
I also removed some unnecessary repetitive code that fetches the quantity values, taking advantage of JavaScript closures and for-loops.
I have a button that the user clicks on to add a new row to the bottom of an input table. I would like this to also increment the id. So the next row would have desc2, hours2, rate2 and amount2 as the id. Is there a way to do this in the JavaScript function.
Also - just want to check my logic on this. After the user completes the filled out form, I will be writing all the data to a mysql database on two different tables. Is this the best way to go about this? I want the user to be able to add as many lines in the desc_table as they need. If this is the correct way to be going about this, what is the best way to determine how many lines they have added so I can insert into the db table using a while loop?
JS file:
function new_line() {
var t = document.getElementById("desc_table");
var rows = t.getElementsByTagName("tr");
var r = rows[rows.length - 1];
var x = rows[1].cloneNode(true);
x.style.display = "";
r.parentNode.insertBefore(x, r);
}
HTML:
<table id="desc_table">
<tr>
<td><font><br><h3>Description</h3></font></td>
<td><font><h3>Hours</h3></font></td>
<td><font><h3>Rate</h3></font></td>
<td><font><h3>Amount</h3></font></td>
<td></td>
</tr>
<tr>
<td ><textarea name="description" id="desc1" ></textarea></td>
<td> <input type="text" name="hours" id="hours1" ></td>
<td> <input type="text" name="rate" id="rate1"></td>
<td><input type="text" name="amount" id="amount1"></td>
<td>
<button type="button" name="add_btn" onclick="new_line(this)">+</button>
<button type="button" name="delete_btn" onclick="delete_row(this)">x</button>
</td>
</tr>
</table>
Thank you!
Check this code.After appending the row it counts the number of rows and and then assigns via if condition and incremental procedure the id's:
function new_line() {
var t = document.getElementById("desc_table");
var rows = t.getElementsByTagName("tr");
var r = rows[rows.length - 1];
var x = rows[1].cloneNode(true);
x.style.display = "";
r.parentNode.insertBefore(x, r);
for(var i=1;i<rows.length;i++){
if(rows[i].children["0"].children["0"].id.match((/desc/g))){
rows[i].children["0"].children["0"].id='desc'+i;
}
if(rows[i].children["1"].children["0"].id.match((/hours/g))){
rows[i].children["1"].children["0"].id='hours'+i;
}
if(rows[i].children["2"].children["0"].id.match((/rate/g))){
rows[i].children["2"].children["0"].id='rate'+i;
}
if(rows[i].children["3"].children["0"].id.match((/amount/g))){
rows[i].children["3"].children["0"].id='amount'+i;
}
}
}
<table id="desc_table">
<tr>
<td><font><br><h3>Description</h3></font></td>
<td><font><h3>Hours</h3></font></td>
<td><font><h3>Rate</h3></font></td>
<td><font><h3>Amount</h3></font></td>
<td></td>
</tr>
<tr>
<td ><textarea name="description" id="desc1" ></textarea></td>
<td> <input type="text" name="hours" id="hours1" ></td>
<td> <input type="text" name="rate" id="rate1"></td>
<td><input type="text" name="amount" id="amount1"></td>
<td>
<button type="button" name="add_btn" onclick="new_line(this)">+</button>
<button type="button" name="delete_btn" onclick="delete_row(this)">x</button>
</td>
</tr>
</table>
Please change variable names for more descriptive. :)
Example solution...
https://jsfiddle.net/Platonow/07ckv5u7/1/
function new_line() {
var table = document.getElementById("desc_table");
var rows = table.getElementsByTagName("tr");
var row = rows[rows.length - 1];
var newRow = rows[rows.length - 1].cloneNode(true);
var inputs = newRow.getElementsByTagName("input");
for(let i=0; i<inputs.length; i++) {
inputs[i].id = inputs[i].name + rows.length;
}
var textarea = newRow.getElementsByTagName("textarea")[0];
textarea.id = textarea.name + rows.length;
table.appendChild(newRow);
}
Note that I removed/edited below fragment.
x.style.display = "";
r.parentNode.insertBefore(x, r);
You could do this a lot easier with jquery or another dom manipulation language, but with vanilla JS here's an example of simply looping through the new row's inputs & textarea and incrementing a counter to append.
var count = 1;
function new_line() {
count++;
var t = document.getElementById("desc_table");
var rows = t.getElementsByTagName("tr");
var r = rows[rows.length - 1];
var x = rows[1].cloneNode(true);
x.style.display = "";
r.parentNode.insertBefore(x, r);
// update input ids
var newInputs = Array.from(x.getElementsByTagName('input'))
.concat(Array.from(x.getElementsByTagName('textarea')));
newInputs.forEach(function(input) {
var id = input.getAttribute('id').replace(/[0-9].*/, '');
input.setAttribute('id', id + count);
});
}
<table id="desc_table">
<tr>
<td><font><br><h3>Description</h3></font></td>
<td><font><h3>Hours</h3></font></td>
<td><font><h3>Rate</h3></font></td>
<td><font><h3>Amount</h3></font></td>
<td></td>
</tr>
<tr>
<td ><textarea name="description" id="desc1" ></textarea></td>
<td> <input type="text" name="hours" id="hours1" ></td>
<td> <input type="text" name="rate" id="rate1"></td>
<td><input type="text" name="amount" id="amount1"></td>
<td>
<button type="button" name="add_btn" onclick="new_line(this)">+</button>
<button type="button" name="delete_btn" onclick="delete_row(this)">x</button>
</td>
</tr>
</table>
After an ajax call, results is returned in success, then:
var the_data = results;
var buildHTML = [];
buildHTML.push("<tr><td>Department</td><td>Count</td><td>Value</td>");
for (var i = 0; i < the_data.length; i++) {
buildHTML.push("<tr><td>" + the_data[i].department + "</td><td>" + the_data[i].count + "</td><td>£" + the_data[i].value + "</td>");
}
$('.portlet-content').empty().append("<table>" + buildHTML.join('</tr>') + "</table>");
Which builds something like:
<table>
<tr>
<td>
Department
</td>
<td>
Count
</td>
<td>
Value
</td>
</tr>
<tr>
<td>
Marketing
</td>
<td>
10
</td>
<td>
£100,000
</td>
</tr>
<tr>
<td>
Information Technology
</td>
<td>
20
</td>
<td>
£1,000,000
</td>
</tr>
</table>
I know how to add another final row at the bottom of this table, but in that row, I want to display totals, i.e. a total of the count and a total of the value, e.g:
<table>
<tr>
<td>
Department
</td>
<td>
Count
</td>
<td>
Value
</td>
</tr>
<tr>
<td>
Marketing
</td>
<td>
10
</td>
<td>
£100,000
</td>
</tr>
<tr>
<td>
Information Technology
</td>
<td>
20
</td>
<td>
£1,000,000
</td>
</tr>
<tr>
<td>
Total
</td>
<td>
30
</td>
<td>
£1,100,000
</td>
</tr>
</table>
How can this be done at clientside?
Here is a generic solution that will work for any table with a tfoot and tbody:
$("table tfoot td").each(function(columnIndex) {
var totalsElement = $(this);
if (totalsElement.hasClass("sumTotal")) {
var sum = 0.0;
totalsElement.parents("table").find("tbody tr").each(function() {
sum += parseFloat($(this).children("td").eq(columnIndex).html());
});
totalsElement.html(sum);
}
});
You need to mark the computed footer cells with "sumTotal" CSS class. To keep it simple I had to remove the pound characters from the table but it works:
http://jsfiddle.net/fRdpJ/47/
You could simply amend the for loop in your code to get the sums.
...
// vars for sum
var the_count = 0, the_sum = 0;
for (var i = 0; i < the_data.length; i++) {
the_count += the_data[i].count;
the_sum += the_data[i].value;
buildHTML.push("<tr><td>" + the_data[i].department + "</td><td>" + the_data[i].count + "</td><td>£" + the_data[i].value + "</td>");
}
buildHTML.push("<tr><td>Total</td><td>" + the_count + "</td><td>" + the_sum + "</td>");
...
add a class="Count" on the TD for which you want to calculate count and then calculate count using JQuery like this:
http://jsfiddle.net/sv2dg/13/