I'm currently working on an e-commerce site and I'm stuck on the search page, especially when filtering the products.
**
This is the HTML code for the product card:**
<div class="product-seller-item" data-brand="Louis Vuitton" data-category="Helmets">
<div class="product-page-seller-item-header">
<img src="/Images/user.png" alt="User profile image">
<p>citygirl1996</p>
</div>
<img class="product-page-seller-item-body-image" src="/Images/Products/product1.png" alt="">
<div class="product-page-seller-item-footer">
<div class="product-page-seller-item-footer-flex">
<p>£15.00</p>
</div>
<p class="product-page-seller-item-footer-description">Juicy Couture</p>
</div>
</div>
And this is the code for the checkbox:
<label class="container">Helmets
<input type="checkbox" value="Helmets">
<span class="checkmark"></span>
</label>
<label class="container">Louis Vuitton
<input type="checkbox" value="Louis Vuitton">
<span class="checkmark"></span>
</label>
And this is the code for JavaScript:
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
const products = document.querySelectorAll('.product-seller-item');
for (let i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function () {
for (let j = 0; j < products.length; j++) {
let productVisible = false;
for (let k = 0; k < checkboxes.length; k++) {
if (checkboxes[k].checked && products[j].dataset.category === checkboxes[k].value) {
productVisible = true;
break;
} else if (checkboxes[k].checked && products[j].dataset.brand
&& products[j].dataset.brand === checkboxes[k].parentElement.textContent.trim()) {
productVisible = true;
break;
}
}
if (productVisible) {
products[j].style.display = 'block';
} else {
products[j].style.display = 'none';
}
}
});
}
The problem is as follows, when I select the Helmets category, it shows me all of them, everything works perfectly, but when I select the brand, it doesn't hide the product that doesn't match.
If the products have a category you can use filtermethod, that will return you a new array with the elements that have this conditions. For example:
const products = document.querySelectorAll('.products'):
const categories = document.querySelectorAll('input[type=checkbox]');
const filteredProducts
= products.filter(product => product.category == categories.checked);
I am building an eCommerce store website, and I am facing an issue. The function updateCartTotal doesn't work at all. The script is also added to the bottom of the HTML body.
Thanks in advance.
HTML:
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>
Javascript:
let cartIcon = document.getElementById("cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
var removeCartButtons = document.getElementsByClassName("material-symbols-outlined");
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem)
}
// Quantity Change //
var quantitInputs = document.getElementsByClassName("cart qty");
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
quantityChanged = (event) => {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
}
function updateCartTotal() {
var cartContainer = document.getElementsByClassName("cart-content")[0];
var cartBox = cartContainer.getElementsByClassName("cart-box");
var total = 0
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
var priceElement = cartBox.getElementsByClassName("cart-price")[0]
var quantityElement = cartBox.getElementsByClassName("cart-qty")[0]
price = parseFloat(priceElement.innerText.replace("£", ""))
quantity = quantityElement.value
total = total + (price * quantity)
}
document.getElementsByClassName("total-price")[0].innerText = total
}
i am expecting the total to update as the quantity changes, and the function to work
You have the following mistakes-
There is no element with the class name cart qty.
var quantitInputs = document.getElementsByClassName("cart qty");
quantityChanged function should have a function keyword.
You are using the same name variable cartBox in updateCartTotal function which is creating confusion-
var cartBox = cartContainer.getElementsByClassName("cart-box");
for (var i = 0; i < cartBox.length; i++) {
var cartBox = cartBox[i]
}
Now, after fixing these mistakes, your code will look like the below which is working.
Note- I moved all the declarations to the top and I replaced those two methods-
getElementsByClassName() = querySelectorAll()
getElementsByClassName()[0] = querySelector()
let cartIcon = document.querySelector("#cart-icon");
let cart = document.querySelector(".cart");
let CloseCart = document.querySelector("#close-cart");
var quantitInputs = document.querySelectorAll(".cart-qty");
var removeCartButtons = document.querySelectorAll(".material-symbols-outlined");
var cartContainer = document.querySelector(".cart-content");
var cartBox = cartContainer.querySelectorAll(".cart-box");
var totalEl = document.querySelector(".total-price")
cartIcon.onclick = () => {
cart.classList.add("active");
};
CloseCart.onclick = () => {
cart.classList.remove("active");
};
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", ready);
} else {
ready();
}
function ready() {
for (var i = 0; i < removeCartButtons.length; i++) {
var button = removeCartButtons[i];
button.addEventListener("click", removeCartItem);
}
// Quantity Change //
for (var i = 0; i < quantitInputs.length; i++) {
var input = quantitInputs[i];
input.addEventListener("change", quantityChanged);
}
}
function removeCartItem(event) {
var buttonClicked = event.target;
buttonClicked.parentElement.remove();
updateCartTotal();
}
function quantityChanged(event) {
var input = event.target;
if (isNaN(input.value) || input.value <= 0) {
input.value = 1;
}
updateCartTotal();
};
function updateCartTotal() {
var total = 0;
for (var i = 0; i < cartBox.length; i++) {
var cartBoxEl = cartBox[i];
var priceElement = cartBoxEl.querySelector(".cart-price");
var quantityElement = cartBoxEl.querySelector(".cart-qty");
price = parseFloat(priceElement.innerText.replace("£", ""));
quantity = quantityElement.value;
total = total + price * quantity;
}
if (totalEl) {
totalEl.innerText = total;
}
}
<div>
<span class="material-symbols-outlined" id="cart-icon">
shopping_cart
</span>
<div class="cart">
<h2 class="cart-title">Your Shopping Cart</h2>
<div class="cart-content">
<div class="cart-box">
<img src="/Monn-Homme/images/tie1.jpg" class="cart-image">
<div class="detail-box">
<div class="cart-product-title">
Tie
</div>
<div class="cart-price"> £10.99</div>
<input type="number" value="1" class="cart-qty">
</div>
<span class="material-symbols-outlined" id="cart-remove">
delete
</span>
</div>
</div>
<div class="total">
<div class="total-title">Total</div>
<div class="total-price">£10.99</div>
</div>
<button type="button" class="buy-btn">Buy Now</button>
<span class="material-symbols-outlined" id="close-cart">
close
</span>
</div>
</div>
The following code shows an alert box:
I want each box to be displayed by clicking on its own button
html
<button class="btn-alert btn-success" type="submit">delete</button>
<button class="btn-alert btn-success" type="submit">delete</button>
<button class="btn-alert btn-success" type="submit">delete</button>
<div class="alert-s col-4"></div>
<div class="alert-s col-4"></div>
<div class="alert-s col-4"></div>
<script>
const targetDiv = document.getElementById("alert");
const btn = document.getElementById("toggle");
function clickfn() {
for(let i = 0; i < targetDiv.length; i++) {
if (targetDiv.style.display = "none") {
targetDiv.style.display = "block";
} else {
targetDiv.style.display = "none";
}
}
};
</script>
can anyone help me to do so?
You can add a class to all your buttons, lets say toggle, then use javascript to call your function like:
var btns = document.getElementsByClassName('toggles');
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
alert("Finaly!");
}
}
you don't need the for loop as getElementById returns a single element.
If you want to show alert on both button click and don't want to write two separate codes give them a similar class name and query them that way using document.querySelectorAll(a dot class name in quotes).
<button class="btn">Button one</button>
<button class="btn">Button two</button>
<script>
const btns = document.querySelectorAll(".btn");
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = () => {
alert(`button ${i + 1} was clicked`);
};
}
</script>
I cannot add new Note after editing. How can I exit from the cycle?
This is a part where I create a new note
const createNote = () => {
if (button.className === "button") {
const div = document.createElement("div");
div.setAttribute("class", "note");
div.textContent = input.value;
field.appendChild(div);
const btn = document.createElement("button");
btn.setAttribute("class", "edit");
btn.textContent = "Edit";
div.appendChild(btn);
const del = document.createElement("button");
del.setAttribute("class", "del");
del.textContent = "Delete";
div.appendChild(del);
console.log("Note has been created");
input.value = "";
}
Here is a part where I want to edit created Note but also I want to create a new one (this part is inside function createNote)
const edit = document.querySelectorAll(".edit");
for (let i of edit) {
i.onclick = () => {
input.value = i.previousSibling.nodeValue;
button.innerText = "Edit";
button.classList.add("editable");
/*button.classList.remove("button");*/
if (button.className === "button editable") {
button.onclick = () => {
i.previousSibling.nodeValue = input.value;
input.value = "";
button.classList.remove("editable");
button.classList.add("button");
button.innerText = "Add";
};
}
};
}
};
button.onclick = createNote;
Here is HTML that I am using
<body>
<div class="container">
<div class="insert">
<input type="text" name="Note" id="noteId" placeholder="add note">
<button class="button">Add</button>
</div>
<div class="field">
<div class="note">Test note
<button class="edit">Edit</button>
<button class="del">Delete</button>
</div>
</div>
</div>
<script src="js/index.js"></script>
</body>
Trying to display different messages inside the p element for when someone clicks on one of the three buttons. But it only displays the first message (reply) for all the buttons.
Can't see what I have done wrong...
HTML
<div class="options">
<div id="good" class="btn"></div>
<div id="idk" class="btn"></div>
<div id="bad" class="btn"></div>
</div>
JavaScript
let good = document.getElementById("good");
let idk = document.getElementById("idk");
let bad = document.getElementById("bad");
let main = document.querySelector(".main");
let reply;
document.getElementById("good"), document.getElementById("idk"), document.getElementById("bad")].forEach(option => {
option.addEventListener("click", () => {
if (good.clicked = true) {
main.style.display = "block";
reply = "Hey";
} else if (idk.clicked = true) {
main.style.display = "block";
reply = "Well yeah";
} else if (bad.clicked = true) {
main.style.display = "block";
reply = "123";
}
document.getElementById("reply").innerHTML = reply;
});
});
const good = document.getElementById("good");
const idk = document.getElementById("idk");
const bad = document.getElementById("bad");
const main = document.querySelector(".main");
const reply = document.getElementById("reply");
const messageTypes = {
good: 'Hey',
idk: 'Well yeah',
bad: '123 BAD'
};
[good, idk, bad].forEach(option => {
option.addEventListener("click", (e) => {
reply.innerHTML = messageTypes[e.target.id];
});
});
<div class="options">
<button id="good" class="btn">good</button>
<button id="idk" class="btn">idk</button>
<button id="bad" class="btn">bad</button>
</div>
<div class="main"><div>
<div id="reply"></div>
Use const for everything, create a separate message dictionary for every message and just map it against the id. You don't need to use jQuery.
If your real use case is as simple as your example, I would consider maybe using different event listeners with different logic inside them. But if you want to use the same event listener, then you can use event.target.id to know which button was clicked:
[document.getElementById("good"), document.getElementById("idk"), document.getElementById("bad")].forEach(option => {
option.addEventListener("click", (event) => {
switch (event.target.id) {
case "good":
reply = "Hey";
break;
case "idk":
reply = "Well yeah";
break;
case "bad":
reply = "123";
break;
}
main.style.display = "block";
document.getElementById("reply").innerHTML = reply;
});
});
Here you can see it working (note that I removed main.style.display = "block"; in the following example since I don't know what main is in your original code):
[document.getElementById("good"), document.getElementById("idk"), document.getElementById("bad")].forEach(option => {
option.addEventListener("click", (event) => {
switch (event.target.id) {
case "good":
reply = "Hey";
break;
case "idk":
reply = "Well yeah";
break;
case "bad":
reply = "123";
break;
}
document.getElementById("reply").innerHTML = reply;
});
});
<div class="options">
<div id="good" class="btn">good</div>
<div id="idk" class="btn">idk</div>
<div id="bad" class="btn">bad</div>
</div>
<div id="reply"/>
It could be something like that:
let good = document.getElementById("good");
let idk = document.getElementById("idk");
let bad = document.getElementById("bad");
let main = document.querySelector(".main");
let reply;
[good, idk, bad].forEach(option => {
option.addEventListener("click", (e) => {
if (e.target == good) {
main.style.display = "block";
reply = "Hey";
} else if (e.target == idk) {
main.style.display = "block";
reply = "Well yeah";
} else if (e.target == bad) {
main.style.display = "block";
reply = "123";
}
document.getElementById("reply").innerHTML = reply;
});
});
<div class="options">
<div id="good" class="btn">good</div>
<div id="idk" class="btn">idk</div>
<div id="bad" class="btn">bad</div>
</div>
<div class="main"><div>
<div id="reply"></div>
I'd be tempted to use explicit event handlers for each of the buttons rather than a generic handler that then tests all three conditions.
You can reduce the code duplication by using a function to handle the display update of the main element and the setting of reply.
Something like the following shows this in action:
let good = document.getElementById("good");
let idk = document.getElementById("idk");
let bad = document.getElementById("bad");
let main = document.querySelector(".main");
good.addEventListener("click", function(e) {
showMain("Good");
});
idk.addEventListener("click", function(e) {
showMain("Well yeah");
});
bad.addEventListener("click", function(e) {
showMain("123");
});
function showMain(replyText) {
main.style.display = "block";
document.getElementById("reply").innerHTML = replyText;
}
.main {
background-color: red;
display: none;
height: 100px;
width: 100px;
}
<button id="good">Good</button>
<button id="idk">Idk</button>
<button id="bad">Bad</button>
<div class="main"></div>
<div id="reply"></div>
You can instead, do something like this for what you want
In Pure VanillaJS
[document.getElementById("good"), document.getElementById("idk"), document.getElementById("bad")].forEach(option => {
option.addEventListener("click", (event) => {
if (event.target.id == "good") {
main.style.display = "block";
reply = "Hey";
} else if (event.target.id == "idk") {
main.style.display = "block";
reply = "Well yeah";
} else if (event.target.id == "bad") {
main.style.display = "block";
reply = "123";
}
document.getElementById("reply").innerHTML = reply;
});
});
= is used for assignments however == is used to check equality of two strings in javascript
[] ...addEventListener("click", (e) => {
if (good.id == e.target.id) {
main.style.display = "block";
reply = "Hey";
}
// and so on
document.getElementById("reply").innerHTML = reply;
});
var btn1=document.getElementById('btn1')
var btn2=document.getElementById('btn2')
var btn3=document.getElementById('btn3')
// jquery way
$('.btn').on("click",function(e){
$("#msg").html(e.target.id+" clicked");
})
// javascript way
var classname = document.getElementsByClassName("btn");
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener("click", function(e){
document.getElementById('msg').innerHTML =e.target.id+' clicked';
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<input type="button" id="btn1" class="btn" value="button 1">
<input type="button" id="btn2" class="btn" value="button 2">
<input type="button" id="btn3" class="btn" value="button 3">
<p id="msg"></p>