Why i need to click twice to call my function - javascript

i need your help please, my function works but i need to click twice to call it. i tried a lot of options but never works fine (sorry for my english im french)
function deleteItem() {
let products = document.querySelectorAll(".deleteItem");
for (let product of products) {
product.addEventListener("click", (e) => {
let id = e.target.getAttribute("dataid");
let color = e.target.getAttribute("datacolor");
let deleteItem = basket.find(
(element) => element.id == id && element.color == color
);
console.log(deleteItem);
basket = basket.filter((item) => item != deleteItem);
localStorage.setItem("basket", JSON.stringify(basket)),
(window.location.href = "cart.html");
});
}
}
deleteItem();
<div class="cart__item__content__settings__delete">
<p class="deleteItem" onclick="deleteItem()" dataid="${id}" datacolor="${color}">Supprimer</p>
</div>

Testing your code, it works on first click.
dont use onclick and eventlistener together, as you will be capturing multiple clicks
This is not an answer, but working code.
function deleteItem() {
let products = document.querySelectorAll(".deleteItem");
for (let product of products) {
product.addEventListener("click", (e) => {
let id = e.target.getAttribute("dataid");
let color = e.target.getAttribute("datacolor");
alert("i am clicked")
});
}
}
deleteItem();
<div class="cart__item__content__settings__delete">
<p class="deleteItem" dataid="5" datacolor="blue">Supprimer</p>
</div>

Related

Close button popup doesn't work (JAVASCRIPT)

