Last active
October 23, 2022 15:32
-
-
Save caprosset/648f01347377f65feeb0d7a2a8d78d02 to your computer and use it in GitHub Desktop.
LAB solution - M1 | DOM Ironhack Cart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<meta name="viewport" content="width=device-width" /> | |
<link rel="stylesheet" href="./css/style.css" /> | |
<title>Ironhack Cart</title> | |
</head> | |
<body> | |
<h1>Ironhack Cart</h1> | |
<table id="cart"> | |
<thead> | |
<tr> | |
<th>Product Name</th> | |
<th>Unit Price</th> | |
<th>Quantity</th> | |
<th>Subtotal</th> | |
<th>Action</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr class="product"> | |
<td class="name"> | |
<span>Ironhack Rubber Duck</span> | |
</td> | |
<td class="price">$<span>25.00</span></td> | |
<td class="quantity"> | |
<input type="number" value="0" min="0" placeholder="Quantity" /> | |
</td> | |
<td class="subtotal">$<span>0</span></td> | |
<td class="action"> | |
<button class="btn btn-remove">Remove</button> | |
</td> | |
</tr> | |
<!-- Iteration 2: Add more products here --> | |
<tr class="product"> | |
<td class="name"> | |
<span>Ironhack Shirt</span> | |
</td> | |
<td class="price">$<span>15.00</span></td> | |
<td class="quantity"> | |
<input type="number" value="0" min="0" placeholder="Quantity" /> | |
</td> | |
<td class="subtotal">$<span>0</span></td> | |
<td class="action"> | |
<button class="btn btn-remove">Remove</button> | |
</td> | |
</tr> | |
</tbody> | |
<tfoot> | |
<!-- Iteration 5: Create new product --> | |
<tr class="create-product"> | |
<td> | |
<input type="text" placeholder="Product Name" /> | |
</td> | |
<td> | |
<input type="number" min="0" value="0" placeholder="Product Price" /> | |
</td> | |
<td></td> | |
<td></td> | |
<td> | |
<button id="create" class="btn">Create Product</button> | |
</td> | |
</tr> | |
</tfoot> | |
</table> | |
<p class="calculate-total"> | |
<button id="calculate" class="btn btn-success">Calculate Prices</button> | |
</p> | |
<h2 id="total-value">Total: $<span>0</span></h2> | |
<script type="text/javascript" src="./js/index.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// get the parent of the product rows (that we will reuse in different functions) | |
var cartElement = document.querySelector("#cart tbody"); | |
// ITERATION 1 | |
function updateSubtot(product) { | |
// Get DOM elements that hold price and quantity | |
const priceElement = product.querySelector(".price span"); | |
const qtyElement = product.querySelector(".quantity input"); | |
// Extract values from DOM elements | |
const price = Number(priceElement.innerHTML); // convert string into number | |
const qty = Number(qtyElement.value); // convert string into number | |
// Calculate subtotal value | |
const subtotal = price * qty; | |
// Get DOM element that holds the subtotal value for the product | |
const subtotalElement = product.querySelector(".subtotal span"); | |
// Set the product subtotal to the corresponding DOM element | |
subtotalElement.innerHTML = subtotal; | |
// Return subtotal value so it can be used later | |
return subtotal; | |
} | |
function calculateAll() { | |
// code in the following two lines is added just for testing purposes in iteration 1. | |
// const singleProduct = document.querySelector('.product'); | |
// updateSubtotal(singleProduct); | |
// end of test | |
// ITERATIONS 2 & 3 | |
// Get the DOM nodes for each product row | |
const productElements = document.querySelectorAll(".product"); // returns a Node List of product rows | |
// Declare an auxiliary variable that will hold the sum of each product subtotal | |
let totalPrice = 0; | |
// Iterate through the product nodes, | |
// call updateSubtot() on it and add the product subtotals to the total value | |
productElements.forEach(function(oneProduct) { | |
var productTotal = updateSubtot(oneProduct); // updates the subtotal element on each product row <tr> | |
totalPrice += productTotal; | |
}); | |
// Get DOM element that holds the cart total value | |
var totalPriceElement = document.querySelector("#total-value span"); | |
// Display the total value of products in cart in the appropriate node | |
totalPriceElement.textContent = totalPrice; | |
} | |
// ITERATION 4 | |
function removeProduct(event) { | |
const target = event.currentTarget; | |
console.log('The target in remove is:', target); | |
const productToRemove = target.parentNode.parentNode; | |
cartElement.removeChild(productToRemove); | |
calculateAll(); // calculates the new cart total, after product removal | |
} | |
// ITERATION 4 - Create a binding function that will allow us to easily bind the eventListener to any "Remove" button | |
function bindDeleteButton(deleteButton) { | |
deleteButton.addEventListener("click", removeProduct); | |
} | |
// ITERATION 5 | |
function createProduct() { | |
let nameElement = document.querySelector('.create-product input[type="text"]'); | |
let priceElement = document.querySelector('.create-product input[type="number"]'); | |
console.log(nameElement); | |
console.log(priceElement); | |
let newProductTr = document.createElement('tr'); // Create new tr element | |
newProductTr.setAttribute('class', 'product'); // same as => newProductTr.className = "product"; | |
// use innerHTML to create child elements inside <tr> | |
newProductTr.innerHTML = ` | |
<td class="name"> | |
<span>${nameElement.value}</span> | |
</td> | |
<td class="price">$<span>${priceElement.value}</span></td> | |
<td class="quantity"> | |
<input type="number" value="0" min="0" placeholder="Quantity" /> | |
</td> | |
<td class="subtotal">$<span>0</span></td> | |
<td class="action"> | |
<button class="btn btn-remove">Remove</button> | |
</td> | |
`; | |
// append the newly created row to the parent | |
cartElement.appendChild(newProductTr); | |
// make sure remove button inherits the same behavior as other remove buttons | |
var newRemoveButton = newProductTr.querySelector('.btn-remove'); | |
newRemoveButton.addEventListener('click', removeProduct); | |
// clean the fields | |
nameElement.value = ""; | |
priceElement.value = 0; | |
} | |
// this code is ran once, on page load | |
window.addEventListener('load', () => { | |
const calculatePricesBtn = document.getElementById('calculate'); | |
calculatePricesBtn.addEventListener('click', calculateAll); | |
// ITERATION 4 | |
const removeButtons = cart.getElementsByClassName('btn-remove'); // returns an HTML collection, needs to be spread into an array to iterate on it | |
[...removeButtons].forEach(button => button.addEventListener('click', removeProduct)); | |
// ITERATION 5 | |
const createButton = document.getElementById('create'); | |
if(createButton) { | |
createButton.addEventListener('click', createProduct); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment