Creating a Subtotal calculator in JavaScript (in a model) - javascript

I am trying to create a subtotal calculator using JavaScript that would automatically multiply the price (in £) of a certain product by the quantity selected by the user.
I have been at this for a few days now. I am working with a constructor and am trying to modify its code. I have tried several approaches using JavaScript and so far none of them worked.
Here is the HTML code I have added to the product page:
<div class="data">
<input class="form-input form-input--incrementTotal"
id="qty[]"
name="qty[]"
type="number"
value="{{#if product.min_purchase_quantity}} {{product.min_purchase_quantity}}{{else}}1{{/if}}"
data-quantity-min="{{product.min_purchase_quantity}}"
data-quantity-max="{{product.max_purchase_quantity}}"
min="1"
pattern="[0-9]*"
aria-live="polite">
<span id="price" data-product-price-without-tax class="price price--withoutTax{{#if price.with_tax}} price-section--minor{{/if}}">{{price.without_tax.formatted}}</span>
<span id="price1" class=price1></span>
<div id="total" class="total"></div>
<div id="total1" class="total1"></div>
</div
Approach 1:
<script>
var priceRange = document.getElementById("qty[]").value;
var priceAmount = $('#price').html();
var removeEuro = priceAmount.replace("£", "");
var total = parseFloat(removeEuro) * parseFloat(priceRange);
$('#total').text('£' + total);
</script>
Approach 2:
<script>
var price1 = parseFloat($("#price").text().split('£')[1]);
$("#price1").text(price1);
var r, i;
r = document.getElementsByClassName("data");
for(i=0;i<r.length; i++){
r[i].getElementsByClassName("total")[0].innerHTML =
r[i].getElementsByClassName("price1")[0].innerText *
r[i].getElementsByClassName("form-input--incrementTotal") [0].value;
}
function total(element) {
var tr = element.parentNode.parentNode;
var price = tr.getElementsByClassName("form-input--incrementTotal") [0].innerText;
tr.getElementsByClassName("total")[0].innerHTML = price * element.value;
}
function sumTotal(){
var tot = 0 ;
var len = document.getElementsByClassName("total").length;
for(var i =0; i<len; i++){
tot += parseInt(document.getElementsByClassName("total") [i].innerText);
}
}
$('#total1').html('£' + parseFloat($('#total').text()))
</script>
Neither of the approaches worked. I keep getting an NaN error. I do not understand why it's telling me the result is not a number. Perhaps {{price.without_tax.formatted}} could be what's causing the issue? Can someone please help me with my code?

Related

I stuck with this code, trying to figure out, how it should work

