I picked up where I left off in the last post, by continuing my website build with Javacript on the shop page.
I am learning to create the following functionality on my page.
I am learning to create the following functionality on my page.
Go through every row in the cart
Find the price and quantity on each row
Multiply the item price by the quantity to find the row total
Sum the row totals together
Display total in the total field.
In the previous session I learned how to use Javascript to target and extract values from each item in the cart row. I also learned how to multiply the values together to give me the cart total (steps 1-3).
Displaying the cart total on the page was pretty simple, I just needed to add another getElementByClassName, searched for the cart-total-price class and set that to a variable called 'total'.
But! I forgot to define the variable, total, earlier on (I think I missed this bit of the video), so the final page didn't work. I was proud of myself though, for spotting that I hadn't defined what 'total' was. I fixed it. So I suppose that's the first example of me debugging my code?
Apparently I need to make sure that the page content has loaded and it sort of makes sense to me. Since my Javascript is loaded at the same time that the page content is loaded, there might be a time when the Javascript loads and the body doesn't. Since the Javascript references elements in the body (which won't have loaded yet), it'll get confused.
So anyway, not sure what I'm doing, but I added an if statement to the top of my .js file to check that the page had loaded.
if(document.readyState == "loading") {
document,addEventListener("DOMContentLoaded, ready")
} else {
ready()
}
function ready() {
var removeCartItemButtons = document.getElementsByClassName("btn-danger")
console.log(removeCartItemButtons)
for (var i = 0; i < removeCartItemButtons.length; i++) {
var button = removeCartItemButtons[i]
button.addEventListener("click", function(event) {
var buttonClicked = event.target
buttonClicked.parentElement.parentElement.remove()
updateCartTotal()
})
}
}
This means, I think, that the buttons will only work once the whole page has loaded, though I really don't know what I've just done. I hope it becomes clear later - most of this course does become clearer the more I crawl through.
I also cleaned up my code slightly by creating an function, removeCartItem, which did all of the business for the 'remove' buttons. I then embedded this function rather than the code for it in the button event listener function. This will make it easier to tell what's going on in my code.
function removeCartItem(event) {
var buttonClicked = event.target
buttonClicked.parentElement.parentElement.remove()
updateCartTotal()
}
The cart total does not update when the quantity inputs are changed. And users can input negative values in. We don't want either of these things to happen.
I started by copying much of the code form the remove button function (including the work mentioned above to clean the code up). I then created a few lines of code which would check what value to input was. If the value is not a number or is less than or equal to zero, I set the input value at 1.
function quantityChanged(event) {
var input = event.target
if (isNaN(input.value) || input.value <= 0) {
input.value = 1
}
}
I could then add the function updateCartTotal so that updating the input updated the total.
This worked quite nicely. But for some reason I was getting loads of recurring 9s at the end of the price. Huh?
This has something to do with how computers multiply or divide "floating point" numbers. Huh?
It's easy enough to fix, I just need to round the total column to 2 decimal places.
I added a simple calculation at the bottom of the updateCartTotal() function. This would take the total, round it and divide by 100 to give a decimal value. Check out the second last line below.
function updateCartTotal() {
var cartItemContainer = document.getElementsByClassName("cart-items")[0]
var cartRows = cartItemContainer.getElementsByClassName("cart-row")
var total = 0
for (var i = 0; i < cartRows.length; i++) {
var cartRow = cartRows[i]
var priceElement = cartRow.getElementsByClassName("cart-price")[0]
var quantityElement = cartRow.getElementsByClassName("cart-quantity-input")[0]
var price = parseFloat(priceElement.innerText.replace("£",""))
var quantity = quantityElement.value
total = total + (price * quantity)
}
total = Math.round(total * 100) / 100
document.getElementsByClassName("cart-total-price")[0].innerText = "£" + total
}
So now I can change the quantity of the each item in my cart, and remove items if I want. When I change the quantity or remove items, my cart total updates.
In the final tutorial, I'll learn how to make the 'Add to cart' buttons work. These need to add an item to the cart when I click them.