I have a Dynamically created HTML table, when page loads I am creating the first row having following columns ItemName,I Code,MRP,Price,UnitQty,Disc%,DiscAmt,Gst%,GstAmt and TotalAmt
ItemName is autocomplete field, So user is selecting item name by typeing and when user focus out I am populating some respective fields ,When user Types inside UnitQty field I am calculating some values and populating according to that in respective fields on keyup event all this is happening in HTML table
outside the tabel I have a Input Field SubTotal which is I am getting with Some calculation i.e price * UnitQty so for respective table row There is a Total Amt column where I have to populate (price * UnitQty) +GstAmt +DiscAmt but currently I am populating price * UnitQty I will do that later
What My issue is
So below is a subTotal Input field where I am populating price * UnitQty of each row so I am storing the values in global variable and then adding the current variable into that but when I type suppose 2 and price is 100 it equals to 200 then I am removing 2 and writing 2 at that time it is adding the previous 200 and current 300 and populating 500 I know this is because of keyup it is adding previous value also but that's not correct
There is no column for subtotal in HTML table that's why I am storing it in a variable
function format(number, decimals = 2) {
const fixed = parseFloat(number).toFixed(decimals);
const [float, dec] = fixed.split('.')
const intFormatted = (+float)
return intFormatted + (dec ? '.' + dec : '');
}
$(document).ready(function() {
var tableData = {};
var tabledata = {
"ALMOND CHBAR~2402": {
"itemName": "ALMOND CHBAR",
"itemCode": "2402",
"costPrice": 20.0,
"gstPercentage": 14.5,
"unitCode": "NOS",
"mrp": 30.0
},
"A BR SB EX~333": {
"itemName": "A BR SB EX",
"itemCode": "333",
"costPrice": 1.0,
"gstPercentage": 0.0,
"unitCode": "NOS",
"mrp": 1.0
}
}
populateData(tabledata)
function rowappend(tbody) {
const markup =
`<tr>
<td>
<input type="text" class="form-control commanChange" id="itemNametd" name="itemNametd">
</td>
<td><input type="text" name="itemCodetd" id="itemCodetd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<td><input type="text" name="mrptd" id="mrptd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<td><input type="tel" id="purRatetd" class="form-control commantd"name="purRatetd"></td>
<td>
<input type="tel" id="unitQtytd"class="form-control commanChange" name="unitQtytd">
</td>
<td>
<input type="tel" id="discPercentagetd"class="form-control commanChange" name="discPercentagetd" value="0.00">
</td>
<td><input type="text" name="discAmttd" id="discAmttd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<td><input type="text" name="gstPercentagetd" id="gstPercentagetd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<td><input type="text" name="gstAmttd" id="gstAmttd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<td><input type="text" name="totalAmttd" id="totalAmttd" class="form-control commantd" readonly="readonly" tabindex="-1"></td>
<input type="hidden" name="unittd" id="unittd" class="form-control commantd">
<td style="background-color: white;border: 1px white"><i class="fas fa-times fa-2x remove-btn" ></i></td>
</tr>`
$(tbody).append(markup);
setTimeout(() => $("[name=itemNametd]", tbody).last().focus(), 100);
var autoCompleteData = Object.keys(tableData);
$("[name=itemNametd]", tbody).last().autocomplete({
source: autoCompleteData,
autoSelectFirst: true,
autoFocus: true
}).data('tableData', tableData);
}
function getValues(row) {
const search = ($('[name=itemNametd]', row).val()).toString()
var data = $('[name=itemNametd]', row).data('tableData');
const value = data[search];
if (value) {
CostPrice = value.costPrice;
$(row).find("[name=itemCodetd]").val(value.itemCode);
$(row).find("[name=mrptd]").val(format(value.mrp));
$(row).find("[name=purRatetd]").val(format(CostPrice));
$(row).find("[name=unittd]").val(value.unitCode);
$(row).find("[name=gstPercentagetd]").val(value.gstPercentage);
$("[name=purRatetd]").focus();
}
}
$(document).on("keyup", "[name=purRatetd]", function(e) {
const row = e.target.parentElement.parentElement
var unitQuantity = $(row).find("[name=unitQtytd]").val();
var purchaseRate = $(row).find("[name=purRatetd]").val();
var mrp = $(row).find("[name=mrptd]").val();
totalAmount = (parseFloat(unitQuantity) * parseFloat(purchaseRate)) || 0;
$(row).find("[name=totalAmttd]").val(format(totalAmount));
});
var subTotalAmt = 0;
$(document).on("keyup", "[name=unitQtytd]", function(e) {
const row = e.target.parentElement.parentElement
unitQuantity = $(row).find("[name=unitQtytd]").val();
purchaseRate = $(row).find("[name=purRatetd]").val();
mrp = $(row).find("[name=mrptd]").val();
totalAmount = (parseFloat(unitQuantity) * parseFloat(purchaseRate)) || 0;
subTotalAmt += totalAmount || 0
$(row).find("[name=totalAmttd]").val(format(totalAmount));
$("#subTotalInput").val(format(subTotalAmt));
});
document.addEventListener("keydown", function(e) {
const row = event.target.parentElement.parentElement
var keycode = event.keyCode || event.which;
if (keycode == '13') {
if (!$(event.target).val()) {
e.preventDefault();
return;
}
const row = e.target.parentElement.parentElement
if (event.target.matches('[name=discPercentagetd]')) {
if ($(row).parent().find('tr').length - $(row).index() === 1) {
rowappend(event.target.parentElement.parentElement.parentElement)
}
}
}
});
$(document).on("focusout", "[name=itemNametd]", function(e) {
const row = e.target.parentElement.parentElement
getValues(e.target.parentElement.parentElement)
});
function populateData(data) {
tableData = Object.assign({}, data);
var autoCompleteData = Object.keys(data);
rowappend($('tbody', '#tableInvoice'));
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="row tableGrn" id="commonDvScroll">
<table class="table table-bordered" id="tableInvoice">
<thead>
<tr>
<th id="itemNameth" class="commanth">Item Name</th>
<th id="itemCodeth" class="commanth">I Code</th>
<th id="mrpth" class="commanth">MRP</th>
<th id="purRateth" class="commanth">Price</th>
<th id="unitQtyth" class="commanth">Unit Qty</th>
<th id="discPercentageth" class="commanth">Disc %</th>
<th id="discAmtth" class="commanth">Disc Amt</th>
<th id="gstPercentageth" class="commanth">GST %</th>
<th id="gstAmtth" class="commanth">GST Amt</th>
<th id="totalAmtth" class="commanth">Total Amt</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class="form-row">
<div class="form-group col-xs-6 col-sm-6 col-md-6 col-lg-2">
<label for="subTotalInput">Sub Total</label>
<div class="input-group">
<input type="tel" class="form-control" aria-label="Text input with dropdown button" name="subTotalInput" id="subTotalInput" readonly="readonly" tabindex="-1">
</div>
</div>
</div>
Note-: Please don't get confused by TotalAmt column that one is for other usage which I will do by adding all the amounts
For now I have been stuck in calculating subTotal row wise and populate in a Input field
On press of enter at Disc% it will create a new row
Please replace your code with below code
$(document).on("keyup", "[name=purRatetd],[name=unitQtytd]", function(e) {
var unitQuantity = $(this).closest('tr').find("[name=unitQtytd]").val();
var purchaseRate = $(this).closest('tr').find("[name=purRatetd]").val();
var unitQuantity = unitQuantity ? unitQuantity : 1;
var mrp = $(this).closest('tr').find("[name=mrptd]").val();
totalAmount = (parseFloat(unitQuantity) * parseFloat(purchaseRate));
$(this).closest('tr').find("[name=totalAmttd]").val(totalAmount);
var subTotal = 0;
$("[name=totalAmttd]").each(function(){
var curVal = parseFloat($(this).val());
if(curVal){
subTotal = curVal + subTotal;
}
});
$("#subTotalInput").val(subTotal);
});
N:B - you are using id in input fields which will repeat again and again after apending so avoid using id and name...In entire code you can use class instead of name or id......class name can be same but id and name can't be same in multiple fields
Related
Scenario: I'd like to input the number at the top of the page. Then I press the button "First Line". It will create a new table row with 16 cells, with the numbers inputted displayed in the new cells. When I press another button "New Line", another row of 16 cells will appear below, with some particular numbers coming out in the new cells as I programmed in function newNo().
Question: I know my syntax in the function newNo() and the two var at the bottom of the js file is wrong. I want this function to be applied in all the new cells, so that it will look up the same "column" or the same cell in the 1st row, and produce a series of numbers according to the algorithm in newNo(), and show it in the next row, in each respective cell. Can this function do so in js/html?
Thanks a lot!
const tab = document.getElementById("tab");
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
btn1.addEventListener('click', () => {
let row = tab.insertRow(-1);
for (var i = 0; i <= 15; i++) {
let c = row.insertCell(i);
c.id = `R${row.rowIndex}C${++c.cellIndex}`;
let inpId = 'inp' + (i + 1);
let inpEl = document.getElementById(inpId);
c.innerHTML = inpEl.value;
}
});
function newCells() {
let row = tab.insertRow(-1);
for (var i = 0; i <= 15; i++) {
let c = row.insertCell(i);
c.id = `R${row.rowIndex}C${++c.cellIndex}`;
}
}
btn2.addEventListener('click', () => {
newCells();
newNo();
});
var row1 = [R1C1, R1C2, R1C3, R1C4, R1C5, R1C6, R1C7, R1C8, R1C9, R1C10, R1C11, R1C12, R1C13, R1C14, R1C15, R1C16];
var r1 = document.getElementById(row1).valueAsNumber;
function newNo() {
if (r1 > 0) {
var choices = [0, (R1C1.valueAsNumber) % 7, (R1C1.valueAsNumber + 2) % 7, (R1C1.valueAsNumber - 2) % 7];
var x = Math.floor(Math.random() * choices.length);
if (choices[x] == choices.at(0)) {
R2C1.innerHTML = choices[x];
} else if (choices[x] !== choices.at(0) && choices[x] <= 0) {
R2C1.innerHTML = choices[x] + 7;
}
}
}
th,
tr,
td {
border: 1px solid black;
padding: 5px;
width: 40px;
}
<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">New Line</button>
</div>
<br>
<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>
</table>
</div>
I have a scoreboard where the user can enter the score and when the user presses the "Submit" button it will show a table that will contain the information that the user has entered. But when I try it in the browser, my table doesn't show the information that was entered in the previous form, it only show the table heading. Let me explain like below:
var testScore = {
name: "",
math: 0,
physical: 0,
chemistry: 0,
avg: 0
};
var i = 1;
// This is the table will show after submited
function score_table() {
document.getElementById("divTable").style.display = "block";
// Gathering the data
testScore.name = document.getElementById("name").value;
testScore.math = document.getElementById("math").value;
testScore.physical = document.getElementById("physics").value;
testScore.chemistry = document.getElementById("chemical").value;
testScore.avg = (parseFloat(testScore.math) + parseFloat(testScore.physics) + parseFloat(testScore.chemistry)) / 3;
// How to get this average score has the form like 8,33 or 6,69, I need //help
document.getElementById("name").value = "";
document.getElementById("math").value = "";
document.getElementById("physics").value = "";
document.getElementById("chemical").value = "";
// Add the information but why it does not work
var table = document.getElementById("tableScore");
var row = table.insertRow(i);
var number = row.insertCell(0);
var name = row.insertCell(1);
var math = row.insertCell(2);
var physics = row.insertCell(3);
var chemistry = row.insertCell(4);
var avg = row.insertCell(5);
number.innerHtml = i;
name.innerHtml = testScore.name;
math.innerHtml = testScore.math;
physics.innerHtml = testScore.physics;
chemistry.innerHtml = testScore.chemistry;
avg.innerHtml = testScore.avg;
i++;
}
#divTable {
display: none;
width: 100%;
}
#tableScore th:nth-child(6),
#tableScore td:nth-child(6) {
display: none;
}
<script src="js/script.js"></script>
<h1 align="center">Class Marksheet</h1>
<!--This is the first table when user access the browser-->
<table align="center">
<tr>
<td>Name:</td>
<td><input name="name" id="name" type="text" /></td>
</tr>
<tr>
<td>Math:</td>
<td>
<input name="math" id="math" type="number" />
</td>
</tr>
<tr>
<td>Physics:</td>
<td>
<input name="physics" id="physics" type="number" />
</td>
</tr>
<tr>
<td>Chemistry:</td>
<td>
<input name="chemical" id="chemical" type="number" />
</td>
</tr>
<td>
<!--This button will show the second table below-->
<button type="submit" onclick="score_table()">Submit</button>
</td>
</table>
<div id="divTable">
<!--This table only show when user click on the "Submit" button and it contains
all the information that submitted. But I try on browser and it is not show the information.
-->
<table id="tableScore" border="2">
<th>No</th>
<th>Name</th>
<th>Math</th>
<th>Physics</th>
<th>Chemistry</th>
<th>Average score</th>
</table>
<button onclick="showAvg()">Show the average score</button>
<button onclick="showBest()">Best student</button>
</div>
In js code you have used innerHtml instead of innerHTML.
Updated code:
var testScore = {
name: "",
math: 0,
physical: 0,
chemistry: 0,
avg: 0
};
var i = 1;
// This is the table will show after submited
function score_table() {
document.getElementById("divTable").style.display = "block";
// Gathering the data
testScore.name = document.getElementById("name").value;
testScore.math = document.getElementById("math").value;
testScore.physical = document.getElementById("physics").value;
testScore.chemistry = document.getElementById("chemical").value;
testScore.avg = (parseFloat(testScore.math) + parseFloat(testScore.physics) + parseFloat(testScore.chemistry)) / 3;
// How to get this average score has the form like 8,33 or 6,69, I need //help
document.getElementById("name").value = "";
document.getElementById("math").value = "";
document.getElementById("physics").value = "";
document.getElementById("chemical").value = "";
// Add the information but why it does not work
var table = document.getElementById("tableScore");
var row = table.insertRow(i);
var number = row.insertCell(0);
var name = row.insertCell(1);
var math = row.insertCell(2);
var physics = row.insertCell(3);
var chemistry = row.insertCell(4);
var avg = row.insertCell(5);
number.innerHTML = i;
name.innerHTML = testScore.name;
math.innerHTML = testScore.math;
physics.innerHTML = testScore.physics;
chemistry.innerHTML = testScore.chemistry;
avg.innerHTML = testScore.avg;
i++;
}
#import url('https://fonts.googleapis.com/css2?family=Bree+Serif&family=Caveat:wght#400;700&family=Lobster&family=Monoton&family=Open+Sans:ital,wght#0,400;0,700;1,400;1,700&family=Playfair+Display+SC:ital,wght#0,400;0,700;1,700&family=Playfair+Display:ital,wght#0,400;0,700;1,700&family=Roboto:ital,wght#0,400;0,700;1,400;1,700&family=Source+Sans+Pro:ital,wght#0,400;0,700;1,700&family=Work+Sans:ital,wght#0,400;0,700;1,700&display=swap');
#divTable {
display: none;
width: 100%;
}
#tableScore th:nth-child(6),
#tableScore td:nth-child(6) {
display: none;
}
<!DOCTYPE html>
<html>
<head> </head>
<body>
<script src="js/script.js"></script>
<h1 align="center">Class Marksheet</h1>
<!--This is the first table when user access the browser-->
<table align="center">
<tr>
<td>Name:</td>
<td><input name="name" id="name" type="text" /></td>
</tr>
<tr>
<td>Math:</td>
<td>
<input name="math" id="math" type="number" />
</td>
</tr>
<tr>
<td>Physics:</td>
<td>
<input name="physics" id="physics" type="number" />
</td>
</tr>
<tr>
<td>Chemistry:</td>
<td>
<input name="chemical" id="chemical" type="number" />
</td>
</tr>
<td>
<!--This button will show the second table below-->
<button type="submit" onclick="score_table()">Submit</button>
</td>
</table>
<div id="divTable">
<!--This table only show when user click on the "Submit" button and it contains
all the information that submitted. But I try on browser and it is not show the information.
-->
<table id="tableScore" border="2">
<th>No</th>
<th>Name</th>
<th>Math</th>
<th>Physics</th>
<th>Chemistry</th>
<th>Average score</th>
</table>
<button onclick="showAvg()">Show the average score</button>
<button onclick="showBest()">Best student</button>
</div>
</body>
</html>
When you use insertCell you need to use innerHTML or appendChild instead of the non-existent innerHtml
Also you do not need to have any integer in insertCell/Row
Also your HTML was invalid
number.appendChild(document.createTextNode(i));
name.appendChild(document.createTextNode(testScore.name));
math.appendChild(document.createTextNode(testScore.math));
physics.appendChild(document.createTextNode(testScore.physics));
chemistry.appendChild(document.createTextNode(testScore.chemistry));
avg.appendChild(document.createTextNode(testScore.avg));
var testScore = {
name: "",
math: 0,
physical: 0,
chemistry: 0,
avg: 0
};
var i = 1;
// This is the table will show after submited
function score_table() {
document.getElementById("divTable").style.display = "block";
// Gathering the data
testScore.name = document.getElementById("name").value;
testScore.math = document.getElementById("math").value;
testScore.physics = document.getElementById("physics").value;
testScore.chemistry = document.getElementById("chemical").value;
testScore.avg = (parseFloat(testScore.math) + parseFloat(testScore.physics) + parseFloat(testScore.chemistry)) / 3;
// How to get this average score has the form like 8,33 or 6,69, I need //help
document.getElementById("name").value = "";
document.getElementById("math").value = "";
document.getElementById("physics").value = "";
document.getElementById("chemical").value = "";
// Add the information but why it does not work
var table = document.querySelector("#tableScore tbody");
var row = table.insertRow();
var number = row.insertCell();
var name = row.insertCell();
var math = row.insertCell();
var physics = row.insertCell();
var chemistry = row.insertCell();
var avg = row.insertCell();
number.appendChild(document.createTextNode(i));
name.appendChild(document.createTextNode(testScore.name));
math.appendChild(document.createTextNode(testScore.math));
physics.appendChild(document.createTextNode(testScore.physics));
chemistry.appendChild(document.createTextNode(testScore.chemistry));
avg.innerHTML = testScore.avg; // alternative to appendChild
i++;
}
#divTable {
display: none;
width: 100%;
}
#tableScore th:nth-child(6),
#tableScore td:nth-child(6) {
display: none;
}
<script src="js/script.js"></script>
<h1 align="center">Class Marksheet</h1>
<!--This is the first table when user access the browser-->
<table align="center">
<tr>
<td>Name:</td>
<td><input name="name" id="name" type="text" /></td>
</tr>
<tr>
<td>Math:</td>
<td>
<input name="math" id="math" type="number" />
</td>
</tr>
<tr>
<td>Physics:</td>
<td>
<input name="physics" id="physics" type="number" />
</td>
</tr>
<tr>
<td>Chemistry:</td>
<td>
<input name="chemical" id="chemical" type="number" />
</td>
</tr>
<td>
<!--This button will show the second table below-->
<button type="submit" onclick="score_table()">Submit</button>
</td>
</table>
<div id="divTable">
<!--This table only show when user click on the "Submit" button and it contains
all the information that submitted. But I try on browser and it is not show the information.
-->
<table border="2" id="tableScore">
<thead>
<th>No</th>
<th>Name</th>
<th>Math</th>
<th>Physics</th>
<th>Chemistry</th>
<th>Average score</th>
</thead>
<tbody>
</tbody>
</table>
<button onclick="showAvg()">Show the average score</button>
<button onclick="showBest()">Best student</button>
</div>
You have some misspelled variables but you can also minimize your output with only one global innerHTML like in my example below:
var testScore = {
name: "",
math: 0,
physical: 0,
chemistry: 0,
avg: 0
};
var i = 1;
// This is the table will show after submited
function score_table() {
document.getElementById("divTable").style.display = "block";
// Gathering the data
testScore.name = document.getElementById("name").value;
testScore.math = document.getElementById("math").value;
testScore.physical = document.getElementById("physics").value;
testScore.chemistry = document.getElementById("chemical").value;
testScore.avg = (parseFloat(testScore.math) + parseFloat(testScore.physics) + parseFloat(testScore.chemistry)) / 3;
// How to get this average score has the form like 8,33 or 6,69, I need //help
document.getElementById("name").value = "";
document.getElementById("math").value = "";
document.getElementById("physics").value = "";
document.getElementById("chemical").value = "";
//MINIMIZED VERSION
document.getElementById("tableScore").innerHTML +=
"<td>" + i + "</td>" +
"<td>" + testScore.name + "</td>" +
"<td>" + testScore.math + "</td>" +
"<td>" + testScore.physical + "</td>" +
"<td>" + testScore.chemistry + "</td>" +
"<td>" + testScore.avg + "</td>";
i++;
}
#divTable {
display: none;
width: 100%;
}
#tableScore th:nth-child(6),
#tableScore td:nth-child(6) {
display: none;
}
<script src="js/script.js"></script>
<h1 align="center">Class Marksheet</h1>
<!--This is the first table when user access the browser-->
<table align="center">
<tr>
<td>Name:</td>
<td><input name="name" id="name" type="text" /></td>
</tr>
<tr>
<td>Math:</td>
<td>
<input name="math" id="math" type="number" />
</td>
</tr>
<tr>
<td>Physics:</td>
<td>
<input name="physics" id="physics" type="number" />
</td>
</tr>
<tr>
<td>Chemistry:</td>
<td>
<input name="chemical" id="chemical" type="number" />
</td>
</tr>
<td>
<!--This button will show the second table below-->
<button type="submit" onclick="score_table()">Submit</button>
</td>
</table>
<div id="divTable">
<!--This table only show when user click on the "Submit" button and it contains
all the information that submitted. But I try on browser and it is not show the information.
-->
<table id="tableScore" border="2">
<th>No</th>
<th>Name</th>
<th>Math</th>
<th>Physics</th>
<th>Chemistry</th>
<th>Average score</th>
</table>
<button onclick="showAvg()">Show the average score</button>
<button onclick="showBest()">Best student</button>
</div>
I have a dynamically generated table like below
this is the code that generate this table
function pullInventory(data) {
var container = document.getElementById('inventoryContainer')
var index = 0;
console.log(index)
data.forEach(function(awardsSnap) {
index ++;
// console.log(awardsSnap, index)
var awardItem = awardsSnap.val()
// Attach an asynchronous callback to rea
var NSNcard = `
<tr>
<td class="serial">${awardItem.NSN}</td>
<td> ${awardItem.Nomenclature} </td>
<td> ${awardItem.Awarddate} </td>
<td> ${awardItem.Awardid} </td>
<td>
<input type="text" placeholder="i.e. 100 EA" class="form-control" value="" id="qty${index}"style="width: 110px;">
</td>
<td>
<input type="text" placeholder="i.e. $9.23 " class="form-control" value="" style="width: 110px;">
</td>
</tr>
`;
container.innerHTML += NSNcard;
});
}
I want to get all the user entered quantity and price on a button click so I use this
document.querySelector("#savebtn").addEventListener("click", e => {
var rows = document.getElementById("WelcomeTable").getElementsByTagName("tbody")[0].getElementsByTagName("tr").length;
saveInventory(rows);
});
function saveInventory(rows) {
const columnHeader = Array.prototype.map.call(
document.querySelectorAll(".table th"),
th => {
return th.innerHTML;
}
);
const tableContent = Object.values(
document.querySelectorAll(".table tbody tr")
).map(tr => {
const tableRow = Object.values(tr.querySelectorAll("td")).reduce(
(accum, curr, i) => {
const obj = { ...accum };
obj[columnHeader[i]] = curr.innerHTML.trim();
console.log(accum, curr, i)
return obj;
},
{}
);
return tableRow;
});
}
everything works fine except that the two input column in the table above does not detect user input. I'm not able to get the quantity and price value entered.
Award Date: "08-23-2012"
Award#: "SP452013D0055"
NSN: "S222V00004789"
Nomenclature: " BATTERIES, NICKEL-CADMIUM"
Quantity: "<input type="text" placeholder="i.e. 100 EA" class="form-control" value="" id="qty18" style="width: 110px;">"
Unit-Price: "<input type="text" placeholder="i.e. $9.23 " class="form-control" value="" style="width: 110px;">"
I tried this and other things but they output undefine
obj[columnHeader[4]]=curr.val();
obj[columnHeader[4]]=curr.value;
how could i get the enetered quantity and price from the dynamic table?
You could try doing something like this:
window.onload = ()=>{
let targetTable = document.getElementById('target-table');
let targetTableRows = targetTable.rows;
let tableHeaders = targetTableRows[0];
// start from the second row as the first one only contains the table's headers
for(let i = 1; i < targetTableRows.length; i++){
// loop over the contents of each row
for(let j = 0; j < targetTableRows[i].cells.length; j++){
// something we could use to identify a given item
let currColumn = tableHeaders.cells[j].innerHTML;
// the current <td> element
let currData = targetTableRows[i].cells[j];
// the input field in the row
let currDataInput = currData.querySelector('input');
// is the current <td> element containing an input field? print its value.
// Otherwise, print whatever is insside
currDataInput ? console.log(`${currColumn}: ${currDataInput.value}`)
: console.log(`${currColumn}: ${currData.innerHTML}`);
}
}
};
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
<table class="table" id="target-table">
<thead>
<tr>
<th scope="col">Person #</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
<th scope="col">Quantity</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
<td><input type="text" value="01-quantity" id="value-01"></td>
<td><input type="text" value="01-price" id="value-01-2"></td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>#fat</td>
<td><input type="text" value="02-quantity" id="value-02"></td>
<td><input type="text" value="02-price" id="value-02-2"></td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>#twitter</td>
<td><input type="text" value="03-quantity" id="value-03"></td>
<td><input type="text" value="03-price" id="value-03-2"></td>
</tr>
</tbody>
</table>
What is done in the example above should also work for your specific case.
Also, here's a working exmaple :)
val() is jQuery method. You'll need to use .value in JavaScript.
obj[columnHeader[i]] = curr.innerHTML.trim();
innerHtml.trim returns only tag having direct child with text in it. In your code last two td having an input as child.
so in that case you need to check 'curr' having a child available. if there is a child available and its tagName is input, then you have to use childs value.
for example
obj[columnHeader[i]] = curr.children.length && curr.children[0].tagName=="INPUT" ? curr.children[0].value : curr.innerHTML.trim();
the above condition can be check and assign to a variable before it is assigned to key
O.k today is starting to be 1 step forward and 2 steps back. I have a Jquery function that does the price x qty = subtotal in the form and then each subtotal is calculated into a total, Which is all fine and dandy. I then have a plain js function that took that total value and added the gst and then a further subtotal figure which was created on it's own and works then at this point when i tried to move it over the gst and finial total functions won't work and i can't get any error codes out of it either. At this point i can only assume that the js script can't talk to the Jquery script or something is really wrong.
// Jquery script
<script type="text/javascript">
jQuery(function($) {
$(".qty, .tradeprice").change(function() {
var total = 0;
$(".qty").each(function() {
var $qty = $(this),
$row = $qty.closest('tr'),
$tradePrice = $row.find('.tradeprice'),
$subtotal = $row.find('.subtotal');
subtotal = parseInt($qty.val(), 10) * parseFloat($tradePrice.val());
total += subtotal;
$subtotal.val(subtotal);
});
$('.total').val(total);
}).change();
});
</script>
// JS script
<script type="text/javascript">
function updatePrice() {
// Get the ex-GST price from its form element
var exPrice = document.getElementById("ex-gst").value;
var gstPrice = document.getElementById("gst").value;
// Get the GST price
gstPrice = exPrice * 0.1;
var TPrice = parseInt(gstPrice) + parseInt(exPrice);
// Set the GST price in its form element
document.getElementById("gst").value = gstPrice;
document.getElementById("inc-gst").value = TPrice;
}
</script>
// bottom of HTML
<form>
<table>
<tr>
<th><input type='text' name='po101' id='po101'/></th>
<td><input name='po102' type='text' id="po102"/></td>
<td><input name='po103' type='text' id="po103" /></td>
<td>$<input name='po104' type="text" class='tradeprice' id="po104" value="0" /></td>
<th><input name='po105' type="text" class='qty' id="po105" value="0" /></th>
<td><input name='po106' type='text' class='subtotal' id="po106" readonly="true" /></td>
</tr>
<tr>
<th height='24' colspan="7">Total:<input type='text' id='Total' name='Total' class='total' readonly="true" onChange="updatePrice()"/></th>
</tr>
<tr>
<th height='24' colspan="7"><div id='submit'><input type='submit' /></div></th>
</tr>
<tr>
<th height='24' colspan="7">
<input type='text' id="gst" name='gst' onChange="updatePrice()" />
<input type='text' id="inc-gst" name='inc-gst' onChange="updatePrice(this.form)"/>
</th>
</tr>
</table>
</form>
I have now edited you code, and changed this line
var exPrice = document.getElementById("ex-gst").value;
to
var exPrice = document.getElementById("Total").value;
I have also updated the code by removing onChange() from HTML and added the trigger for your updatePrice() function to the change event.
And then this is the result (I have also added the jQuery version as comments, both will work).
jQuery(function($) {
$(".qty, .tradeprice").change(function() {
var total = 0;
$(".qty").each(function() {
var $qty = $(this),
$row = $qty.closest('tr'),
$tradePrice = $row.find('.tradeprice'),
$subtotal = $row.find('.subtotal');
subtotal = parseInt($qty.val(), 10) * parseFloat($tradePrice.val());
total += subtotal;
$subtotal.val(subtotal);
});
$('.total').val(total);
updatePrice();
}).change();
});
function updatePrice() {
// Get the ex-GST price from its form element
var exPrice = document.getElementById("Total").value;
//var exPrice = $('#Total').val() //this is jQuery
var gstPrice = document.getElementById("gst").value;
//var exPrice = $('#gst').val() //this is jQuery
// Get the GST price
gstPrice = exPrice * 0.1;
var TPrice = parseInt(gstPrice) + parseInt(exPrice);
// Set the GST price in its form element
document.getElementById("gst").value = gstPrice;
//$('#gst').val(gstPrice) //this is jQuery
document.getElementById("inc-gst").value = TPrice;
//$('#inc-gst').val(TPrice) //this is jQuery
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<table>
<tr>
<th>
<input type='text' name='po101' id='po101' />
</th>
<td>
<input name='po102' type='text' id="po102" />
</td>
<td>
<input name='po103' type='text' id="po103" />
</td>
<td>$
<input name='po104' type="text" class='tradeprice' id="po104" value="0" />
</td>
<th>
<input name='po105' type="text" class='qty' id="po105" value="0" />
</th>
<td>
<input name='po106' type='text' class='subtotal' id="po106" readonly="true" />
</td>
</tr>
<tr>
<th height='24' colspan="7">Total:
<input type='text' id='Total' name='Total' class='total' readonly="true" />
</th>
</tr>
<tr>
<th height='24' colspan="7">
<div id='submit'>
<input type='submit' />
</div>
</th>
</tr>
<tr>
<th height='24' colspan="7">
<input type='text' id="gst" name='gst' />
<input type='text' id="inc-gst" name='inc-gst' />
</th>
</tr>
</table>
</form>
I have an invoice form to generate a PDF. I want to calculate the inputs after the change of the value that the user fills in the form.
I can calculate the first row, but i want to (1) calculate each row and at the end to (2) calculate all the colums properly. For the first step just to the (1) and i will make the total calculation.
The problem is that i generate the rows with dynamic name and id because i post them in an array to the database. For this example the id is the same for every row of inputs.
PS: i cannot make .change work and i use $(document).on('change', '#qty', function (e) { calculateLine(); }); to trigger the calculation function for each input. I dont know why .change is not working as it support to, with latest jquery.
[invoice.php]
<script>
$(document).ready(function () {
$(document).on('change', '#qty', function (e) { calculateLine(); });
$(document).on('change', '#price', function (e) { calculateLine(); });
$(document).on('change', '#discount', function (e) { calculateLine(); });
$(document).on('change', '#discountPrice', function (e) { calculateLine(); });
});
</script>
[invoice.js]
function calculateLine() {
var qty = parseFloat($('#qty').val());
var price = parseFloat($('#price').val());
var discount = parseFloat($('#discount').val());
var discountPrice = parseFloat($('#discountPrice').val());
var vat = parseFloat($('#vat').val());
var netTotal = 0;
var total = 0;
var vatAmount = 0;
if (!qty && qty == 0) {
return;
}
if (!price && price == 0) {
return;
}
netTotal = qty * price;
if ((!discount || discount == 0) && discountPrice != 0) {
discount = (discountPrice / netTotal) * 100;
}
if ((!discountPrice || discountPrice == 0) && discount != 0) {
discountPrice = (netTotal / 100) * discount;
}
if (discountPrice != 0 && discount != 0) {
discountPrice = (netTotal / 100) * discount;
}
if ((!discount || discount == 0) && (!discountPrice || discountPrice == 0)) {
discountPrice = 0;
discount = 0;
}
total = netTotal - discountPrice;
if (!total || total == 0) {
total = 0;
}
vatAmount = (total / 100) * vat;
$('#total').val(total);
$('#discount').val(discount);
$('#discountPrice').val(discountPrice);
$('#vatAmount').val(vatAmount);
//calculateTotal();
}
[html]
<tr>
<td class="col-xs-0">
<input type="checkbox" name="selected[]" class="checkall">
</td>
<td class="col-xs-5">
<textarea type="text" name="invoice[item][{{j}}][description]" class="form-control description" rows="1" ></textarea>
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][unit]" class="form-control unit" value="" />
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][qty]" class="form-control qty" value="" />
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][price]" class="form-control price" value="" />
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][discount]" class="form-control discount" value="" >
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][discountPrice]" class="form-control discountPrice" />
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][total]" class="form-control total" value="" />
</td>
<td class="col-xs-1">
<input type="text" name="invoice[item][{{j}}][vat]" class="form-control vat" value="{{invcl_vat}}" readonly />
<input type="hidden" name="invoice[item][{{j}}][vatAmount]" class="form-control vatAmount" value="" readonly />
</td>
</tr>
You haven't shown your HTML, but it's clear from your question that you're using the same id (qty, etc.) on more than one element. You can't do that. Every id must be unique on the page. In this case, you'd probably use classes instead.
The general way that you do what you're talking about is indeed to use delegated event handling, then find the containing row, and use that as the starting point looking for descendant inputs using classes rather than ids:
$("selector-for-the-table").on("change", "input", function() {
// Get the row containing the input
var row = $(this).closest("tr");
// Get the values from _this row's_ inputs, using `row.find` to
// look only within this row
var qty = parseFloat(row.find('.qty').val());
var price = parseFloat(row.find('.price').val());
var discount = parseFloat(row.find('.discount').val());
var discountPrice = parseFloat(row.find('.discountPrice').val());
var vat = parseFloat(row.find('.vat').val());
// ...
});
I've also rooted that on the table, rather than document, so it only applies where appropriate.
Live (Simplified) Example:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<meta charset="utf-8">
<title>Example</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" class="qty"></td>
<td><input type="text" class="price"></td>
<td><input type="text" class="total" disabled></td>
</tr>
<!-- ...and so on... -->
</tbody>
</table>
<script>
(function() {
"use strict";
$("table").on("change", "input", function() {
var row = $(this).closest("tr");
var qty = parseFloat(row.find(".qty").val());
var price = parseFloat(row.find(".price").val());
var total = qty * price;
row.find(".total").val(isNaN(total) ? "" : total);
});
})();
</script>
</body>
</html>
You've said before that the names are dynamic. Surely there is some characteristic of the fields you're trying to find that is consistent, or you can make them consistent. In the worst case (and I mean in the worst case), you could do something based on position — the first input in the row is row.find("input:eq(0)"), the second is row.find("input:eq(1)"), and so on.
Live Example Using eq:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<meta charset="utf-8">
<title>Example</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text"></td>
<td><input type="text"></td>
<td><input type="text" disabled></td>
</tr>
<!-- ...and so on... -->
</tbody>
</table>
<script>
(function() {
"use strict";
$("table").on("change", "input", function() {
var row = $(this).closest("tr");
var qty = parseFloat(row.find("input:eq(0)").val());
var price = parseFloat(row.find("input:eq(1)").val());
var total = qty * price;
row.find("input:eq(2)").val(isNaN(total) ? "" : total);
});
})();
</script>
</body>
</html>
But avoid that if you possibly can, it's fragile — if you change the order of columns, you have to change your code.