I'm working on a poject, need it must be auto calculation.
let say that we have uncounted hidden inputs with known same class and attr. diffrent value, attr diffrent price, price2 price 3 in a div to count
What im trying to do is to get attrs (price, priceX2, priceX3)
if the user inserted a number ex. 1 or 40, will return first input(price, priceX2, priceX3), and if its given 61 0r 70 then it will return to the third input(price, priceX2, priceX3) so on
<div id="countDiv">
<input type="number" value="" id="counter" />
<button id="countBtn"> Count </button>
<input type="hidden" value="40" price="1100" priceX2="1200" priceX3="1220" class="classeid">
<input type="hidden" value="60" price="1150" priceX2="1250" priceX3="1300" class="classeid">
<input type="hidden" value="70" price="1220" priceX2="1350" priceX3="1400" class="classeid">
</div>
<script>
$(document).ready(function(){
$("#countBtn").click(function(){
var parentDOM = document.getElementById("countDiv");
var classCounter = parentDOM.getElementsByClassName("classeid");
var counter = $("#counter").val();
for (var i = 0, n = classCounter.length; i < n; ++i) {
var mPrice = parseInt(classCounter[i].value);
var cPrice = parseInt(classCounter[i].getAttribute('price'));
var cPriceX2 = parseInt(classCounter[i].getAttribute('priceX2'));
var cPriceX3 = parseInt(classCounter[i].getAttribute('priceX3'));
}
});
});
</script>
Hope this code help you.
Do do it dynamically it's not better to do using the Hidden field if you have more than 3 input hidden field. The logic will be different in that case.
Considering only 3 hidden input fields then code looks as below:
HTML Code:
provide id to the each hidden input fields as first, second and third as written in the code.
JavaScript Code:
$("#countBtn").click(function(){
var counter = $("#counter").val();
if(counter > 0 && counter <= 40) {
var mprice = $("#first").val();
var cprice = $("#first").attr("price");
var cPriceX2 = $("#first").val("priceX2");
var cPriceX3 = $("#first").attr("priceX3");
}
else if(counter > 39 && counter <= 60) {
var mprice = $("#second").val();
var cprice = $("#second").attr("price");
var cPriceX2 = $("#second").val("priceX2");
var cPriceX3 = $("#second").attr("priceX3");
}
else {
var mprice = $("#third").val();
var cprice = $("#third").attr("price");
var cPriceX2 = $("#third").val("priceX2");
var cPriceX3 = $("#third").attr("priceX3");
}
}

Adding value of selected radio button to an equation

I am at my wits end. I cannot figure out how to add the value of the radio button to the equation. Can someone give me a clue at least on this??
If I don't have the radio button function included, this works fine.
<input type="radio" class="InternetCost" name="int" id="no_int" value="0">None<br>
<input type="radio" class="InternetCost" name="int" id="ten" value="10">10<br>
<input type="radio" class="InternetCost" name="int" id="twenty" value="20">20<br>
<input type="radio" class="InternetCost" name="int" id="thirty" value="30">30<br>
//Try to select radio button
var values = document.getElementsByName("int");
function getValue() {
for(var i = 0; i < values.length; i++) {
if(values[i].checked == true) {
selectedValue = values[i].value;
console.log('value=' + selectedValue);
}
}
}
function calculate()
{
//get selectedValue - this is where I am lost!
var radioValue = getValue()*1;
//Package
var pkgCost = document.getElementById("pkg").value*1;
//Package - Static
var equipPkg = document.getElementById("pep").value*1;
//Additional amount
var addBox = document.getElementById("addtl").value*1;
//Additional Box cost - static
var totalNum = document.getElementById("add_cost").value*1;
//Service amount
var dvrSvc = document.getElementById("dvr_svc").value*1;
//Service cost - static
var dvrCost = document.getElementById("dvr_cost").value*1;
// Sum everything
var SumAll = pkgCost + equipPkg + (addBox*totalNum) + (Svc*Cost) + radioValue;
// print the total
document.getElementById("Sum").innerHTML = SumAll.toFixed(2)
}
Your solution should work fine except you're using
console.log('value=' + selectedValue);
instead of actually returning the value.
return selectedValue;
Example

Unchecking a checkbox and modifying value of sum

I am trying to design a menu. If you check a box, then sum get added up and if you uncheck it, the sum is reduced. I face trouble in reducing the sum while unchecking the box and also the value of sum is not globally changed. Please help me out.
<head>
<script>
var sum=0;
function a(sum,num) {
sum=sum+num;
document.getElementById("demo").innerHTML=sum;
}
</script>
</head>
<body>
<input type="checkbox" name="Dal" id="dal" onclick=a(sum,10)>Dal<br>
<input type="checkbox" name="Rice" id="rice" onclick=a(sum,20)>Rice<br>
<h1> Total Price is : </h1>
<p id="demo"> 0 </p>
</body>
Change the markup, add a value and a class, and remove the inline JS
<input type="checkbox" name="Dal" id="dal" value="10" class="myClass">Dal
<input type="checkbox" name="Rice" id="rice" value="20" class="myClass">Rice
<h1> Total Price is : </h1><p id="demo">0</p>
Then do
<script type="text/javascript">
var inputs = document.getElementsByClassName('myClass'),
total = document.getElementById('demo');
for (var i=0; i < inputs.length; i++) {
inputs[i].onchange = function() {
var add = this.value * (this.checked ? 1 : -1);
total.innerHTML = parseFloat(total.innerHTML) + add
}
}
</script>
FIDDLE
You can do something like this:
function a (elem, num) {
var k = (elem.checked) ? 1 : -1;
sum = sum + k * num;
document.getElementById("demo").innerHTML = sum;
}
And in the HTML:
<input type="checkbox" name="Dal" id="dal" onclick="a(this, 10);">Dal<br>
<input type="checkbox" name="Rice" id="rice" onclick="a(this, 20);">Rice<br>
Try something like this:
var sum = 0;
function a(id, num) {
if(id.checked == true){
sum += num;
id.onclick = function() { a(id, num)};
}
else {
sum -= num;
id.onclick = function() { a(id, num)};
}
document.getElementById("demo").innerHTML=sum;
}
Fiddle: http://jsfiddle.net/95pvc/2/
My own take would involve removing the event-handling from the HTML (unobtrusive JavaScript) for easier maintenance in future, using data-* attributes to contain the price and using a class-name to identify the relevant ingredients, to give the following HTML:
<input class="ingredients" type="checkbox" name="Dal" data-price="10" id="dal" />Dal
<input class="ingredients" type="checkbox" name="Rice" data-price="20" id="rice" />Rice
<h1> Total Price is : </h1>
<p id="demo">0</p>
Which leads to the following JavaScript:
var ingredients = document.getElementsByClassName('ingredients');
function price() {
var result = document.getElementById('demo'),
curPrice = 0,
ingredients = document.getElementsByClassName('ingredients');
for (var i = 0, len = ingredients.length; i < len; i++) {
if (ingredients[i].checked) {
curPrice += parseFloat(ingredients[i].getAttribute('data-price'));
}
}
result.firstChild.nodeValue = curPrice;
}
for (var i = 0, len = ingredients.length; i < len; i++) {
ingredients[i].addEventListener('change', price);
}
JS Fiddle demo.
To avoid having to iterate through the relevant checkboxes, it might be better to wrap those input elements in a form, and then bind the event-handling to that form:
var ingredients = document.getElementsByClassName('ingredients');
function price() {
var result = document.getElementById('demo'),
curPrice = 0,
ingredients = document.getElementsByClassName('ingredients');
for (var i = 0, len = ingredients.length; i < len; i++) {
if (ingredients[i].checked) {
curPrice += parseFloat(ingredients[i].getAttribute('data-price'));
}
}
result.firstChild.nodeValue = curPrice;
}
document.getElementById('formID').addEventListener('change', price);
JS Fiddle demo.
References:
addEventListener().
element.getAttribute().
getElementsByClassName().
parseFloat().

Calculating totals when clicking checkboxes

I have a list of radio buttons represented by this code:
<form id="menu4strombolis">
input1 <input type="radio" name="menu1"><br />
input2 <input type="radio" name="menu2"><br />
input3 <input type="radio" name="menu3"><br />
input4 <input type="radio" name="menu4"><br />
input5 <input type="radio" name="menu5"><br />
input6 <input type="radio" name="menu6"><br />
input7 <input type="radio" name="menu7"><br />
</form>
Whenever a button is selected I need the subtotal and total to be updated.
This is how i want it to look.
Subtotal: <br />
Tax:<br />
Total:<br />
Where tax is always %7 or .7
The prices of menu 1 through 7 increments by $5. Menu1 is $5, menu2 is $10 and so forth.
I was trying to figure out the JavaScript to this but the problem is that i don't want it to display right after the buttons I want it displayed on the bottom of the page.
If I do document.write the whole page gets overwritten. Please help me on this issue guys. I am sure it's really simple.
Preamble
This sounds like homework to me. However, I find that the best way to learn, is by example.
So here's me, leading by example, OK?
You didn't give me much to go on, so for the sake of this example, I'm assuming you've got a list of checkboxes or radiobuttons that say Menu 1... Menu n. Each checkbox that is checked will be added to the subtotal, and then the tax calculated on top of that.
Doing it with radio buttons is a little easier, so I added that example as well.
On the bottom of the post are references for future study on what is used in this example.
If you have any further questions please ask them in the comment area at the bottom of this post.
The Javascript (checkboxes) | JSFiddle example (see it in action)
//Set the tax and base cost
var f_tax = 0.07,
i_menu_base = 5;
//Declare all the variables that will be used
var e_menu = document.getElementById("menu"),
e_checkboxes = e_menu.getElementsByTagName("input"),
e_subtotal = document.getElementById("sub_total");
// Add event listeners for when any checkbox changes value
for(var i = 0; i < e_checkboxes.length; i++){
e_checkboxes[i].onchange = function(){
//Recalculate subtotal
get_subtotal();
}
}
//get_subtotal calculates the subtotal based on which checkboxes are checked
function get_subtotal(){
var f_sub_total = 0.0,
f_grand_total = 0.0;
var subtotal, tax, grandtotal;
for(var i = 1; i <= e_checkboxes.length; i++){
//If the checkbox is checked, add it to the total
if(e_checkboxes[i-1].checked){
f_sub_total += i * i_menu_base;
}
}
//Calculate the grand total
f_grand_total = f_sub_total*(1+f_tax);
//Format them
subtotal = (Math.round(f_sub_total*100)/100).toFixed(2);
tax = (Math.round(f_tax*10000)/100).toFixed(2);
grandtotal = (Math.round(f_grand_total*100)/100).toFixed(2);
//Add them to the display element
e_subtotal.innerHTML = "Subtotal: "+subtotal+"<br />";
e_subtotal.innerHTML += "Tax: "+tax+"%<br />";
e_subtotal.innerHTML += "Total: "+grandtotal;
}
The Javascript (radio buttons) | JSFiddle example (see it in action)
//Set the tax
var f_tax = 0.07,
i_menu_base = 5;
//Declare all the variables that will be used
var e_menu = document.getElementById("menu"),
e_radios = e_menu.getElementsByTagName("input"),
e_subtotal = document.getElementById("sub_total");
// Add event listeners for when any checkbox changes value
for(var i = 0; i < e_radios.length; i++){
e_radios[i].onchange = function(){
//Recalculate subtotal
get_subtotal(this);
}
}
//get_index gets the index of the element (1..n)
function get_index(element){
for(var i = 1; i <= e_radios.length; i++){
if(e_radios[i-1] == element){
return i;
}
}
}
//get_subtotal calculates the subtotal based on the radio that was changed
function get_subtotal(el){
var f_sub_total = 0.0,
f_grand_total = 0.0;
var subtotal, tax, grandtotal;
f_sub_total += get_index(el) * i_menu_base
//Calculate the grand total
f_grand_total = f_sub_total*(1+f_tax);
//Format them
subtotal = (Math.round(f_sub_total*100)/100).toFixed(2);
tax = (Math.round(f_tax*10000)/100).toFixed(2);
grandtotal = (Math.round(f_grand_total*100)/100).toFixed(2);
//Add them to the element
e_subtotal.innerHTML = "Subtotal: "+subtotal+"<br />";
e_subtotal.innerHTML += "Tax: "+tax+"%<br />";
e_subtotal.innerHTML += "Total: "+grandtotal;
}
References for future study
In order in which they appear
getElementById()
getElementsByTagName()
looping through an array
onchange
Math.round(), decimal trick and toFixed()
innerHTML
Despite any additonal input from you, and my better judgement, I was bored so I did it all.
HTML:
<form id="menu4strombolis">input1
<input type="radio" name="menu1" value="5">
<br>input2
<input type="radio" name="menu2" value="10">
<br>input3
<input type="radio" name="menu3" value="15">
<br>input4
<input type="radio" name="menu4" value="20">
<br>input5
<input type="radio" name="menu5" value="25">
<br>input6
<input type="radio" name="menu6" value="30">
<br>input7
<input type="radio" name="menu7" value="35">
<br>
</form>
<button id="getTotal">Total</button>
<div id="subtotal">Sub-Total:</div>
<div id="tax">Tax:</div>
<div id="total">Total:</div>
JS:
var button = document.getElementById("getTotal");
button.onclick = function () {
var subtotalField = document.getElementById("subtotal");
var radios = document.forms["menu4strombolis"].getElementsByTagName("input");
var subtotal = 0;
var tax = 0;
var total = 0;
for (var i = 0, length = radios.length; i < length; i++) {
if (radios[i].checked) {
subtotal += parseInt(radios[i].value);
}
}
tax = (subtotal * .07).toFixed(2); ;
total = subtotal + tax;
document.getElementById("subtotal").innerHTML = "Sub-Total: $" + subtotal;
document.getElementById("tax").innerHTML = "Tax: $" + tax;
document.getElementById("total").innerHTML = "Total: $" + total;
};
and the working fiddle:
http://jsfiddle.net/RGvTt/1/
Though on a side note, you should either group some of the radios together in the same group... or make them checkboxs.
Updated to fix the bug that the OP couldn't fix:
http://jsfiddle.net/RGvTt/4/
Need to use parseFloat.
iPhone fiddle programming FTW!
What you want is element.innerHTML
So it would look something like this:
<form id="menu4strombolis">
input1 <input type="radio" name="menu1"><br />
input2 <input type="radio" name="menu2"><br />
input3 <input type="radio" name="menu3"><br />
input4 <input type="radio" name="menu4"><br />
input5 <input type="radio" name="menu5"><br />
input6 <input type="radio" name="menu6"><br />
input7 <input type="radio" name="menu7"><br />
</form>
..... ..html stuff here
Subtotal: <span id="subtotal"></span><br/>
Tax: <span id="tax"></span><br/>
Total: <span id="total"></span><br/>
ETC...
<script>
var subtotal = //whatever menu item is checked then .value();
var span_subtotal = document.getElementById("subtotal);
var tax = document.getElementById("tax");
var total = document.getElementById("total");
var the_tax = subtotal * .07;
span_subtotal.innerHTML = subtotal;
tax.innerHTML = the_tax;
total.innerHTML = subtotal + the_tax;
<script>

Shortening JavaScript Function

I must admit, I don't know much about JavaScript that is why my question might sound little bit silly.
But what I'm trying to do is grab values from selected by name radio groups.
It looks like this
function calc() {
var op1 = document.getElementsByName('form[radio1]');
var op2 = document.getElementsByName('form[radio2]');
var op3 = document.getElementsByName('form[radio3]');
var result = document.getElementById('result');
result.value = 0;
result.value = parseInt(result.value);
for (i = 0; i < op1.length; i++) {
if (op1[i].checked) result.value = parseInt(result.value) + parseInt(op1[i].value);
}
for (i = 0; i < op2.length; i++) {
if (op2.options[i].selected) result.value = parseInt(result.value) + parseInt(op2[i].value);
}
for (i = 0; i < op3.length; i++) {
if (op3.options[i].selected) result.value = parseInt(result.value) + parseInt(op3[i].value);
}
return false;
}
And this is my form. Im using rs form for joomla.
<form action="index.php" enctype="multipart/form-data" id="userForm" method="post">
<input name="form[radio1]" value="25" id="radio20" type="radio">
<label for="radio20">Description1</label>
<input name="form[radio1]" value="35" id="radio21" type="radio">
<label for="radio21">Description2</label>
<input name="form[radio2]" value="20" id="radio20" type="radio">
<label for="radio20">Description1</label>
<input name="form[radio2]" value="30" id="radio21" type="radio">
<label for="radio21">Description2</label>
<input type="hidden" value="0" id="result" name="form[result]">
<input type="submit" class="rsform-submit-button" onclick="calc()" id="submit" name="form[submit]" value="submit">
And everything would be OK, as the function is working. the only trouble is that I have about 80 radiograms.
Is there a way to shorten it?
Use arrays of objects (like all the radio buttons, for instance) and iterate over them. Start like this:
var opts = [],
numOpts = 80;
for (var i=0; i<numOpts, i++)
{
opts.push(document.getElementsByName('form[radio' + i + ']'));
}
Edit: let's have a go at the full function. The only thing I'm not 100% sure about is whether you mean to use opX[i].checked or opX.options[i].selected (since your code does different things for op1 and op2/3). Shouldn't be too hard to extrapolate if I've guessed wrong, though.
function calc()
{
var opts = [],
numOpts = 80,
value = 0,
result = document.getElementById('result'),
i, j, opt;
for (i=0; i<numOpts; i++)
{
opts.push(document.getElementsByName('form[radio' + i + ']'));
}
numOpts = opts.length;
for (i=0; i<numOpts; i++)
{
opt = opts[i];
for (j=0; j<opt.length; j++)
{
// or did you mean:
// if (opt.options[j].selected) ?
if (opt[j].checked)
{
value = value + parseInt(opt[j].value, 10);
}
}
}
result.value = value;
return false;
}
jQuery is a great library that's like using JavaScript on steroids. It is well worth learning and there are plenty of examples out in the wild.
You can write complex "selectors" quite like this:
$('input[name=form[radio1]]').attr('checked').each(function() {
result.value = $(this).attr('value')
})
(I'm not sure if it will accept a name like "form[radio1]" as valid, but give it a try.

Categories

Resources