So how would one in JavaScript or with the added help of jQuery be able to get price variations. For example the first item is a set base at $450 and every item after that is a additional $150. But here is the trick the client is able to change that price so $450 is now $225 and additional is $75. I know how to do this with a bunch of if else statements but that just seems messy. Is there a better way?
Here's my code so far it only does the divided by two part but not the additions.
Edit: Further explanation of how this works
item#1 450
item#2 150
item#3 150
full[x] half[ ]
item#1 225
item#2 75
item#3 75
full[ ] half[x]
each additional is actually the base divided by 3 so 450 = 150 and 225 = 75 and the half is the original base 450 / 2 = 225
var dropResult;
$(function (){
$(".t").click(function(){
dropResult = $("input[name=drop]:checked").val();
dropCalculate();
});
});
function dropCalculate() {
var dropPrice = 450;
var dropAmount = $(".itemadd", "#items").length;
$("#dropAmount").html("Total: " + dropAmount);
if (dropResult == 1) {
dropTotal = dropAmount * dropPrice;
$("#dropPrice").html("Price Total: $" + dropTotal.toFixed(2));
}else {
dropTotal = dropAmount * dropPrice / 2;
$("#dropPrice").html("Price Total: $" + dropTotal.toFixed(2));
}
}
Okay, so if I understand you correctly, you want to apply a discount to the given price in a clean manner, depending on the number of items. I'd first start by applying the DRY (Don't Repeat Yourself) principle to your code, and putting variables in local scope:
//var dropResult = $("input[name=drop]:checked").val();
//this line doesn't actually do anything, so I removed it. It will always return true, as you're using the :checked pseudo-selector to only select checked checkboxes.
$(function (){
$(".t").click(function(){
dropCalculate(450);
});
});
function dropCalculate(dropPrice) {
var dropAmount = $(".itemadd", "#items").length,
dropTotal = dropAmount * dropPrice;
if (dropResult != 1) {
dropTotal = dropTotal / 2;
}
$("#dropPrice").html("Price Total: $" + dropTotal.toFixed(2));
}
Which is a lot cleaner. Then, if you have more complex discount rules, or multiple rules for multiple products, you can use an object for that. Here is a simple example of that:
$(function (){
$(".t").click(function(){
var pricesObj = {
'default': 75,
'1':450,
'2':225
};
dropCalculate(pricesObj);
});
});
function dropCalculate(priceObj) {
var dropAmount = $(".itemadd", "#items").length;
if (priceObj[dropAmount]) {
dropTotal = priceObj[dropAmount] * dropAmount;
}
else{
dropTotal = priceObj['default'] * dropAmount;
}
$("#dropPrice").html("Price Total: $" + dropTotal.toFixed(2));
}
If you need any help understanding that, just ask!
Update: I misunderstood your use case, but this should still point you in the right direction. In my code, if there is 1 product, the price is 450, 2 is 225, and more is 75 each.
a quick change you could make, it's something like that:
dropTotal = dropAmount * dropPrice;
$("#dropPrice").html("Price Total: $" + dropResult == 1 ? dropTotal.toFixed(2)) : (dropTotal / 2).toFixed(2));
check this fiddle
$('#dropPrice').text( '$' + (450 + ((450 * ($('#items .itemadd').length - 1)) / 3)) / (Number($("input[name=drop]").is(':checked')) + 1));
Related
I'm trying to validate in Javascript that a number is in increments of 50, if not, then throw a validation error. For example:
123 - invalid, can either be 100 or 150
272 - invalid, can either be 200 or 250 or 300
etc...
I'm thinking that the % remainder operator is what I need to use but not quite sure how to build a javascript validation rule to match this.
Are you looking for something like:
(val) => {
var remainder = val % 50;
if (remainder !== 0) {
var lower = val - remainder;
var higher = lower + 50;
throw new Error(val + ' - invalid, can either be ' + String(lower) + ' or ' + String(higher));
}
}
That could be reduced, but this way you can see the logic at work.
This is the math you want to preform:
Math.round(123/ 50)*50; //this gives 100
Math.ceil(123/ 50)*50; //this gives 150
and here is the validation function
function validate(number) {
var round = Math.round(number / 50) * 50;
var ceil = Math.ceil(number / 50) * 50;
if (number == round) { return console.log("valid"); }
return console.log(`${number} - invali, can eiher be ${round} or ${ceil}`);
}
I didn't think this was possible until console.log(); shown me that whats happening is impossible.
I can't understand how this is possible it's like those variables are being modified before code execution finishes.
I got this JavaScript code with debugging in it.
It's wrapped in this.
$('#buyAmountInput').keyup(function () {
var buyAmount = parseFloat($(this).val());
var totalPrice = 0;
var max = $(this).attr("max");
var min = $(this).attr("min");
if (buyAmount != $(this).val()) {
if (isNaN(buyAmount)) {
buyAmount = 1;
$(this).val('');
} else {
$(this).val(buyAmount);
}
} else {
if (buyAmount > max) {
buyAmount = max;
$(this).val(buyAmount);
} else if (buyAmount < min) {
buyAmount = min;
//$(this).val(buyAmount);
}
}
totalPrice = buyAmount * unitPrice;
//lots of code trimmed off here.
largessAmount = Math.round(buyAmount * largessRule.rebate) / 100;
////
console.log("Buy amount " + buyAmount + " LargessRebate " + largessRule.rebate);
console.log("Total Price " + totalPrice);
console.log("Largess Amount " + largessAmount);
console.log("New rate " + Number(totalPrice / (buyAmount + largessAmount)).moneyFormat());
console.log("No .moneyFormat() New rate " + Number(totalPrice / (buyAmount + largessAmount)));
console.log("( " + totalPrice + " / ( " + buyAmount + " + " + largessAmount + " ))");
////
$('#unitPrice').html(Number(totalPrice / (buyAmount + largessAmount)).moneyFormat());
});
Debug looks like this
Buy amount 5000 LargessRebate 20
Total Price 4250
Largess Amount 1000
New rate 0.71
No .moneyFormat() New rate 0.7083333333333334
( 4250 / (5000 + 1000))
function fastKeyListener content_script.js:208
Buy amount 5000 LargessRebate 20
Total Price 4250
Largess Amount 1000
New rate 0.00 //<- What happened here
No .moneyFormat() New rate 0.00008499830003399932 //<- What happened here
( 4250 / (5000 + 1000)) //<- Third line executed this will give good rate..
Even if the variables are global and this code is in a keypress up jQuery callback function.
The variables are printed before they are executed by console.log() and they are correct but the answer is dead wrong.
Here is the moneyFormat() which I don't think could be the problem could it?
var effective_bit = -2;
Number.prototype.moneyFormat = function () {
var num = this;
sign = (num == (num = Math.abs(num)));
num = Math.floor(num * Math.pow(10, -effective_bit) + 0.50000000001);
cents = num % Math.pow(10, -effective_bit);
num = Math.floor(num / Math.pow(10, -effective_bit)).toString();
for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++)
num = num.substring(0, num.length - (4 * i + 3)) + ', ' + num.substring(num.length - (4 * i + 3));
if (effective_bit < 0) {
if (cents < 10 && effective_bit == '-2') cents = "0" + cents;
money = (((sign) ? '' : '-') + num + '.' + cents);
} else {
money = (((sign) ? '' : '-') + num);
}
return money;
};
I didn't post the whole code as it's very large, but you can see it live here
Just put into the Unit to buy of 4999, then scroll to 5000 it's all good.. try putting like 5001 or 50000 it will reset it to 5000 and give wrong answer in the process.
EDIT:
could of simplified the question to why does the console.log() functions evaluate incorrect answer if the same equation generated with the same variables just 1 line after in execution after gives correct answer, even on calculator.
Like some quantum going on here, bear with me there is nothing I could have done from 1 line to another line during that code-execution no breakpoints were set nothing plus those callbacks are functions generated in their own sandbox I believe so they are like ajax threads all working to complete sooner or later they all work separately from each other, so nothing working together here to mess it up. What you think could possibly happen here? some temporarily corruption or something?
This occurs sometimes when doing claulations using string variables.
Try converting the buyAmount and any variable that came from HTML to number before any calculation.
You can use the Number() function or parseFloat().
http://jsfiddle.net/rcdmk/63qas2kw/1/
I'm having some problems with this code. My problem is that with the code below, it doesn't plus the detection-ratio text with the 'incr'. It just enters the incr, but doesn't plus.
This is my code.
(function loop() {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
var incr=Math.floor(Math.random()*6);
setTimeout(function() {
document.getElementById('detection-ratio').innerText = '0 / '+ ++incr;
loop();
}, rand);
}());
The 'detection-ratio' text looks like this as default:
0 / 0
Then, lets say 'incr' generates the number '3', then it should increase the last 0 with 3, so it would look like this:
0 / 3
Then, lets say it's going to generate a new 'incr', lets say '5'. Then it would look like this:
0 / 8
---> But right now, it doesn't do that. It just writes the 'incr' into the 'detection-ratio' without increasing it.
Hope this code would help you to get the expected output, let me know if something breaks. Also stop iteration once it reaches > 26
var incr = 0;
(function loop() {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
incr += Math.floor(Math.random()*6);
setTimeout(function() {
console.log('0 / '+ incr);
loop();
}, rand);
}());
Thanks for the explanation and patience.
I am assuming you are trying to append text to detection-ratio
if so you need to
document.getElementById('detection-ratio').innerText += '0 / '+ incr;
++ before a variable is a pre-increment operator, since you are generating random numbers i am assuming that is not actually what you want.
Since you're calling the loop recursively anyway, you may want to consider a more functional approach:
(function loop(startctr) {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
nextctr = startctr + Math.floor(Math.random()*6);
setTimeout(function() {
console.log('0 / '+ nextctr);
loop(nextctr);
}, rand);
}(0));
My hourly wage calculator isn't working. I should be getting 3 different numbers, but the two first numbers don't show up, and the last number is NaN. Please help. The code I'm using is shown below.
var hourly = $('#txtHourlyWage').val();
var fraction = hourly/60/60/10;
var calc = new Calculator();
function addCommas(str){
return(str+"").replace(/\b(\d+)((\.\d+)*)\b/g,function(a,b,c){
return(b.charAt(0)>0&&!(c||".").lastIndexOf(".")?b.replace(/(\d)(?=(\d{3})+$)/g,"$1,"):b)+c;
});
}
$('#year-calculation').html(addCommas(Math.round(calc.annual/(hourly*calc.per_hour))) + ' years' );
$('#your-time').html( (((hourly*2080)/ calc.annual) * 52 * 5 * 8).toFixed(1) + " hours");
$('#txtHourlyWage').bind('keypress', function(e) {
if ($('#txtHourlyWage').length < 2) {
return ( e.which!=8 && e.which!=0 && (e.which<48 || e.which>57)) ? false : true ;
} else {
return false;
}
return
})
$('#txtHourlyWage').keyup(function (){
$('#year-calculation').html(addCommas(Math.round(calc.annual/(hourly*calc.per_hour))) + ' years' );
$('#your-time').html( (((hourly*2080)/ calc.annual) * 52 * 5 * 8).toFixed(1) + " hours");
$('#HourlyWageOutput').html("At this rate, it would take you <span id=\"year-calculation\"> </span> to earn his yearly income and <span id=\"your-time\"> </span> for him to earn yours.");
});
This code produces the following:
At this rate, it would take you to earn his yearly income and for him to earn yours.
NaN hours
As you can see from above, what the code has produced doesn't make sense because the numbers are missing. I can't tell what I'm doing wrong. Please help.
You're not setting the numbers on the keyup event.
You need to put these lines:
$('#year-calculation').html(addCommas(Math.round(calc.annual/(hourly*calc.per_hour))) + ' years' );
$('#your-time').html( (((hourly*2080)/ calc.annual) * 52 * 5 * 8).toFixed(1) + " hours");
inside the keyup. As it is, they are only fired once, onload, presumably before there is anything to calculate with.
EDIT AGAIN: Still untested but I think it should work:
function addCommas(str){
return(str+"").replace(/\b(\d+)((\.\d+)*)\b/g,function(a,b,c){
return(b.charAt(0)>0&&!(c||".").lastIndexOf(".")?b.replace(/(\d)(?=(\d{3})+$)/g,"$1,"):b)+c;
});
}
$('#txtHourlyWage').bind('keypress', function(e) {
if ($('#txtHourlyWage').length < 2) {
return ( e.which!=8 && e.which!=0 && (e.which<48 || e.which>57)) ? false : true ;
} else {
return false;
}
return;
});
$('#HourlyWageOutput').html("At this rate, it would take you <span id=\"year-calculation\"> </span> to earn his yearly income and <span id=\"your-time\"> </span> for him to earn yours.");
$('#txtHourlyWage').keyup(function (){
var hourly = $(this).val();
var fraction = hourly/60/60/10;
var calc = new Calculator();
$('#year-calculation').html(addCommas(Math.round(calc.annual/(hourly*calc.per_hour))) + ' years' );
$('#your-time').html( (((hourly*2080)/ calc.annual) * 52 * 5 * 8).toFixed(1) + " hours");
});
Of course, you don't need to set $('#HourlyWageOutput') if it's already defined in the HTML.
How do I get cart checkout price exact to the penny using Javascript?
Right now after taking out all of the trial .rounds etc I was trying.. I am coming up 1.5 cents too high using a high 15 products/prices to test.
for (var i = 0; i < Cookie.products.length; i++) {
boolActive = Cookie.products[i].og_active;
if (boolActive)
{
itemPrice = Cookie.products[i].price;
itemQty = Cookie.products[i].quantity;
itemDiscountPercent = Cookie.products[i].discount_percent;
subtotal = itemPrice * itemQty;
priceDiscount = (subtotal * itemDiscountPercent);
discountAmount += priceDiscount;
}
}
if (!isNaN(discountAmount))
{
var newCartTotal = (cartTotal - priceDiscount);
alert("New Cart Total: " + newCartTotal);
}
var newCartTotal = (cartTotal - pricediscount).toFixed(2)
that will give you the value, but it will be a string. If you need it to stay numeric, use:
var newCartTotal = ((cartTotal - pricediscount * 100) << 0) / 100;
You need to round the discount for each line item: priceDiscount = round_to_hundredth(subtotal * itemDiscountPercent)
Note that this result may not agree with the result you'd get if you add the unrounded results and then round the sum. However, this is the way invoices usually work when calculated by hand (especially since each item can have a different discount percent, so the discount is calculated for each line).
I think you left out a line saying discountAmount += priceDiscount.
modify your code to :
priceDiscount = parseFloat( (subtotal * itemDiscountPercent).toFixed(2) );
and:
newCartTotal = parseFloat( (cartTotal - priceDiscount).toFixed(2) );