Calculate the price of the items, depending on its quantity - javascript

I'm trying to make block with the prices. The unit price varies depending on its quantity of units. For example:
Quantity — Price for each
1____________________$110
10___________________$105
20___________________$100
...
Number of items:__
Total:
Price for each:
There is a need to write a the text field into which the user enters the number of items, and everything is recalculating and summing on the fly.
Here is my realization of this task:
var price1 = 110,
price2 = 105,
price3 = 100,
qty1 = 1,
qty2 = 10,
qty3 = 20;
function conversion(val) {
var div = document.getElementById("div"),
price = document.getElementById("price");
if (isNaN(val)) {
div.innerHTML = "";
price.innerHTML = "";
} else {
switch (true) {
case (val <= 0):
{
div.innerHTML = "";
price.innerHTML = "";
break;
}
case (val >= qty1 && val < qty2):
{
div.innerHTML = val * price1;
price.innerHTML = price1;
break;
}
case (val >= qty2 && val < qty3):
{
div.innerHTML = val * price2;
price.innerHTML = price2;
break;
}
case (val >= qty3):
{
div.innerHTML = val * price3;
price.innerHTML = price3;
break;
}
}
}
}
<div>
Quantity — Price for each
</div>
<div>
<div>1 — $110</div>
<div>10 — $105</div>
<div>20 — $100</div>
</div>
<div>
Number of items:
<div>
<input id="txt" onblur="conversion(this.value)" onchange="conversion(this.value)" onkeypress="conversion(this.value)" onkeyup="conversion(this.value)" type="number">
</div>
</div>
<div>
Total:
<div id="div"></div>
</div>
<div>
Price for each:
<div id="price"></div>
</div>
How it can be properly implemented, taking into account the fact that the lines with the quantity and unit price can be from one to infinity (values are taken from the database)?
I think it is possible to record the price and quantity in data-atributes and parse it with JS. Like this:
...
<div data-quantity="10" data-price="105">
<span class="quantity">10</span>
<span class="price">105</span>
</div>
...
Thanks!

Using the data attribute is indeed a solution:
console.log(document.getElementById("test").dataset)
<div data-quantity="10" data-price="105" id="test">
<span class="quantity">10</span>
<span class="price">105</span>
</div>
It's not fully compatible with previous IE version though, so be careful with it.
I would however suggest that you look for a way of moving your calculations away from the DOM to speed up your calculations.
For instance, parsing the data to a JavaScript object and doing the calculations there would save you some DOM trips and thus speed:
console.clear();
//markup for product
function Product(name) {
return {
//Name of product
name : name,
//List of price ranges (populated later)
prices : [
],
//method for adding a price
newPrice : function newPrice(quantity, cost) {
//Push new price unto list
this.prices.push({
quantity : quantity,
cost : cost
});
//Sort list
this.prices = this.prices.sort(function (a, b) {
return a.quantity - b.quantity
});
},
//Get the price for a variable quantity of this product
get : function (quantity) {
//Loop through prices to find the most matching
var price = 0;
for (var i = 0; i < this.prices.length; i++) {
if (this.prices[i].quantity <= quantity) {
price = this.prices[i].cost;
} else {
break;
}
}
console.log('price per unit:', price, 'price for all', quantity, 'units:', price * quantity)
}
};
} //Make an instance
var myHotProduct = new Product('Fancy pants');
//Add some prices
myHotProduct.newPrice(0, 110);
myHotProduct.newPrice(10, 105);
myHotProduct.newPrice(20, 100);
//get some quantities
myHotProduct.get(0);
myHotProduct.get(1);
myHotProduct.get(9);
myHotProduct.get(10);
myHotProduct.get(19);
myHotProduct.get(20);
//Log everything we know about our product
console.log(myHotProduct);
Now you can get your prices as arrays and modify them outside of the limitations of data-.

Related

How to update order quantity (increment and decrement) in shopping cart?

