I have a function to add up my sum and charge respectively. But when i alert sum + charge, i get NaN. why is this happening?
<script>
sum = 0;
charge = 0;
$('.panel').append(
'<div class="container" style=" font-size:14px; "> '+
'<table style="width:100%;" class="table" id="tables">'+
'<td class="name" >'+std.name+'</td>'+
'<td><p class="total" ><span class="min-total" name="total" id="total"></span></p></td>'+
'</table>'+
'</div>'
$('.panel').on('keyup','.quantity',function()
container = $(this).closest('div');
quantity = Number($(this).val());
price = Number($(this).closest('div').find('.price').data('price'));
container.find(".min-total span").text(quantity * price);
sum = 0;
$(".sum-total").each(function(){
sum = sum + Number($(this).text());
})
}
$('.charge').on('keyup','.charge',function(){
$('.charge span').text( Number($(this).val()));
charge = Number($(this).val());
alert(sum + charge);
</script>
The wikipedia definition says:
In computing, NaN, standing for not a number, is a numeric data type
value representing an undefined or unrepresentable value. https://en.wikipedia.org/wiki/NaN
In your code either $(this).text() or $(this).val() cannot be computed by Number() and return NaN. Make sure the value of those is either a Number or a string made of numbers.
Related
I am trying to create some simple code that can calculate the value of product that has been checked by checkbox form. The values are all in decimal (0.00) form. Javascript section is showing whole only. Can anyone assist how this can be done?
Here is the code
<input type="checkbox" class="css-checkbox" name="iMac" id="<?php echo $rows2['id']; ?><?php echo $rows2['product_name']; ?>" value="<?php echo $rows2['product_price']; ?>"></input>
function computer() {
var userMesssage = document.getElementById("userMesssage");
var iMac = document.orderForm.iMac; // array of inputs
var totalOrder = ""; // list all checked ids
var totalCost = 0; // add values to calculate cost
for (var i = 0; i < iMac.length; i++){
if (iMac[i].checked) {
totalOrder += iMac[i].id + " ,<br />"; // add ids separated by spaces
totalCost += parseInt(iMac[i].value); // add value attributes, assuming they are integers
}
}
// show total order and cost
userMesssage.innerHTML = "<b>Your Budget</b>: <br />" + totalOrder + "<br />Total Budget: $" + totalCost;
userMesssage.style.color = "#fff";
}
You have to use .toFixed() function to convert into integer from decimal.
totalCost += (+(iMac[i].value).toFixed());
An additional + is added in front to convert string to number.
console.log(+(Math.random()*10).toFixed());
I am able to display the name, price and fetch the quantity previously entered into the database. On page load, i want the script to calculate the total by multiplying the price and quantity of each selected item and adding up the sub-totals of each item to get the grand total.
how can i achieve this?
<div class="panel_container"></div>
<script type="text/javascript">
$( document ).ready(function() {
#foreach ($items->products as $product)
var product = $('#{!! $product->id !!}');
var selectedItems = JSON.parse(product.attr('data-products'));
if(product.prop("checked") ) {
$('.panel_container').append(
'<div class="container">' +
'<p class="name">' + product.name + '</p>' +
'<p class="price" data-price="' + product.price + '">' + product.price + '</p>' +
'<p class="sub-total"><span class="sub-total" name="sub-total" id="sub-total"></span></p>'+
'<input type="text" class="form-control quantity" placeholder="qty" name="quantity[]" value="{!!$product->pivot->quantity!!}" required/>'+
'</div>'
)
} else {
//clear selected item
}
#endforeach
calculate();
});
var sub-total = 0;
var calculate = function() {
var ship_container = $('.panel_container').closest('div');
var quantity = Number($('.quantity').val());
var price = Number($('.panel_container').closest('div').find('.price').data('price'));
ship_container.find(".sub-total span").text(quantity * price);
}
</script>
Your code must be modified to run for each product.
var grandTotal = 0;
var calculate = function() {
// for each product
$('.panel_container .container').each(function() {
var product = $(this),
quantity = Number(product.find('.quantity').val()), // get quantity
price = Number(product.find('.price').data('price')), // get price
total = quantity * price; // calculate product total
product.find('.sub-total span').text(total); // show product total
grandTotal += total; // add to grand total
});
// use the grandTotal here..
alert('Grand total: ' + grandTotal);
}
Additionally, id attributes are required to be unique in the html so you should remove the id="sub-total" from the loop.
I'm simply trying to take inputs from html input fields.
The problem is, my function always evaluate the inputs to 0.
What should I do my code to work as I expected (to take inputs from fields and pass them to my javascript functions). If there is alike answered questions asked before, please refer.
Please do not propose jQuery solutions - I can't follow its full of parantheses syntax.
P.S. Zeros on ternary, are just for avoiding NaNs. Nothing else.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<strong>Data</strong>
<hr>Price:
<input type="text" id="price" value="0">
<br>Prepay:
<input type="text" id="prepay" value="0">
<br>Percent:
<input type="text" id="percent" value="0">
<br>Month:
<input type="text" id="month" value="0" onchange="refactorTable('payment-plan')">
<br>
<hr>
<strong>Table</strong>
<table id="payment-plan" border="1">
<thead>
<tr>
<td>Month</td>
<td>Amount</td>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript">
var Sum = parseInt(document.getElementById('price').value);
var PrePayment = parseInt(document.getElementById('prepay').value);
var Percent = parseInt(document.getElementById('percent').value);
var Month = parseInt(document.getElementById('month').value);
//console.log(Sum +" -- "+ PrePayment +" -- "+ Percent +" -- "+ Month);
function monthlyPaymentPlan(Sum, PrePayment, Percent, Month) {
var BigJohn = Sum - PrePayment;
//console.log(BigJohn);
var monthly = Math.ceil((BigJohn + BigJohn * Percent) / Month);
return Month > 0 ? monthly : 0;
}
function lastMonth(Sum, PrePayment, Percent, Month) {
return Month > 0 ? Sum - monthlyPaymentPlan(Sum, PrePayment, Percent, Month) * (Month - 1) : 0;
}
function refactorTable(tbl_id) {
var table = document.getElementById(tbl_id).getElementsByTagName('tbody')[0];
table.innerHTML = "";
var i = 0;
var rows = document.getElementById('month').value;
rows = parseInt(rows);
for (i = 0; i < rows - 1; i++) {
table.insertRow(-1).innerHTML = "<td>" + (i + 1) + "</td><td>" + monthlyPaymentPlan(Sum, PrePayment, Percent, Month) + "</td>";
}
table.insertRow(-1).innerHTML = "<td>" + rows + "</td><td>" + lastMonth(Sum, PrePayment, Percent, Month) + "</td>";
}
</script>
</body>
</html>
You are getting the values when the page renders, instead of when the function is supposed to run. Place your assignments inside a function and call the function.
// Define the variables globally so they can be used in any function
var Sum;
var PrePayment;
var Percent;
var Month;
// Call this function to set the values of the global variables.
function getValues() {
Sum = parseInt(document.getElementById('price').value);
PrePayment = parseInt(document.getElementById('prepay').value);
Percent = parseInt(document.getElementById('percent').value);
Month = parseInt(document.getElementById('month').value);
}
// Call the getValues function first to set the values and then continue on
// with your function calculations.
function refactorTable(tbl_id) {
getValues();
// Do the rest...
}
You need to get the values at the time the function is called. Right now you're getting the values on page load (which is 0).
function refactorTable(tbl_id) {
var Sum = parseInt(document.getElementById('price').value);
var PrePayment = parseInt(document.getElementById('prepay').value);
var Percent = parseInt(document.getElementById('percent').value);
var Month = parseInt(document.getElementById('month').value);
var table = document.getElementById(tbl_id).getElementsByTagName('tbody')[0];
table.innerHTML = "";
var i=0;
var rows = document.getElementById('month').value;
rows = parseInt(rows);
for(i=0; i<rows-1; i++) {
table.insertRow(-1).innerHTML = "<td>" + (i+1) + "</td><td>" + monthlyPaymentPlan(Sum, PrePayment, Percent, Month) + "</td>";
}
table.insertRow(-1).innerHTML = "<td>" + rows + "</td><td>" + lastMonth(Sum, PrePayment, Percent, Month) + "</td>";
}
You have need to update input variable value on change of id="month" so you can get updated value.
var Sum = '';
var PrePayment = '';
var Percent = '';
var Month = '';
function inputsval() {
Sum = parseInt(document.getElementById('price').value);
PrePayment = parseInt(document.getElementById('prepay').value);
Percent = parseInt(document.getElementById('percent').value);
Month = parseInt(document.getElementById('month').value);
}
function refactorTable(tbl_id) {
inputsval();
//Your other code.....
}
var Sum = parseInt(document.getElementById('price').value);
This is not defining a function, or a macro. This is a one-time calculation of a number, and it seems this is going to happen when the page starts up. So, it won't ever change from its first value (0).
You should probably move these declarations inside of refactorTable. Thankfully, you already have them set up to be passed as arguments.
This JavaScript function works independently for each line in the php foreach loop below just fine. However I Want to add those
two independent totals together to get a grand total and display it in the DIV tag below. I can't figure out how to set aside the
amounts and then add them together. The grand total should update with each change of quanity just like the amounts currently do.
Right now totalprice just reflects one amount but not a grand total.
<head>
<script type="text/javascript">
function update(iteration){
var qty = document.getElementById('qty_' + iteration).value;
// alert('quantity_' + iteration);
var price = document.getElementById('price_' + iteration).value;
price = price.substring(0, 7);
qty = parseInt(qty);
var amount = (qty * price).toFixed(2) ;
parseFloat(document.getElementById('amount_' + iteration).value = amount).toFixed(2);
//HERE's the code that's not working..
var subtotal;
for(var i =1; i < itemCount; i++) {
subtotal += document.getElementById('amount_' + i).value;
}
//this works
var divobj = document.getElementById('totalPrice');
divobj.style.display='block';
divobj.innerHTML = "Total $"+parseFloat(subtotal);
}
</script>
</head>
<?php
$listitems = unserialize($row["products"]);
$i=1;
foreach($listitems as $item)
{
echo '<tr><td>'.$item["code"].'</td><td><input type="number" id="qty_'.$i.'" name="qty_'.$i.'" min="1" size="3" value="1" onChange="iteration = '.$i.'; update(iteration); " /></td>';
echo '<td><input type="hidden" name="price_'.$i.'" id="price_'.$i.'" value="';
echo $item['price'];
echo '" />';
echo $item['price'];
echo '</td><td><input type="text" name="amount_'.$i.'" id="amount_'.$i.'" size="6" readonly value="';
echo $item['price'];
echo '"/></td></tr>';
$i++;
}
?>
<div id="totalPrice"></div>
Couple things stick out.
parseInt( ) needs a radix parameter.
parseInt(qty, 10);
Im confused on what this line is doing:
parseFloat(document.getElementById('amount_' + iteration).value = amount).toFixed(2);
parseFloat returns a floating point, but you arent setting it to anything?
The problem that is causing your error is the var subtotal declaration.
You are declaring a variable to equal amount + itself, which doesn't exist yet.
What do you want subtotal to equal?
Edit:
Now that you updated, you want to iterate the number of items and add them all together.
var subtotal;
for(var i =0; i < itemCount; i++) {
subtotal += document.getElementById('amount_' + i).value;
}
This would iterate over 0-itemCount of the amount elements.
I'm sure I'm contravening some deep dark law of javascript, but I'm not really a JS developer and this is driving me mad. This function is called on an orderform to read the quantity and price of items, row by row, and then provide the subtotal, delivery and total.
The problem is with line 10 - it keeps "forgetting" that the variable data throughout is numeric (floating point) and so returns lots of NaN. How can I force the variables throughout this function to behave as numbers rather than strings?
EDIT
Here's the revised code based on feedback so far (thank you!). It's still not working ;)
<script type="text/javascript">
function subTotal(rows) {
var i, subTotal, lineTotal, orderShip, orderTotal;
for (i = 1; i <= rows; ++i) {
//Grab values from form
var quantity = parseFloat($('#quantity' + i).val());
var uPrice = parseFloat($('#uPrice' + i).val());
//Error checking
alert('quantity = ' + quantity +' and uPrice = ' + uPrice);
if (isNaN(quantity)) alert('quantity = NaN');
if (isNaN(uPrice)) alert('uPrice = NaN');
if ((quantity == '') || (uPrice == '')) {
} else {
lineTotal = quantity * uPrice;
alert('lineTotal = ' + lineTotal);
subTotal += lineTotal;
alert('subTotal = ' + subTotal);
}
//If we've maxed out the number of rows, then subTotal should be calculated - push back to form.
if (i == rows) {
$('#orderSubTotal').val(subTotal );
orderShip = subTotal * 0.25;
$('#orderShip').val(orderShip.toFixed(2));
orderTotal = subTotal + orderShip;
$('#orderTotal').val(orderTotal.toFixed(2));
}
}
}
</script>
<form>
<table>
<tr>
<td><input type="text" id="item1" name="item1" value="Some description" readonly="readonly" /></td>
<td><input type="text" id="quantity1" name="quantity1" value="25" onchange="javascript:subTotal('2')" /></td>
<td><input type="text" id="uPrice1" name="uPrice1" value="1.50" readonly="readonly" /></td>
</tr>
<tr>
<td><input type="text" id="item2" name="item2" value="Some description" readonly="readonly" /></td>
<td><input type="text" id="quantity2" name="quantity2" value="25" onchange="javascript:subTotal('2')" /></td>
<td><input type="text" id="uPrice2" name="uPrice2" value="2.75" readonly="readonly" /></td>
</tr>
<tr>
<td colspan="3">
SubTotal
<input type="text" id="orderSubTotal" name="orderSubTotal" readonly="readonly" style="text-align: right" value="0.00" />
<br />Shipping
<input type="text" id="orderShip" name="orderShip" readonly="readonly" style="text-align: right" value="0.00" />
<br />Total
<input type="text" id="orderTotal" name="orderTotal" readonly="readonly" style="text-align: right" value="0.00" />
</td>
</tr>
</table>
</form>
I think the real problem is in your loop: You're looping from 0 to rows inclusive. So if you pass in 10 for rows, you'll be looping 11 times, starting with 0 and continuing through (including) 10. I suspect that's your real problem. If you don't have a quantity0 element, or (assuming rows is 10) you don't have a quantity10 element, then $("#quantity" + i).val() will return undefined, which converts to NaN when you convert it (implicitly or explicitly). (And the same for uPrice0 / uPrice10.) And of course, once you have NaN, any mathematical operation using it results in NaN.
In terms of your question about how to ensure they don't change, basically, convert them to numbers early. You're currently using quantity and uPrice without converting them, which means initially they're strings. Now, JavaScript is pretty smart about converting them for you, but sometimes you want to be explicit.
Separately: Where does x come from?
You haven't shown any data to work with, but just speculatively:
function subTotal(rows) {
var i, subTotal, lineTotal, quantity, uPrice, orderShip, orderTotal;
subTotal = 0;
for (i = 0; i < rows; ++i) {
// OR
//for (i = 1; i <= rows; ++i) {
quantity = $('#quantity' + i).val();
uPrice = $('#uPrice' + i).val();
if ((quantity == '') || (uPrice == '')) {
} else {
quantity = parseFloat(quantity);
uPrice = parseFloat(uPrice);
// Might consider checking isNaN(quantity) and isNan(uPrice) here
lineTotal = quantity * uPrice;
subTotal += lineTotal;
alert('subtotal = ' + subTotal);
}
if (i == x) { // Where does `x` come from?
$('#orderSubTotal').val(subTotal );
orderShip = subTotal * 0.25;
$('#orderShip').val(orderShip.toFixed(2));
orderTotal = subTotal + orderShip;
$('#orderTotal').val(orderTotal.toFixed(2));
}
}
}
The problem is that you're performing a mathematical calculation on the fields before using parseFloat:
var lineTotal = quantity * uPrice; // <-- result is most likely NaN here
subTotal = parseFloat(subTotal ) + parseFloat(lineTotal);
Perform your parsing at the point you get the values to make life a little easier:
var quantity = parseFloat($('#quantity' + i).val());
var uPrice = parseFloat($('#uPrice' + i).val());
Then change the subTotal = line to this:
subTotal += lineTotal;
Another possible issue is if the result of $('#uPrice' + i).val() doesn't start with a parseable float — if it starts with a currency symbol, e.g. £ or $, for instance — parseFloat will always return NaN for that field. You can work around it using $('#uPrice' + i).val().slice(1).
Do some error checking:
function subTotal(rows) {
var subTotal = 0;
while (var i=0; i < rows; i++) {
// convert as soon as you get the values
var quantity = parseFloat($('#quantity' + i).val());
var uPrice = parseFloat($('#uPrice' + i).val());
if (isNaN(quantity) || isNaN(uPrice)) { // error checking
alert("Invalid values on row " + i);
continue;
}
var lineTotal = quantity * uPrice;
subTotal += lineTotal;
alert('subtotal = ' + subTotal);
if (i == x) {
$('#orderSubTotal').val(subTotal );
var orderShip = subTotal * 0.25;
$('#orderShip').val(orderShip.toFixed(2));
var orderTotal = subTotal + orderShip;
$('#orderTotal').val(orderTotal.toFixed(2));
}
}
}
You're probably running into an index problem at some point, getting a NaN from one of the (non-existing fields), adding it to subTotal which makes it a NaN instantly.
You better convert the value before doing any mathematical operation. So the code should be:
var numQuanitity = parseFloat(quantity);
var numPrice = parseFloat(uPrice);
if (isNaN(numQuanitity) || isNaN(numPrice)) {
//you can alert or ignore
}
else {
var lineTotal = numQuanitity * numPrice;
subTotal += lineTotal;
alert('subtotal = ' + subTotal);
}
...