Dynamic form field extraction and calculation, how? - javascript

I have a form with variable length of dynamic field names, for instanced, item{n}, the n could be 1 or 30, and I need to calculate the subtotal of qty{n} * price{n} for each such data row, then finally sum subtotal up.
The form looks like the following:
<form>
<table name="forInstruction">
<tr><td>... </td> <td>...</td> ... more td </tr>
....
</table>
<table name="forUserinput">
<tr>
<td><input type="text" id="item1">,</td> <td><input type="text" id="qty1">,</td>
<td><input type="text" id="price1">,</td> <td>fieldX1 t1 </td> ... more td
</tr>
<tr>
<td><input type="text" id="item2">,</td> <td><input type="text" id="qty2">,</td>
<td><input type="text" id="price2">,</td> <td>fieldX2,t2 </td> ... more td
<td><input type="text" id="item3">,</td> <td><input type="text" id="qty3">,</td>
<td><input type="text" id="price3">,</td> <td>fieldX3,t3 </td> ... more td
...
</table>
<input type="button" value="Calculate subtotal and total" ... />
</form>
Notes:
a) t{n} = subtotal field.
b) as mentioned above, number of rows is unknown, it could be 1 to 30.
What I'd like to do is: calculate subtotal and total.
each subtotal = qty{n} * parseFloat(price{n})
My attempt is to loop through the entire form, I'm able to retrieve
all the values for the qty{n} field,
but I don't know how to retrieve the value of its Corresponding
Price{n}.
var fQ=0,fP=0;
st = 0;
total = 0;
for (f=0; f < document.qr.elements.length; f++) {
if (document.qr.elements[f].name.indexOf('qty')>=0) {
// alert(document.qr.elements[f].name + ' ' + document.qr.elements[f].value);
fQ = document.qr.elements[f].value;
// alert(fQ);
}
else if (document.qr.elements[f].name.indexOf('priceLabel')>=0) {
fP = document.qr.elements[f].value;
}
// what do we do here? Or this is not the good way to go?
}
Maybe, loop through the entire form isn't a good idea... only data rows in a named table? If so, how?
Many thanks in advance.
EDIT 1:
Upon advice,
new code:
var i = 0, t=0,
element;
while ((element = forms[0].elements['qty' + i])) {
var subtotal = forms[0].elements['qty' + i] * forms[0].elements['price' + i];
forms[0].elements['total' + i].value = subtotal;
t = t + parseFloat(subtotal);
alert(t);
// ...
i++;
}
forms[0].elements['totalFinal'].value = t;
but err msg:
"ReferenceError: forms is not defined". How come? Thanks.

Related

How to create a function for Onkeyup