I have this following code for the shopping cart with pure Javascript which can add multiply products into cart. Any clue on how to update the product quantity when the user click the + and - button in the cart without changing the order of the item in the cart?
Each button already have the product id as primary key. My idea is I could remove (using pop) the selected object using .filter() and then add (using push) back updated object into the list. But doing so will change the order of the cart.
var productList = [
{ id: 101, product: "Logitech Mouse", unitprice: 45.0 },
{ id: 102, product: "Logitech Keyboard", unitprice: 50.0 },
{ id: 103, product: "HP Mouse", unitprice: 35.0 }
];
var cart = [];
cart.length = 0;
const createCartHTMLElements = object => {
// Check type
if (typeof object !== "object") return false;
// Start our HTML
var html = "<table><tbody>";
// Loop through members of the object
debugger;
object.forEach(function(item) {
html += `<tr><td>${item.product}</td>\
<td>${item.unitprice.toFixed(2)}</td>\
<td>\
<button class="plus-btn" data-id="${item.id}">+</button>\
<label id="quantity">${item.quantity}</label>\
<button class="minus-btn" data-id="${item.id}">-</button>\
</td>\
<td>${item.total.toFixed(2)}</td>\
<td><i class="fa fa-remove del" data-id="${item.id}"></i></td>\
</tr>`;
});
// Finish the table:
html += "</tbody></table>";
// Return the table
return html;
};
const populateProducts = arrOfObjects => {
// Start our HTML
var html = "";
// Loop through members of the object
arrOfObjects.forEach(function(item) {
html += `<div class="column"><div class="card">\
<h2>${item.product}</h2>
<p class="price">RM ${item.unitprice.toFixed(2)}</p>
<p><button class=AddToCart data-id="${
item.id
}">Add to Cart</button></p>\
</div></div>`;
});
return html;
};
window.addEventListener("load", function() {
document.getElementById("productRow").innerHTML = populateProducts(
productList
);
var addToCart = document.getElementsByClassName("AddToCart");
Array.prototype.forEach.call(addToCart, function(element) {
element.addEventListener("click", function() {
debugger;
// Filter the selected "AddToCart" product from the ProductList list object.
// And push the selected single product into shopping cart list object.
productList.filter(prod => {
if (prod.id == element.dataset.id) {
prod.quantity = 1;
prod.total = prod.unitprice;
cart.push(prod);
document.getElementById(
"shoppingCart"
).innerHTML = createCartHTMLElements(cart);
return;
}
});
});
});
});
<div id="shoppingCartContainer">
<div id="shoppingCart"></div>
</div>
<hr />
<div id="productRow"></div>
You use ids multiple times; You should instead apply a class to <label id="quantity">${item.quantity}</label> so that it is <label class="quantity">${item.quantity}</label>. Also please add class price to the price and class total to the total.
Then, you can increase or lower the amount:
$(document.body).on('click', '.plus-btn', function(){
var $tr = $(this).closest('tr');
//update the quantity;
var $quantity = $tr.find('.quantity');
var n = $quantity.html();
var i = parseInt(n) + 1;
$quantity.html(i);
//update the total price
var $price = $tr.find('.price');
var price = parseFloat($price.html());
var $total = $tr.find('.total');
$total.html(i*price);
});
$(document.body).on('click', '.minus-btn', function(){
var $tr = $(this).closest('tr');
//update the quantity;
var $quantity = $tr.find('.quantity');
var n = $quantity.html();
var i = parseInt(n) - 1;
if(i<0) i = 0;
$quantity.html(i);
//update the total price
var $price = $tr.find('.price');
var price = parseFloat($price.html());
var $total = $tr.find('.total');
$total.html(i*price);
});

Removing the shipping price, if the amount has reached a certain value

