I am trying to create a simple jQuery calculator but it doesn't seem to be working as I hope it to be. Basically it should calculate automatically at 0 the price from the input boxes and then multiply when the +/- are clicked.
It doesn't seem to do anything or show any errors.
jQuery(document).ready(function(){
var qty = parseInt($('.qty').val());
var price = parseFloat($('#price').val());
$("#price").each(function(){
total += parseFloat(this.value);
});
http://jsfiddle.net/hktxyz5z/1/
I am not sure if I am over thinking, anyone got any ideas?
You need to give the variable declarations inside the click event:
var qty = parseInt($('.qty').val());
var price = parseFloat($('#price').val());
The reason is, you are statically setting the values to 0.00 at the first load. Every time you increment or decrement, the values do not change. It is set once and not set when it is changed. They don't dynamically change, after the click events are fired.
The solution is to put the above two lines inside the .click() functions.
jQuery(document).ready(function(){
$("#price").each(function(){
total += parseFloat(this.value);
});
// This button will increment the value
$('.qtyplus').click(function(e){
// Stop acting like a button
e.preventDefault();
// Get the field name
fieldName = $(this).attr('field');
// Get its current value
var currentVal = parseInt($('input[name='+fieldName+']').val());
// If is not undefined
if (!isNaN(currentVal)) {
// Increment
$('input[name='+fieldName+']').val(currentVal + 1);
qty = parseInt($('.qty').val());
price = parseFloat($('#price').val());
$('#total').val((qty * price ? qty * price : 0).toFixed(2));
} else {
// Otherwise put a 0 there
$('input[name='+fieldName+']').val(0);
qty = parseInt($('.qty').val());
price = parseFloat($('#price').val());
$('#total').val((qty * price ? qty * price : 0).toFixed(2));
}
});
// This button will decrement the value till 0
$(".qtyminus").click(function(e) {
// Stop acting like a button
e.preventDefault();
// Get the field name
fieldName = $(this).attr('field');
// Get its current value
var currentVal = parseInt($('input[name='+fieldName+']').val());
// If it isn't undefined or its greater than 0
if (!isNaN(currentVal) && currentVal > 0) {
// Decrement one
$('input[name='+fieldName+']').val(currentVal - 1);
qty = parseInt($('.qty').val());
price = parseFloat($('#price').val());
$('#total').val(((qty * price > 0) ? qty * price : 0).toFixed(2));
} else {
// Otherwise put a 0 there
$('input[name='+fieldName+']').val(0);
qty = parseInt($('.qty').val());
price = parseFloat($('#price').val());
$('#total').val(((qty * price > 0) ? qty * price : 0).toFixed(2));
}
});
});
Working Fiddle: http://jsfiddle.net/txk2d85y/
jQuery provide a plugin which may help you : "jQuery-Calx"
watch its demostration here :
http://prototype.xsanisty.com/calx2/
I'm not sure why you have two price boxes, but I've updated the fiddle to have 1, since this causes some unusual behaviour.
However, the root of the problem is that you have declared qty and price on document.ready, but then are not updating them whenever the buttons are clicked. Here is a fiddle demonstrating one solution:
http://jsfiddle.net/hktxyz5z/2/
However, I feel like you could make the whole thing much shorter and cleaner, reducing repetition of code between the plus and minus buttons. Stay tuned for an update with a recommendation...
Update
Here is a refactored version:
http://jsfiddle.net/hktxyz5z/3/
The changes I've made are:
You don't need an input, since you are simple preventing the default action anyway. In that case it is better to use a <button>, which I have done.
Both quantity buttons now respond to the same event handler, which simple reads the adjustment attribute from the button and passes it to the adjustQty function.
The adjustQty function then calculates the new total, and updates the text boxes.
If I've missed something obvious regarding the purpose of the second price box, please let me know and I'll adjust my example.
Update 2:
I'm guessing that you want to add up both price values, then multiply by the quantity? If so, this amended example should do the trick:
http://jsfiddle.net/hktxyz5z/4/
The only real difference is that it calculates the total for both price boxes before it multiplies by the quantity.
Related
I am building a webshop with WooCommerce.
We are using WooCommerce advanced quantity so the quantity is not like 1,2,3,4 etc but in steps of 0.72 for example. When using the +/- button it is working fine. (steps: 0.72, 1.44, 2.16 etc)
When I fill in 20 with my keyboard and click add to my cart in my cart there has been add a quantity of 19.44 instead of 20 because 20 is not an possible option. I want the field to autocorrect to the closest possible quantity value before adding it to my cart. So more like autocorrect it after deselecting the field.
How can I achieve this? Has it something to do with javascript?
Hope you guys can help me!
Link to example page so you can test it: https://www.stenenentegels.nl/product/trommelsteen-chelsea-20x30x4/
You can just set the value to the current value minus itself with the modulus operator. You can determine the best event, but blur would probably work best.
let qty = document.getElementById('qty');
qty.onblur = function(){
let val = this.value; // Current Value
let step = this.getAttribute('step'); // Get step instead of hard coding it
this.value = (val - (val % step)).toFixed(2); // Simple math that adjusts the value on blur
}
<input type="number" id="qty" step=".72" />
To round up one step, you could consider:
let qty = document.getElementById('qty');
qty.onblur = function(){
let val = this.value; // Current Value
let step = this.getAttribute('step'); // Get step instead of hard coding it
let roundDown = (val - (val % step)).toFixed(2);
let roundUp = (parseFloat(roundDown) + parseFloat(step)).toFixed(2);
this.value = roundUp;
}
<input type="number" id="qty" step=".72" />
If you only want this to effect steps that aren't 1, just wrap that in an if statement:
let qty = document.getElementById('qty');
qty.onblur = function(){
let val = this.value; // Current Value
let step = this.getAttribute('step'); // Get step instead of hard coding it
if( step != 1 ){
let roundDown = (val - (val % step)).toFixed(2);
let roundUp = (parseFloat(roundDown) + parseFloat(step)).toFixed(2);
this.value = roundUp;
}
}
<input type="number" id="qty" step=".72" />
You could do it in the blur event of the #qty field with javascript:
jQuery("#qty").on("blur", function(){
correctValue = jQuery(this).val() - (jQuery(this).val() % 0.72);
jQuery(this).val(correctValue.toFixed(2));
})
Edit: You need to find a place to put this - in a WooCommerce template or in the general js file of the site.
Edit 2: You can check that this actually works by pasting the above code in the Chrome JS console and then entering "20" in the field and clicking out of the field again.
Probably a simple answer but for some reason I can not find the answer even with a simple Google search.
I have number text box that I want to know if the value of the number goes up or increments, I want to do something and if the value goes down or decrements I want it to something else.
This is the simple JS I have right now but right now I am just looking for if the text box goes above 1. I want to actually know if the value actually incremented.
I am using jQuery.
I have some simple buttons incrementing the value of the textbox by 1 or drecrementing by 1.
You will see the section below where I need some help with as noted.
=============
EDIT:
Added a JSFiddle
http://jsfiddle.net/4v6wb2ys/2/
You will see on the left is a total of attendees. This controls the number that can be controlled on the right. My issue is partially the CART part at the bottom of the right panel in 'Result' in the Fiddle.
The Cart does not add items to the Cart as needed. It adds some but then on the decrement it adds more items until the value of the textbox hits 0. Then it removes them.
This is the main part of my question I am asking here. I need to add an take away items as the values in the right panel are incremented and decremented.
I know my JS is pretty ugly. IF there are improvements, please let me know how to fix them.
=======================
$(".AddMinusButton").on('click touchstart', function (event) {
var $button = $(this);
var oldValue = $button.parent().find("input.attendeeQuantityInput").val();
var newVal = oldValue;
//Increment and decrement the value of the textbox
if ($button.text() == "+") {
newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue >= 1) {
newVal = parseFloat(oldValue) - 1;
}
}
$InputItem = $('.ProductDetailPage').find("input[data-attendee='" + gaData + "']");
$InputItem.each(function() {
//I have some values for vars $list and li but those are not important for this.
//THIS IS WHERE I NEED THE ANSWER TO MY QUESTION
if ($(this).val() >= 1) { //This line should probably be were the 'IF value increments'
$list.append(li);
} else {
$list.find("li." + attendee + parentSection).remove();
}
});
});
Here is the sequence:
....
....
var newVal = oldValue;
var incremented; //declare a new variable;
....
....
newMemVal = parseFloat(oldMemValue) + 1;
incremented = true; //after you increment the value set the variable to true
.....
.....
newVal = parseFloat(oldValue) - 1;
incremented = false; //after you increment the value set the variable to false
....
....
if ( incremented ) { //Now you know what you did!! 'incremented' remembers for you.
$list.append(li);
....
....
I am trying to calculate the total of a selection of CDs in addition of P&P. The code I'm using is coming to a total of NaN?
Very confused here. what am I doing wrong?
function calculateTotal() {
var Collection method = document.getElementById('collection').value +
var select CDs = document.getElementById('selectCD').value;
var total = document.getElementById('total');
total.value = 'collection'(total) + 'selectCD'(total);
}
Here is a JSFiddle with the full code.
In your fiddle collection and selectCD are divs (not inputfields) containing inputfields. You can't do divElm.value.
Then the php-code in your fiddle would normally be able to output more then one cd, so you'd need to add the totals of the selected cd's to.
The minimum changes needed to get your code working are:
function calculateTotal(){
var coll = document.getElementsByName('deliveryType'),
cds = document.getElementsByName('cd[]'),
cdTot = 0,
L = coll.length;
while(L--){if(coll[L].checked){ //get shipping costs
coll=Number(coll[L].getAttribute('title')); break;
} }
L=cds.length;
while(L--){if(cds[L].checked){ //add total prices
cdTot += Number(cds[L].getAttribute('title'));
} }
// output total
document.getElementById('total').value = coll + cdTot;
}
Also you'd want to set some more triggers to function calculateTotal (from the shipping costs and selected cd's; this way, if they change, the total-field will update to).
See this working fiddle with these changes (and some other fixes) based on your fiddle so you can get motivated seeing it (calculation) in action.
However I do hope this is for a school-question and not for a live webshop. I would re-think my strategy as I think you are currently working your way to a big security hole.
Good luck!
I have multiple dropdown lists calculating a total price at the end, it works great apart from a few issues.
Firstly, I would like to add further prices to it, so it should read:
Total : £20.97
V.A.T : £4.19
Total Amount : £25.16
I'm sure this is simple but i cannot think how?
Secondly - It only works on a single selection drop down lists, if i want to select multiple options in one list, it will only calculate one
Here's the code i use to calculate the price:
$(function(){
$(".calculate").on("change", function(){
var total = 0;
$('.calculate').each(function() {
if($(this).val() != 0) {
total += parseFloat($(this).val());
}
});
$('#total').text('£' + total.toFixed(2));
});
});//]]>
Thirdly, there are about 8 dropdown lists but i want the last one to discount the total price instead of adding to it, the code above takes the price from option value of each selection and so will the discount amount (In the discount column in the database, it's written as 10%.
So basically, after 7 lists i should have a total of i.e. £20.97 then once the last list is selected, it should replace the price with a discount amount i.e. (-10%) £18.87
I'm so close to finishing this but i can't get over the last hurdle.
Thanks
When a SELECT allows multiple selections the jQuery val() function returns an array of values. So your code needs to detect if val() returns and array and if so loop the array and add all those items. Here is one way:
$('.calculate').each(function() {
var currentValue = $(this).val();
if (currentValue.length != undefined) {
for (var i = 0; i < currentValue.length; i++) {
if (currentValue[i] != 0) {
total += parseFloat(currentValue[i]);
}
}
}
else if(currentValue != 0) {
total += parseFloat(currentValue);
}
});
That should take care of multiple select options. For the discount, just get the value of your final SELECT and apply your discount:
var discount = parseFloat($('.discount').val()) / 100;
total = total - (total * discount);
Is the Javascript pulling the values from the DDL from the Database or hard-coded into the form?
the computation for the % is 20.97 *0.10. Since the 10% is hard-coded this should work for the final drop down list.
Also, other than adding values to the form, and the computation for percentage, I'm not sure where the problem is, maybe some more information would be of value...
First, please take a look at my fiddle.
I'm trying to figure out a clean way of making the price next to each item change when any item is selected (in that group, you can image that there will be graphics cards etc in a different section which also will need the same functionality).
If its positive I need the class to be .positive and vice versa, and if the item is selected (+0) then the price difference wont be displayed.
This will also be used on checkbox's.
Non-working example.
You'll want to compare each selected item with items having the same name. In the .each() loop in CalculatePrice(), pass the checked item to this function:
function CalculateDiffs(item) {
var selectedPrice = +item.data("price");
item.siblings(".item_price").text("");
$(".calculation-item[name='"+item.attr("name")+"']").not(item).each(function(){
var price = +$(this).data("price");
var diff = (price-selectedPrice).toFixed(2);
if (diff >= 0) {
diff = "+"+diff;
}
$(this).siblings(".item_price").toggleClass("negative", diff < 0).text(diff);
});
}
As for checkboxes, the above function will take care of hiding the price when it is checked. To display the prices for unchecked checkboxes:
$(".calculation-item:checkbox:not(:checked)").each(function(){
$(this).siblings(".item_price").text("+"+$(this).data("price"));
});
Or, if you want to display the price of a checked checkbox as negative, use this instead:
$(".calculation-item:checkbox").each(function(){
var diff = (this.checked ? "-" : "+") + $(this).data("price");
$(this).siblings(".item_price").toggleClass("negative",this.checked).text(diff);
});
http://jsfiddle.net/gilly3/HpEJf/8/
Actually it's pretty straight forward, all you'll need to do is calculate the difference between the selected price and the price of all the options in the list. Eg, something like this:
$(".calculation-item").each(function(index) {
var my_cost = base_price + $(this).data("price");
var difference = Math.round(my_cost - base_cost);
});
I've created a working jsFiddle for you here: http://jsfiddle.net/HpEJf/6/. You'll need to implement decimal rounding etc but this should put you on the right track :)
If my understanding is correct, you want to display the cost difference from the previously selected radio button and the currently selected radio button.
To do that you need to keep track of the previously selected button. The only way I know of to do that is to set a variable outside the clickhandler scope to keep track of it and update the element in the clickhandler.
The rest is fairly straightforward. I updated your jsFiddle with an example of how to do it. The relevant code is below:
Adding at top of script:
//global for last checked/selected radio
var lastSelection = $(".calculation-item:checked");
//clear existing price diffs set by markup
$('span.processor_price').text('');
Added another function:
function priceDifference(oldPrice, newPrice) {
var difference = {
'cssClass': '',
'inCost': '0'
};
var fixedDiff = '';
var diff = newPrice - oldPrice;
diff = Math.ceil(Math.abs(diff * 100)) / 100;
fixedDiff = diff.toString();
if (newPrice < oldPrice) {
difference.cssClass = 'negative';
difference.inCost = '-' + fixedDiff;
} else if (newPrice > oldPrice) {
difference.cssClass = 'positive';
difference.inCost = '+' + fixedDiff;
}
/* else {
* must be the same, no reason for this block
* as the default empty string will suffice
* as will the cost difference of 0
}*/
return difference;
}
And changed your click handler to:
$(".calculation-item").click(function() {
var difference = {};
if (lastSelection) {
//get difference
difference = priceDifference($(lastSelection).data("price"), $(this).data("price"));
//change class
$(this).siblings('span.processor_price').addClass(difference.cssClass).text(difference.inCost);
$(lastSelection).siblings('span.processor_price').removeClass('positive').removeClass('negative').text('');
if (lastSelection !== this) {
lastSelection = this;
}
} else {
lastSelection = this;
}
CalculatePrice();
});