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());
Related
I'm trying to add all the values from the class "q-total" But I can't get it to work. Here's the code:
$(document).on("change", ".row-inputs", function(){
var total = 0;
var price = 0;
var multi = 0;
$('.q-quantity', this).each(function(){
multi = $(this).val();
})
$(".q-price", this).each(function(){
price += +$(this).val() * multi;
})
$(".q-total", this).val(price);
for (var i = 0; i < $(".q-total").length; i++) {
// total = 0;
// console.log($(".q-total", this).val() )
total += parseInt($(".q-total", this).val());
}
console.log("Total " + total)
})
Below is the class code I use to add new rows to the html. In case this might help to figure out why the above code is not working.
var counter = 1;
var limit = 10;
function addInput(divName){
if (counter == limit) {
alert("You have reached the limit of adding " + counter + "
inputs");
}
else {
var newdiv = document.createElement('div');
newdiv.className = "row-inputs";
newdiv.innerHTML = "<input type='text' name=''
placeholder='product name' class='q-product-name'> " +
"<input type='number' name='' placeholder='0' class='q-quantity'
value=1> " +
"<input type='text' name='' placeholder='price' class='q-price'> "
+
"<input type='text' name='' placeholder='price' class='q-total'>";
document.getElementById(divName).appendChild(newdiv);
counter++;
}
}
Thank you
Your loop is incorrect:
Change
for (var i = 0; i < $(".q-total").length; i++) {
// total = 0;
// console.log($(".q-total", this).val() )
total += parseInt($(".q-total", this).val());
}
To
$(".q-total").each(function(){
total += +$(this).val();
})
In the original for loop you never iterate over the values, you always take $(this).val(). Not sure why you varied from your .each() approach you've used everywhere else, but that is your fix.
To explain further, using your example of add rows with prices of 3,4,5. The first time through (1st row), you have one element in the jQuery collection, so total=0 becomes total += 3; Second row added and you have two elements, but only look at the value of the current row, so total=0 becomes total += 4 && total += 4 hence total=8; On third row change, there are three elements, to total = 15 ( 3 * 5);
I am trying to calculate the sum of 4 different values, they are all calculated using their data tags in the dom, however I have no idea how to fetch the total value of the four of them combined, here's my function.
function calculateUserPricing(initialValues: boolean) {
var displayElements = ["jsSuperUser", "jsUser", "jsResourceUser", "jsRessource"];
for (var i in displayElements) {
var element = $("div." + displayElements[i]);
var quantity = parseFloat(element.data("price"));
var users;
var total;
if (initialValues)
users = parseInt(element.data("users"));
else
element.find(".jsDisplayPrice").text(currencySymbol + " " + $.formatNumber(quantity * users, lineCurrencyFormat));
}
for (var i in displayElements) {
total += $(displayElements[i]);
element.find(".jsDisplayTotal").text(currencySymbol + " " + $.formatNumber(total, lineCurrencyFormat));
}
}
The last bit is my attempt at fetching the value, however to no avail..
Here's the html, each element that shows its own total value looks like this, there's 4 of these boxes, and i need their grandsum It's the one classed as "jsDisplayTotal" that displays the individual boxes local total, they all look like this:
<div class="container jsRessource" int:title="Ressource" data-price="{../#resource-sys}"
data-users="{#resources}">
<div class="box boxSmTxt">
<xsl:text><int:text>Ressource</int:text></xsl:text>
</div>
<div class="boxLgTxt">
<xsl:value-of select="#resources" />
</div>
<span class="prMnd">
<xsl:value-of select="../#resource"></xsl:value-of>
<xsl:text> <int:text>/ måned</int:text></xsl:text>
</span>
<div class="priceBox">
<span class="price">
<span class="prMnd">
<span class="jsDisplayPrice" id="resourcePrice">
</span>
<xsl:text> <int:text>i alt</int:text></xsl:text>
<br/>
<xsl:text><int:text>Totalsum:</int:text> </xsl:text>
<span class="jsDisplayTotal"></span>
</span>
</span>
</div>
</div>
EDIT: it's worth noting that the four values (prices) are stored in each their ".jsDisplayPrice" div which displays the total of that specific price category, however all these four prices must be added together to an grand total.
EDIT2: Tried something, but it doesn't work, just prints out 0, any feedback would be appreciated, code example below:
var totalElement = $('.jsDisplayTotal');
function calculateTotal() {
var total = 0;
$('.jsDisplayPrice').each(function() {
total += parseInt($(this).val());
});
totalElement.text(currencySymbol + " " + $.formatNumber(total, lineCurrencyFormat));
}
calculateTotal();
Structural sample of how it works:
This is 1 of the 4 user categories of which I am trying to combine the total of for a grandsum
The first big number is the quantity of users, the number "19" just below is a static number, what each user of this category will cost, the next line is the current total price of this specific category with the price * quantity, and this is the jsDisplayPrice .div the last line should be the totalsum of this particular category, and 3 more combined, the grandsum of all 4 user categories.
Thanks for reading.
Try:
var total = 0;
for (var i in displayElements) {
var element = $("div." + displayElements[i]);
var quantity = parseFloat(element.data("price"));
var users;
total += quantity;
}
element.find(".jsDisplayTotal").text(currencySymbol + " " + $.formatNumber(total, lineCurrencyFormat));
I managed to solve the problem I had by changing the existiting calculateUserPricing() function
like so:
function calculateUserPricing(initialValues: boolean) {
var displayElements = ["jsSuperUser", "jsUser", "jsResourceUser", "jsRessource"];
var total = 0;
for (var i in displayElements) {
var element = $("div." + displayElements[i]);
var quantity = parseFloat(element.data("price"));
var users;
if (initialValues)
users = parseInt(element.data("users"));
else
users = $(".entries tr.jsSuperUsers").length;
var subtotal = quantity * users;
total = total + subtotal;
element.find(".jsDisplayPrice").text(currencySymbol + " " + $.formatNumber(subtotal, lineCurrencyFormat));
}
element.find(".jsDisplayTotal").text(currencySymbol + " " + $.formatNumber(total, lineCurrencyFormat));
}
It was easier and simpler to incorporate it in the existing function, since the value of the calculateUserPricing function was already formatted it didn't recognize it as a valid number
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 have build a simple likert scale application which lets users to add as many likert question as they want (the code is below, you can try it).
So, the user create questions (likert) on the first page (index.html) after then, by submitting, they have a survey-like page (execute.php) that is presenting their likert scale questions.
PROBLEM: The thing is that everything works, except naming the input radio button in order to catch it by some php script later. It is named, but not every row has the same name so the likert scale doesn't work right. It should work like this: Every row of radio buttons of each question should have one name.
FOR EXAMPLE: For the first question: the radio buttons in the first row should have names likert11, likert11, likert11... The second row should be likert12, likert12, likert12...
And for the question 2: It should be likert21, likert21...
INDEX.HTML
<input type="submit" value="LIKERT" onclick="addlik();" />
<form action="execute.php" method="post">
<div id="brain1"></div><br/>
<input type="submit" name="submit" value="OK"><br/>
</form>
SCRIPT.JS
n=1;
function addlik() {
var textarea = document.createElement("textarea");
textarea.name = "question[" + n + "]";
textarea.rows = 2;
textarea.cols = 60;
var lik = document.createElement("textarea");
lik.name = "lik[" + n + "]";
lik.rows = 6;
lik.cols = 30;
var liko = document.createElement("textarea");
liko.name = "liko[" + n + "]";
liko.rows = 6;
liko.cols = 30;
var div = document.createElement("div");
div.innerHTML = n + ". Question: <br />" + textarea.outerHTML + "<br />The left textbox is for Items (vertical). The rigth one is for Options (header horizontal): <br/>" + lik.outerHTML + liko.outerHTML + "<br /><hr/><br/>";
document.getElementById("brain1").appendChild(div);
n++;
}
EXECUTE.PHP
<?php
$bla = "";
$question = $_POST['question'];
$length = count($_POST['question']);
$likoprint = array("","","","","","","","","","","","","","","","","","","","","");
$tablerow = array("","","","","","","","","","","","","","","","","","","","","");
$radiooptions = array("","","","","","","","","","","","","","","","","","","","","");
for($j=1; $j<=$length; $j++) {
if($_POST['question'][$j] != "") {
$lik = $_POST['lik'];
$likarr[$j] = explode("\n", str_replace("\r\n", "\n", $lik[$j]));
$liko = $_POST['liko'];
$likoarr[$j] = explode("\n", str_replace("\r\n", "\n", $liko[$j]));
$ln = 1;
for($lo=0;$lo<sizeof($likoarr[$j]);$lo++) {
$val = $lo + 1;
$likoprint[$j] .= '<td>'.$likoarr[$j][$lo].'</td>';
$radiooptions[$j] .= '<td><input type="radio" name="likert'.$j.$lo.'" value="'.$val.'"></td>';
}
for($l=0;$l<sizeof($likarr[$j]);$l++) {
$tablehead = '<td>Items\Options</td>'.$likoprint[$j];
$tablerow[$j] .= '<tr><td>'.$likarr[$j][$l].'</td>'.$radiooptions[$j].'</tr>';
$table = '<table style="width:900px;"><tr>'.$tablehead.'</tr>'.$tablerow[$j].'</table>';
}
$bla .= $j.') '.$question[$j].'<br/>'.$table.'<br/><br/>';
}}
echo $bla;
?>
You are getting the radio value but this is not the best way possible. What you can do is use one input name for every answer(option) to the question, and in the input value use the value of the option. That way you get the option checked easily. Something like this:
for($lo=0;$lo<sizeof($likoarr[$j]);$lo++) {
$val = $lo + 1;
$likoprint[$j] .= '<td>'.$likoarr[$j][$lo].'</td>';
$radiooptions[$j] .= '<td><input type="radio" name="likert'.$j.'" value="'.$val.'"></td>';
}
For accessing more than one option use checkbox, since it can easily be implemented, checked and unchecked:
for($lo=0;$lo<sizeof($likoarr[$j]);$lo++) {
$val = $lo + 1;
$likoprint[$j] .= '<td>'.$likoarr[$j][$lo].'</td>';
$radiooptions[$j] .= '<td><input type="checkbox" name="likert['.$j.'][]" value="'.$val.'"></td>';
}
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);
}
...