So I have a working shopping cart page, but I do not know how to remove the shipping value, once a user has reached a total, for example, of 50 or higher. In the previous version this was already implemented, so I tried to compare and figure out how to implement this in the new page, but am not skilled enough in JavaScript. This is the JavaScript I am using right now.
$(document).ready(function() {
var taxRate = 0.05;
var shippingRate = 5.00;
var fadeTime = 300;
$('.product-quantity input').change( function() {
updateQuantity(this);
});
$('.product-removal button').click( function() {
removeItem(this);
});
function recalculateCart()
{
var subtotal = 0;
$('.product').each(function () {
subtotal += parseFloat($(this).children('.product-line-price').text());
});
var tax = subtotal * taxRate;
var shipping = (subtotal > 0 ? shippingRate : 0);
var total = subtotal + tax + shipping;
$('.totals-value').fadeOut(fadeTime, function() {
$('#cart-subtotal').html(subtotal.toFixed(2));
$('#cart-tax').html(tax.toFixed(2));
$('#cart-shipping').html(shipping.toFixed(2));
$('#cart-total').html(total.toFixed(2));
if(total == 0){
$('.checkout').fadeOut(fadeTime);
}else{
$('.checkout').fadeIn(fadeTime);
}
$('.totals-value').fadeIn(fadeTime);
});
}
function updateQuantity(quantityInput)
{
var productRow = $(quantityInput).parent().parent();
var price = parseFloat(productRow.children('.product-price').text());
var quantity = $(quantityInput).val();
var linePrice = price * quantity;
productRow.children('.product-line-price').each(function () {
$(this).fadeOut(fadeTime, function() {
$(this).text(linePrice.toFixed(2));
recalculateCart();
$(this).fadeIn(fadeTime);
});
});
}
function removeItem(removeButton)
{
var productRow = $(removeButton).parent().parent();
productRow.slideUp(fadeTime, function() {
productRow.remove();
recalculateCart();
});
}
});
Set shipping to zero when subtotal + tax >= 50 (assuming that's the business rule).
var shipping = subtotal > 0 && (subtotal + tax < 50) ? shippingRate : 0;
And then, for display purposes, set the shipping value element to empty when shipping === 0. A ternary operator is one way to do it.
$('#cart-shipping').html(shipping === 0 ? '' : shipping.toFixed(2));

How to calculate total?

I faced a problem for my code and I could not solve it. I have 2 functions, the first one calculates the total and second one discounts the total (if the user write the discount code, it will show the discounted total). But I don't know how to get and call the right value from total to keep it in the second function to calculate the discount because it always shows 0 in the amount. The TOTAL is for the first function and JavaScript code is for the second function.
total = parseInt(TicketsPrice[i].value) * parseInt(NOfTictet);
document.getElementById("total").innerHTML = total;
function discount(coupon) {
var yCoupon = "winner1";
var price = Number(document.getElementById('total').innerHTML);
var amount;
var input = document.getElementById('discount').value;
if (input == coupon) {
amount = price || 0 * 0.25;
document.getElementById("Offerprice").innerHTML = amount;
} else {
alert("Invalid");
}
}
<input type="text" name="coupon" id="discount">
<button onclick="discount()">discount</button>
<p id="total"></p>
<p><span id="Offerprice"></span></p>
Something like this?
function discount() {
var coupon = "winner1";
var price = Number(document.getElementById('total').value);
var input = document.getElementById('discount').value;
if (input == coupon) {
var amount = price * (1 - .25) // 25% off coupon
document.getElementById("Offerprice").innerHTML = amount;
} else {
document.getElementById("Offerprice").innerHTML = 'Invalid coupon'
}
}
<div>Total: <input id="total"></div>
<div>Coupon: <input id="discount"></div>
<button onclick="discount()"> discount</button>
<p><span id ="Offerprice"></span></p>
You have several issues in your code. Here is a working version. I hardcoded the total only for testing because I don't know the HTML for your tickets:
var total = 500; //This is only for testing.
document.getElementById("total").innerHTML = total;
function discount() {
var coupon = "winner1";
var price = Number(document.getElementById('total').innerHTML);
var input = document.getElementById('discount').value;
if (input == coupon) {
var amount = price * 0.75; //discount of 25%
document.getElementById("Offerprice").innerHTML = amount;
} else {
alert("Invalid");
}
}
<input type="text" name="coupon" id="discount">
<button onclick="discount()">discount</button>
<p id="total"></p>
<p><span id="Offerprice"></span></p>

How to create multiple variables dynamically that can be summed up

I have a variable that gets its value once an ID is clicked, via .innerText
var currentID = e.target.id;
I need the value of this variable, currentID, to be stored in a new variable which is named just like the ID of which it got its value.
So, if a user clicks an element with the ID price1, and the price is 200.
A new variable with the name price1 with value 200 should be created.
Then, I want to sum up the new variables: price1+price2+price3 etc = totalprice.
This is what I'm doing right now:
$('div.unselected-option').click(function(e) {
$(this).toggleClass("selected-option unselected-option")
if ($(this).hasClass("selected-option")) {
var currentID = e.target.id;
console.log(currentID);
var price1 = document.getElementById(currentID).innerText
var finalprice
finalprice = +price1;
document.getElementById("showprice2").innerHTML = finalprice
Here's an image of the design:
I can't seem to figure this out... What I'm doing right now just results in having 1 variable which means I cannot sum anything up... I would love your view on this issue!
Your use case is pretty strange I hope your backend is secured and well made.
Here is a potential solution:
<div id="a1" onclick="handleProductClick">20</div>
<div id="a2" onclick="handleProductClick">40</div>
<div id="b1" onclick="handleProductClick">20</div>
<div id="b2" onclick="handleProductClick">60</div>
...
<div id="total-price">0</div>
...
const basket = {}
function addToBasket(event) {
const { id, innerText } = event.target
const price = parseInt(innertText, 10)
const product = basket[id]
const count = product.count || 1
basket[id] = {
price,
count
}
}
function getBasketTotalPrice = () => {
return Object.keys(basket)
.reduce((total, product) => total + product.count * product.price, 0)
}
function handleProductClick = (event) => {
addToBasket(event)
const totalPrice = getBasketTotalPrice()
document.querySelector('#total-price').innerHTML = totalPrice
}

Javascript selection

I have a dropdown list of "Pounds", "grams", "Kilograms" and "Ounces". I want a situation that when I select gram to perform a function, when I input a value in the input field, also when i select pounds i want another function to perform when i input a value in the input field and so on. I have tried it but couldn't get it done.
Here's my code....
HTML
<div id="weight-dropdown">
<h4>Weight Converter</h4>
<select id="select-weight">
<option value="0">...</option>
<option value="1">Pounds</option>
<option value="2">Grams</option>
<option value="3">Kilograms</option>
<option value="4">Ounce</option>
</select>
<input id="input" type="number" placeholder="Enter value...">
</div> <!-- weight dropdown-->
<div id="output">
<div>
<h5>Pounds (lbs) :</h5>
<div id="poundsOutput"></div>
</div>
<div>
<h5>Grams (g) :</h5>
<div id="gramsOutput"></div>
</div>
<div>
<h5>Kilorams (kg) :</h5>
<div id="kgOutput"></div>
</div>
<div>
<h5>Ounce (oz) :</h5>
<div id="ozOutput"></div>
</div>
</div><!--output-->
Javascript
if (document.getElementById("select-weight").selectedIndex = "0"){
document.getElementById("input").addEventListener("input", function(e){
var pounds= e.target.value;
document.getElementById("poundsOutput").innerHTML = pounds
document.getElementById("gramsOutput").innerHTML = pounds/0.0022046;
document.getElementById("kgOutput").innerHTML = pounds/2.2046;
document.getElementById("ozOutput").innerHTML = pounds*16;
})
} else (document.getElementById("select-weight").selectedIndex = "2"){
document.getElementById("input").addEventListener("input", function(e){
var grams= e.target.value;
document.getElementById("poundsOutput").innerHTML = grams*0.0022046;
document.getElementById("gramsOutput").innerHTML = grams;
document.getElementById("kgOutput").innerHTML = grams/1000;
document.getElementById("ozOutput").innerHTML = grams/28.35;
})
}
You assign the input listener based on the input value once , but once assigned it gets always triggered, even if the select changes. May do it the other way round and use a switch:
document.getElementById("input")
.addEventListener("input", function(e){
var input = e.target.value;
switch(document.getElementById("select-weight").selectedIndex){
case 0:
return alert("Please select unit");
break;
case 1 :
var pounds = input;
var grams = input/0.0022046;
var kg = input/2.2046;
var oz = input * 16;
break;
case 2:
var pounds = input * 0.0022046;
var grams = input;
var kg = pounds/2.2046;
var oz = pounds * 16;
break;
case 3:
//...
break;
}
//update DOM with values
document.getElementById("poundsOutput").innerHTML = pounds;
document.getElementById("gramsOutput").innerHTML = grams;
document.getElementById("kgOutput").innerHTML = kg;
document.getElementById("ozOutput").innerHTML = oz;
});
While the upper code is good / understandable, you could use a more shorter approach. You could get the value of the next "row" by dividing through a certain number, and of the previous by multiplying with a certain number. So you could do:
var conversion = [
null,//an endpoint
1,// pounds / this = grams
2,//grams / this = kg
3, //kg/this = oz
null//an endpoint
];
//some pseudocode:
var index = selectWeight.selectedIndex;
var start = event.target.value;
var result = [];
//now multiple from right to left of selected index:
conversion.slice(0,index).reduceRight(function(value,multiplier,i){
result[i] = value;
return value * multiplier;
}, start);
//divide from right to left:
conversion.slice(index-1).reduce(function(value,divider,i){
result[index+i-1] = value;
return value / divider;
},start);
And now weve got our results:
var [pounds,grams,kg,oz] = result;
You're doing a left-hand assignment;
if (document.getElementById("select-weight").selectedIndex = "0"){
while it should be
if (document.getElementById("select-weight").selectedIndex == "0"){
Same applies to other statements.
Use the event onClick for each option and then use their ids to do a factory of weight functions.

Categories

Resources