I am trying to write a function to analyze the users input before calling Onkeyup. I am not sure where to write this if statement, or if I have the correct syntax. I wrote the if statement inside the asset-tag class. This is my code:
const getAssetInfo = (assetTag, index) => {
// get the table row that this input is in
$.get("http://localhost:3000/assets/" + assetTag , (data) => {
// find the `.description` element and set it's value
if (data){
$(`#manufacturer_serial_no${index}`).val(data.serial_no);
$(`#description${index}`).val(data.description);
$(`#cost${index}`).val(data.cost);
$(`#po_no${index}`).val(data.po_no);
}
console.log(data);
})
.fail(() => {
// alert("DONE");
// console.log(index);
$(`#manufacturer_serial_no${index}`).val("");
$(`#description${index}`).val("");
$(`#cost${index}`).val("");
$(`#po_no${index}`).val("");
});
};
$('document').ready(() => {
// Handler to Add New Asset
const table = $("#formTable tbody");
let count = 1;
$('#add').click(() => {
const newRow = `
<tr index="${count}">
<form>
<td><input
class="asset-tag" id='asset_tag_no${count}' type='text'
if (input.length >= 4){
console.log('not enough characters to call API endpoint');
}
else{
onkeyup = "getAssetInfo(this.value,${count})";
}
bottom required /></td>
<td><input class="serial-no" id='manufacturer_serial_no${count}' type='text' bottom required readonly/></td>
<td><textarea class="description" id='description${count}' type='text' bottom required readonly description></textarea></td>
<td><input id='cost${count}' type='value' bottom require readonly/></td>
<td><input id='po_no${count}' type='text' bottom require readonly/></td>
<td><textarea id='remarks${count}' type='text' bottom remarks></textarea></td>
<td><button type="button" index="${count}" class="btn btn-danger btn-remove">X</button></td>
</form>
</tr>
`;
table.append(newRow);
// Handler to Remove New Asset
$('.btn-remove').click(function(){
let index = $(this).attr('index');
$(`tr[index='${index}'`).remove();
});
count++;
});
I want this error in the console log to only execute when a certain amount of characters are in the box instead of each time a character is inputted.

How to calculate each table row indipendently on keyup

<tbody id="dailysale_tbody">
<tr class="items">
<td><select id="items_select" name="dailysale[luitem_id]"><option value=""></option></select></td>
<td><select id="brands_select" name="dailysale[lubrand_id]"><option value=""></option></select></td>
<td><select id="models_select" name="dailysale[lumodel_id]"><option value=""></option></select></td>
<td><input class="texts" id="dailysale_qty" name="dailysale[qty]" type="text" /></td>
<td><input class="texts" id="dailysale_price" name="dailysale[price]" type="text" /></td>
<td><input class="texts" id="dailysale_total" name="dailysale[total]" type="text" /></td>
<td><input type="checkbox" class="delete_row"></td>
</tr>
$(function() {
$('#dailysale_qty, #dailysale_price').keyup(function() {
var last_item = $('.items').find('#dailysale_qty');
var qty = last_row.find('#dailysale_qty').val();
var price = last_row.find('#dailysale_price').val();
var sub_total = last_row.find('#dailysale_total');
var s_total = qty * price;
if (isNaN(s_total)) {
sub_total.val('0');
}
else
sub_total.val(s_total);
});
});
I am able to perform calculations on this row. However, when I dynamically add rows with jquery, calculations are not working on the other rows.
When the calculating function is bind a button onclick, everything works well. But not on input keyup as required. I want to perform calculations on the new added row with onkeyup on qty and price input fields.
Note than upon cloning, the ids are stripped of the current row and assigned to the new row for reference.
You probably not registering keyup function when you adding new row.
You should do :
$('#dailysale_qty, #dailysale_price').unbind('keyup').keyup( function(...
Every time you adding new row.
#Nosyara The suggested line of code isn't working. Here is how am adding new rows. The commented line is what you suggested.
$(function(){
$('#newitembtn').click(function(){
//$('#dailysale_qty, #dailysale_price').unbind('keyup').keyup(function() {
var last_row = $('#dailysale_tbody').find('tr:last');
var newrow = last_row.clone();
last_row.find('#items_select').removeAttr('id');
last_row.find('#brands_select').removeAttr('id');
last_row.find('#models_select').removeAttr('id');
last_row.find('#dailysale_qty').removeAttr('id');
last_row.find('#dailysale_price').removeAttr('id');
last_row.find('#dailysale_total').removeAttr('id');
newrow.find('#items_select').val('');
newrow.find('#brands_select').val('');
newrow.find('#models_select').val('');
newrow.find('#dailysale_qty').val('');
newrow.find('#dailysale_price').val('');
newrow.find('#dailysale_total').val('');
last_row.after(newrow);
});
});
});

dynamically recalculate the input field values based on the total amount with jQuery

I have a page which has a Total Amount input field and an HTML table with rows having column showing the item amount(from db) and a input field against it(autopopulates the split amt from the Total Amount and also allows user input). My requirement is, when the user inputs the total amount, it should get split into the input boxes(applied amount column) in the table based on their item amount(Item Amount column prepopulated from db)
Eg: Input Amount:100
Item Amount | Applied amount(input box)
25 25
100 75
50 0
I'm able achieve this by:
var oidata = [];
var poidata = "", poibalance = "";
function applyAmount() {
oidata = [];
poidata = "", poibalance = "";
var total = parseFloat(document.getElementById("total-amount").value);
if(total>0){
$('#ao_amt_tbl tbody tr td[data-value]').each(function() {
var dataValue = this.getAttribute("data-value");
var dataId = this.getAttribute("data-id");
var $row = $(this).closest("tr");
var priceAmt = 0;
if(dataValue > 0){
if(total > dataValue ||
total == dataValue){
total = total - dataValue;
$row.find('.applied').val(dataValue);
$row.find('.balance').val('0.00');
oidata.push(dataId);
}
else{
priceAmt = dataValue - total;
$row.find('.applied').val(total.toFixed(2));
$row.find('.balance').val(priceAmt.toFixed(2));
if(total>0){
poibalance=priceAmt;
poidata=dataId;
oidata.push(dataId);
}
total=0;
}
}
});
if(total>0)
alert('$' + total.toFixed(2) + ' remaining.');
}
the HTML is-
<table id='ao_amt_tbl'>
<thead>
<tr>
<th>Amount</th><th>Amount Applied</th><th>Balance</th>
</tr>
</thead>
<tbody>
<tr>
<td data-id="19185" data-value="25">$25</td>
<td class="ao_td_jn"><input type="text" name="applied-amount" id="total1" placeholder="0.00" class="applied"></td>
<td><input type="text" name="balance-amount" id="balance1" placeholder="0.00" class="balance"></td>
</tr>
<tr>
<td data-id="19186" data-value="100">$100</td>
<td class="ao_td_jn"><input type="text" name="applied-amount" id="total2" placeholder="0.00" class="applied"></td>
<td><input type="text" name="balance-amount" id="balance2" placeholder="0.00" class="balance"></td>
</tr>
<tr>
<td data-id="19186" data-value="50">$50</td>
<td class="ao_td_jn"><input type="text" name="applied-amount" id="total2" placeholder="0.00" class="applied"></td>
<td><input type="text" name="balance-amount" id="balance2" placeholder="0.00" class="balance"></td>
</tr>
</tbody>
Now suppose I adjust the second row 'applied-amount' input value it should recalculate and distribute the 100 dollar among other rows. For example, change the second input value to 50, it should recalculate and distribute the values as 25, 50, 25. and recalculate the balance field as 0, 50, 25.
Using the above example; If the Input Amount is 100, the system should recalculate the rest of the Applied Amount input vales based on the balance amount from Input Amount(100)
Item Amount | Applied amount(input box)
25 25
100 50 <-- user input
50 25 <-- script needs to automatically recalculate and change the rest of the Applied amount input with balance amount (100 - 75 = 25).
Basically, the script needs to loop through the 'Applied amount' input boxes and split the Input Amount(100), from top to bottom until the Input amount is 0.
Hope I'm clear with my requirement. Any help will be greatly appreciated. thanks
use
$(document).ready(function () {
$('input').keydown(function () {
applyAmount();
});
});
you can also use
onkeydown=applyAmount();
inside the tag of whichever input tag you want.
thankyou all.. I got the solution. Did something like this;
$(function (){
$("input[id*='total-']").on('keyup', function() {
var ttl = //get Input Amount
var gid = $(this).parents('tr').find('.ao_td_jn').attr('data-id');
var Ajt = this.value;
ttl = ttl - Ajt;
if(ttl>0){
$('#ao_amt_tbl tr td[data-value]').each(function() {
var dv = this.getAttribute("data-value");
var dataId = this.getAttribute("data-id");
var $row = $(this).closest("tr");
if(gid == dataId){
var balAmt = dv - Ajt;
$row.find('.balance').val(balAmt.toFixed(2));
}
else{
...
}
...
}
}
});

How to get the value from the before selected radio?

In my case I have lines of radioboxes, every radio has a value. This value must be calculated and the result must be placed in a DIV.
My Problem is, I can't find a way to subtract the value of the choosen radion before.
let me show you a sample markup:
<table>
<tr>
<td><input name="tools" value="20" type="radio"></td>
<td><input name="tools" value="300" type="radio"></td>
<td><input name="tools" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" value="5" type="radio"></td>
<td><input name="addons" value="10" type="radio"></td>
</tr>
</table>
<div id="result"></div>
JavaScript :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var price = $(this).val(),
showPrice = $('#result').text(),
endresult = parseFloat(showPrice) + parseFloat(price),
$('#result').text(endResult);
});
With checkboxes it works fine, but in case of radioboyes I don't have a click-event to identify this on I must subtract.
in the first line we see the radios name=tools. here I take at first this one with value 20.
after that the value 20 will be shown in the#result, fine. But when I take now another radio name=tools the new value will add to the 20. and that is my problem. I don't know how to find the before selected radio button to get this value and subtract it.
Try using this:
html code:
<table>
<tr>
<td><input name="tools" class="test1" value="20" type="radio"></td>
<td><input name="tools" class="test1" value="300" type="radio"></td>
<td><input name="tools" class="test1" value="1000" type="radio"></td>
</tr>
<tr>
<td><input name="addons" class="test" value="5" type="radio"></td>
<td><input name="addons" class ="test" value="10" type="radio"></td>
</tr>
javascript:
<script>
var testPrice = 0;
var test1Price = 0;
var endprice = 0;
var price ='';
$('.test').click(function(){
price = $(this).val();
testPrice = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
$('.test1').click(function(){
var price = $(this).val();
test1Price = price;
endPrice = parseFloat(testPrice) + parseFloat(test1Price),
$('#result').text(endPrice);
});
</script>
try it's demo on http://jsfiddle.net/rxrzX/
You don't need to substract. You can just find 2 value of 2 diff radio button : tools and addons. Then just add them and write in the div
You can get radio button value by :
$('input[name=radioName]:checked').val();
I think try this :
var radioClick = $('input[type="radio"]');
radioClick.on('change', function(evt){
// function sub or add the price...
// here is a shortcut of the add calc version...
var toolsprice = $('input[name=tools]:checked').val(),
var addonsprice = $('input[name=addons]:checked').val(),
endresult = parseFloat(toolsPrice) + parseFloat(addonsprice),
$('#result').text(endResult);
});
You could use an object literal that tracks the value, using a closure:
radioClick.on('change', (function()
{
var valTracker = {},
resultDiv = $('#result');//easier on the DOM
return function(evt)
{
valTracker[this.name] = valTracker[this.name] || 0;//get old value
var endResult = parseFloat(resultDiv.text()) + parseFloat($(this).val()) - valTracker[this.name];//subtract old value, too
valTracker[this.name] = parseFloat($(this).val());//set current value
resultDiv.text(endResult);
}
}()));
The valTracker object literal tracks the current radio value (the name of the element is used as property). I've also kept a reference to the $('#result') div in the closure. That way, you don't have to query the DOM every time the callback function is called.
Try using the code below: JSFIDDLE
var radio_groups = []
$(":radio").each(function(){
if (radio_groups.indexOf(this.name) == -1){
radio_groups.push(this.name);
}
});
$('input:radio').change(function(evt){
var resultPrice = 0;
$.each(radio_groups, function(){
curPrice = $(':radio[name="' + this + '"]:checked').val();
if (!(curPrice)){
curPrice = 0;
}
resultPrice = parseInt(resultPrice) + parseInt(curPrice);
});
$('#result').text(resultPrice);
});
This will work, even if you add more radio button groups. If you want this functionality only for specific groups, define the names in the array radio_groups instead of getting them from the document.

Counting elements doesn't work

I have a table and want to calculate each element like:
calc-this-cost * calc-this-cost(value of checkbox) = calc-this-total
Then summ all calc-this-cost and put it to totalcost div.
This is table:
<td class="params2">
<table id="calc-params">
<tr>
<td>aaa</td><td class="calc-this-cost">159964</td><td class="calc-this-count">
<input type="checkbox" name="a002" value="0" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
<tr>
<td>bbb</td><td class="calc-this-cost">230073</td><td class="calc-this-count">
<input type="checkbox" name="a003" value="0" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
<tr>
<td>ccc</td><td class="calc-this-cost">159964</td><td class="calc-this-count">
<input type="checkbox" name="a004" value="1" onclick="calculate(this);" />
</td><td class="calc-this-total">0</td>
</tr>
........
</table>
.......
</td>
<div id="calc-total-price">TOTAL COST: <span>0</span></div>
My script (in function calculate)
var totalcost=0;
$('.params2 tr').each(function(){
var count=parseFloat($('input[type=checkbox]',$(this)).attr('value'));
var price=parseFloat($('.calc-this-cost',$(this)).text().replace(" ",""));
$('.calc-this-total',$(this)).html(count*price);
totalcost+=parseFloat($('.calc-this-cost',$(this)).text());
});
$('#calc-total-price span').html(totalcost);
Counting each element and put result to calc-this-cost - work perfect.
But totalcost result NaN. Why?
[general] don't parseFloat() more than you need to
[general] move repeating code to functions
[jQuery] use .find() over context and cache nodes ($row)
[general] look at how String.replace() works
[general] look at Number.toFixed() for displaying floats
example
var totalcost = 0,
toFloat = function(value) {
// remove all whitespace
// note that replace(" ", '') only replaces the first _space_ found!
value = (value + "").replace(/\s+/g, '');
value = parseFloat(value || "0", 10);
return !isNaN(value) ? value : 0;
};
$('.params2 tr').each( function() {
var $row = $(this),
count = toFloat($row.find('.calc-this-count input').val()),
price = toFloat($row.find('.calc-this-cost').text()),
total = count * price;
$row.find('calc-this-total').text(total.toFixed(2));
totalcost += total;
});
$('#calc-total-price span').text(totalcost.toFixed(2));
console.log() will solve all your problems:
$('.params2 tr').each(function(){
var count=parseFloat($('input[type=checkbox]',$(this)).attr('value'));
var price=parseFloat($('.calc-this-cost',$(this)).text().replace(" ",""));
$('.calc-this-total',$(this)).html(count*price);
totalcost+=parseFloat($('.calc-this-cost',$(this)).text());
console.log(count, price, totalcost)
});
Add more logging where every you don't understand something. Didn't I just tell you to use logging? :)

Categories

Resources