i'm trying to create a custom pupop in javascript, this is my first time with this.
I have a problem with the close button, the "x" target correctly the div to close, but doesn't remove the "active" class at click.
https://demomadeingenesi.it/demo-cedolino/
HTML CODE
<div class="spot spot-2">
<div class="pin"></div>
<div class="contenuto-spot flex flex-col gap-3">
<img class="chiudi-popup" src="img/chiudi.svg" />
[---CONTENT---]
</div>
</div>
</div>
JAVASCRIPT CODE
const tooltips = function () {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
const chiudiPopup = document.querySelector(".chiudi-popup");
spot.classList.add("active");
contenuto.classList.add("show");
if (curActive && curActive !== spot) {
curActive.classList.toggle("active");
contActive.classList.toggle("show");
}
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
});
});
const chiudiPopup = document.querySelector(".chiudi-popup");
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
What the code above does is adding an click listener, but it's inside another click listener, so all it's doing is adding an click listener on the first .chiudi-popup that removes .active and .show from the last spot element.
It's hard to see if this is correct, because you haven't given us enough to reproduce the problem, but I moved the code above outside the spot.addEventListener("click", () => { and instead of searching the whole document with const chiudiPopup = document.querySelector(".chiudi-popup"); the code nows only targets the .chuidi-popup element within the spot: const chiudiPopup = spot.querySelector(".chiudi-popup");
const tooltips = function() {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
spot.classList.add("active");
contenuto.classList.add("show");
if (curActive && curActive !== spot) {
curActive.classList.toggle("active");
contActive.classList.toggle("show");
}
});
// MOVED FROM THE CLICK LISTENER
const chiudiPopup = spot.querySelector(".chiudi-popup");
chiudiPopup.addEventListener("click", () => {
spot.classList.remove("active");
contenuto.classList.remove("show");
});
});
EDIT: I missed that you have the img.chiudi-popup inside your container, which will trigger both event listeners. I would honestly just simplify the code and always hide the container when clicking on it again. You can still have the img.chiudi-popup (close image) to make it easier for the users to understand that they can click on it.
const tooltips = function() {
const spots = document.querySelectorAll(".spot");
spots.forEach((spot) => {
const contenuto = spot.querySelector(".contenuto-spot");
const pin = spot.querySelector(".pin");
spot.addEventListener("click", () => {
let curActive = document.querySelector(".spot.active");
let contActive = document.querySelector(".contenuto-spot.show");
if (curActive !== spot) {
spot.classList.add("active");
contenuto.classList.add("show");
}
if (curActive) {
curActive.classList.remove("active");
contActive.classList.remove("show");
}
});

how to stop function in js?

I have a form that counts when a button (button.clicked in the example below) is clicked. I want to make it operate in two modes: one keeps counting with every click, the other has a timer (started with the click of another button, button.start) that will disable the click-count button when the timer runs out. Each mode is chosen by clicking a button (button.menu-timer and button.menu-clicks). When the count mode is selected, one function (cc) is called. When switched to the timer mode, another function (tt) should be called and the first function should stop.
If I click one mode button, then everything works as it should, but if after that I click the other mode button, both functions continue to operate; each click of button.click adds two to the count. Moreover, if you click the mode buttons several times, clicking the count button will increase the counter many times, rather than only once.
I searched for solutions on the Internet and found one based on return; I tried to use return in various ways but couldn't get it to work.
I need that when choosing the right mode, only the desired function works. And so that when you click several times on one mode, the function will run once.
The following snippet is also available on CodePen.
let clicker = document.querySelector(".click");
let start = document.querySelector(".start");
let clickerValue = document.querySelector(".click").value;
const reset = document.querySelector(".reset");
const menuTimer = document.querySelector(".menu-timer");
const menuClicks = document.querySelector(".menu-clicks");
const times = document.querySelectorAll(".time");
let i = 0;
let y;
let tf;
let timer = 15;
function tt(tf) {
if (tf ===2) {
return;
}
start.addEventListener("click", () => {
start.style.zIndex = "-1";
y = setInterval(() => {
if (i === timer) {
clicker.setAttribute("disabled", "");
} else {
i++;
}
}, 1000);
});
clicker.addEventListener("click", () => {
clicker.textContent = clickerValue++;
});
reset.addEventListener("click", resetF);
}
function cc(tf) {
if (tf = 1) {
return;
}
start.addEventListener("click", () => {
console.log("111111");
start.style.zIndex = "-1";
});
clicker.addEventListener("click", () => {
clicker.textContent = `a ${clickerValue++}`;
});
reset.addEventListener("click", resetF);
}
function resetF() {
clearInterval(y);
i = 0;
start.style.zIndex = "2";
clickerValue = 0;
clicker.textContent = clickerValue;
clicker.removeAttribute("disabled", "");
}
menuTimer.addEventListener("click", function () {
menuTimer.classList.add("active");
menuClicks.classList.remove("active");
tt(1);
resetF();
});
menuClicks.addEventListener("click", function () {
menuClicks.classList.add("active");
menuTimer.classList.remove("active");
cc(2)
resetF();
});
<div class="menu">
<button type="button" onclick="tf = 1" class="menu-timer">TIMER</button>
<button type="button" onclick="tf = 2" class="menu-clicks">CLICKS</button>
</div>
<div class="click-btn">
<button class="click" type="button">0</button>
<button class="start" type="button">START</button>
</div>
<button class="reset" type="button">Reset</button>
You have a typo with assigning = instead of equality operator ===
function cc(tf) {
if (tf = 1) { // should be ===
return;
}
...
}
Also before you addEventListener('click', ...), a good practice is to remove previous click listeners with removeEventListener('click')

how to fetch a new image from api after one click vanilla.js

I'm trying to figure out a better way to fetch a new image when clicking my button.
here is my code:
function getPizzaHtml(pizza) {
return `
<div class="header">Random Pizzas 🍕</div>
<button id="show-pizza-btn">Click Me</button>
<div class="pizza-image">
<img class="pizza-images" style="display: none" src="${pizza.image}"/>
</div>
`
}
getPizzaImg().then(pizza => {
console.log(pizza)
document.body.innerHTML = getPizzaHtml(pizza);
let pizzaBtn = document.getElementById('show-pizza-btn');
pizzaBtn.addEventListener('click', (e) => {
let pizzaImg = document.querySelector('.pizza-images');
if(pizzaImg.style.display === 'none') {
pizzaImg.style.display = 'inline'
} else {
window.location.reload();
}
})
})
with the if-statement, I can fetch a new image since it reloads the page and so reloads the fetch. But, in order for it to appear, I have to click it twice.
I appreciate all advice and help!
You can change pizzaImg.src to change the image. You can change your event listener to something like this:
pizzaBtn.addEventListener('click', (e) => {
let pizzaImg = document.querySelector('.pizza-images');
if(pizzaImg.style.display === 'none') {
pizzaImg.style.display = 'inline'
} else {
getPizzaImg().then(newPizza => pizzaImg.src = newPizza.image)
}
})

How to use a button to delete a "to do" list item that was added through javascript

I'm adding trying create a delete button to delete the corresponding list item. I've tried trying to make a for loop to iterate through the list items but there are no items to begin with, so no array to iterate through. not sure if my logic is right here or I'm overlooking something.
This is my code, what do I need to do to make the delete button work?
<div class="container">
<h1>TO DO LIST</h1>
<form id="taskForm">
<input id="taskInput"></input>
<button type="button" id="taskButton">Click Here</button>
</form>
<ul id="taskLister"></ul>
</div>
<script>
let button = document.getElementById("taskButton");
button.addEventListener('click', () => taskList());
function taskList() {
let item = document.getElementById("taskInput").value;
let newTask = document.createElement("li");
let deleteTaskButton = document.createElement("button");
deleteTaskButton.innertext = item;
newTask.innerText = item;
document.getElementById("taskLister").appendChild(newTask);
document.getElementById("taskLister").appendChild(deleteTaskButton);
if(markTaskComplete) {
newTask.addEventListener('click', (e) => markTaskComplete(e));
deleteTaskButton.addEventListener('click', (i) => removeTask(i));
}
}
function markTaskComplete(e) {
let strikeThrough = e.target;
strikeThrough.style.textDecoration = "line-through";
}
function removeTask(i) {
let deleteTask = i.target;
deleteTask.parentNode.removeChild(li);
}
You are close, you just need to make a couple of changes to get it to work:
Add the deleteTaskButton as a child of the newTask list item. You are adding it as a sibling, but if we make it a child then this associates it directly with the li element, so we can easily find the li you want to delete:
function taskList() {
[...]
document.getElementById("taskLister").appendChild(newTask);
newTask.appendChild(deleteTaskButton); // 1. add to the new task li
[...]
}
Now in your removeTask function, the clicked button that gets passed in is a child of the li you have chosen to delete, so you just need to get its parent element and remove it:
function removeTask(i) {
let deleteTask = i.target.parentElement;
deleteTask.remove();
}
That's all you need!
Working Example:
let button = document.getElementById("taskButton");
button.addEventListener('click', () => taskList());
function taskList() {
let item = document.getElementById("taskInput").value;
let newTask = document.createElement("li");
let deleteTaskButton = document.createElement("button");
deleteTaskButton.textContent = "Delete "+item;
newTask.innerText = item;
document.getElementById("taskLister").appendChild(newTask);
newTask.appendChild(deleteTaskButton); /* 1. ADD BUTTON TO LI */
if (markTaskComplete) {
newTask.addEventListener('click', (e) => markTaskComplete(e));
deleteTaskButton.addEventListener('click', (i) => removeTask(i));
}
}
function markTaskComplete(e) {
let strikeThrough = e.target;
strikeThrough.style.textDecoration = "line-through";
}
function removeTask(i) {
/* 2. THE BUTTON IS NOW A CHILD OF THE LI, SO DELETE ITS PARENT */
let deleteTask = i.target.parentElement;
deleteTask.remove();
}
<div class="container">
<h1>TO DO LIST</h1>
<form id="taskForm">
<input id="taskInput"></input>
<button type="button" id="taskButton">Click Here</button>
</form>
<ul id="taskLister"></ul>
</div>
Also FYI, to add the text to a button, you use textContent instead of innertext, e.g.
deleteTaskButton.textContent = "Delete "+item;

How to alert when element in a list is clicked?

function whatami(img){
console.log(img.key);
}
let animals = ["frog","frog","sheep","sheep","snail","snail","mouse","mouse","bat","bat","walrus",
"walrus","giraffe","giraffe","zebra","zebra","dog","dog","octopus","octopus","hippo",
"hippo","camel","camel","pig","pig","rhino","rhino","rooster","rooster","panda","panda",
"turtle","turtle","raccoon","raccoon","polar bear","polar bear","lion","lion","bison",
"bison","orca","orca","snake","snake","shark","shark","toucan","toucan","butterfly",
"butterfly","anteater","anteater","seal","seal","armadillo","armadillo","rooster","rooster"]
var array = shuffle(animals);
let images = array.map(image => {
return <img onClick = {whatami(image)} key={image} src={"/animalgameback.jpg"} alt="" className="img-responsive"/>
});
return (
<div>
<div>
{images}
</div>
</div>
)
}
}
I have this list of images and I need a way to find which one is clicked when I press one of them. How do I do this?
The click must receive a callback function. Try writing the onClick with a arrow function like this
onClick = { () => { whatami(image)} }
I would write ()=>{whatami(image)} instead of whatami(image). LEt me know if it works.

Categories

Resources