Foreach of my "categories" collection document's (5), i'm displaying a button. And i would like when I click on my button it change the value of my document "active" field to "yes" or "no" depending of the old value.
This is what I tried :
db.collection("categories").orderBy("id", "asc").onSnapshot(snapshot =>
{
let changes = snapshot.docChanges();
changes.forEach(change =>
{
if (change.type == "added" || change.type == "removed")
{
renderNavItems(change.doc);
renderTab(change.doc);
renderButtons(change.doc);
}
else if(change.type == "modified")
{
buttonFc(change.doc);
}
})
});
RenderButtons() Function : (Only one time)
var buttons;
var button;
var buttonDiv;
function renderButtons(doc)
{
button = document.createElement("button");
buttonDiv = document.createElement("div");
buttonDiv.setAttribute("class","btnDiv"+doc.data().id);
if (doc.data().active == "yes")
{
button.setAttribute("class", "btn btn-success btn-sm btnView");
button.textContent= "Slide activée";
}
else if (doc.data().active == "no")
{
button.setAttribute("class", "btn btn-danger btn-sm btnView");
button.textContent= "Slide desactivée";
}
buttonDiv.appendChild(button);
var tab = document.querySelector("#"+doc.data().name);
tab.appendChild(buttonDiv);
buttonFc(doc);
}
buttonFc() function : (Each time, the value of my field change)
function buttonFc(doc)
{
DocRef = db.collection("categories").doc(doc.id);
if (doc.data().active == "yes")
{
button.addEventListener('click', () =>
{
console.log("YES TO NO");
DocRef.update({
"active": "no"
})
});
}
else if (doc.data().active == "no")
{
button.addEventListener('click', () =>
{
console.log("NO TO YES");
DocRef.update({
"active": "yes"
})
});
}
But, when I click on a button, my functions loops and each time loop is bigger.
When I click 5 time :
The buttonFc() function adds a new eventlistener for each time it is called, so you end up with multiple eventlisteners on the same button. This explains why the loop gets 'bigger' each time.
Make sure you add eventlisteners only once.
Related
I have a javascript code where I store an element in an array upon clicking on a button, and change the button from "+" to "-". Upon clicking the button again, I want to remove that element from the array.
I have this code. It does the first part well, but it also removes the element without clicking on the button the second time.
let favorites = []
let buttonList = document.querySelectorAll("button")
let click = 0
buttonList.forEach((button, index) => {
button.addEventListener('click', function saveFavourites() {
click++
favorites.push(products[index])
button.textContent = "-"
console.log(favorites)
if (click === 1) {
this.removeEventListener('click', saveFavourites)
}
})
button.addEventListener('click', function removeFavourites() {
click ++
let i = favorites.indexOf(products[index])
favorites.splice(i, 1)
button.textContent = "+"
console.log(favorites)
if (click === 2) {
this.removeEventListener('click', removeFavourites)
}
})
})
You're adding two separate event listeners to the same button element. Use a single event listener and toggle a boolean flag variable to keep track of whether the element should be added or removed.
let favorites = []
let buttonList = document.querySelectorAll("button")
buttonList.forEach((button, index) => {
let isAdded = false; // flag variable to track whether the element is added or removed
button.addEventListener('click', function toggleFavourites() {
if (isAdded) {
let i = favorites.indexOf(products[index])
favorites.splice(i, 1)
button.textContent = "+"
isAdded = false;
} else {
favorites.push(products[index])
button.textContent = "-"
isAdded = true;
}
console.log(favorites)
})
})
When the button is clicked, the code checks the value of isAdded and either adds the element to the favorites array or removes it.
Here is the Demo:- Codesandbox
I have to change shapes by clicking on the button on web page .So for that I I made multiple id's so for every click of the button current id gets changed into another id and shape changes. every id has properties of a particular shape.
var shapeBtn = document.getElementById("cng_shape");
shapeBtn.onclick = () => {
if (document.getElementById("shape").id == "shape") {
document.getElementById("shape").id = "shape1";
// document.getElementById("shape").setAttribute("id","shape1");
//
} else if (document.getElementById("shape1").id == "shape1") {
document.getElementById("shape1").setAttribute("id", "shape3");
} else if (document.getElementById("shape3").id == "shape3") {
document.getElementById("shape3").setAttribute("id", "shape");
}
};
I tried using if statements and check whether the current id is true and it its true change its id to new one.
try below code , also need to check if id is exist like below,
var shapeBtn = document.getElementById("cng_shape");
shapeBtn.onclick = () => {
if ( document.getElementById("shape") && document.getElementById("shape").id == "shape") {
document.getElementById("shape").id = "shape1";
// document.getElementById("shape").setAttribute("id","shape1");
//
} else if ( document.getElementById("shape1") && document.getElementById("shape1").id == "shape1") {
document.getElementById("shape1").setAttribute("id", "shape3");
} else if ( document.getElementById("shape3") && document.getElementById("shape3").id == "shape3") {
document.getElementById("shape3").setAttribute("id", "shape");
}
};
<div id="shape">test</div>
<input type="button" id="cng_shape" value="click" />
I have a masterFunction which should fire another function called reset when the AC button on my calculator is pressed (picked up via e.target.id = "AC").
However it's not firing, in fact no functions are firing when I press the AC button.
I've added a console log and can see e.target.id = "AC" yet it still won't fire.
Reduced code:
//Update display with button clicked
buttonGrid.addEventListener('click', e => {
console.log(e.target.id);
masterFunction(e);
});
//Fire relevant function depending on the button pressed etc
let masterFunction = (e) => {
if (e.target.id === "AC") {
reset(e);
}
};
// Reset the screen
let reset = (e) => {
secondNumberCounter = false;
operatorPressed = false;
firstNumber = 0;
secondNumber = 0;
buttonNumber = 0;
decimalCounter = 0;
displayArea.textContent = 0;
};
Can anyone see what I'm doing wrong?
https://jsfiddle.net/2s9nuLj0/5/
Because your first if condition is eating up the clicks. Basic debugging will show your problem.
console.log('BEFORE THE IFS');
if (operatorPressed === false && firstNumberCounter === true && e.target.dataset.type != "nonNumberFunction") {
console.log('I AM HERE!!!!')
firstNumberPicker(e);
}
and you should stop the default action of the clicks
buttonGrid.addEventListener('click', e => {
masterFunction(e);
e.preventDefault();
});
I created a click event that opens a previously 'hidden' div and closes it again once you click the same button.
However, it only runs once (one open and one close) - I'm at a loss to explain why it doesn't work if I click it again.
let readMore = document.getElementById('clickAbout');
let moreInfo = document.getElementById('about');
let changeSepa = document.getElementById('sepChange');
readMore.addEventListener('click', function(){
changeSepa.style.height = '2rem';
if (moreInfo.className == "") {
moreInfo.className = "open";
moreInfo.style.display = 'block';
} else {
moreInfo.style.display = 'none';
}
});
this happens because you're checking if className == "", but you are modifying the className to be "open". On the second click it checks the className which is now "open" and goes to the else block. On the third click you expect for it to go into the first block but the className is still "open".
For an easy fix just change the className in the else block
else {
moreInfo.className = "";
moreInfo.style.display = 'none';
}
Also i suggest you make use of the classList property on elements
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
using the class list it could look like this:
readMore.addEventListener("click", function () {
changeSepa.style.height = "2rem";
if (moreInfo.className == "") {
moreInfo.classList.add("open");
moreInfo.style.display = "block";
} else {
moreInfo.classList.remove("open");
moreInfo.style.display = "none";
}
});
Or even
readMore.addEventListener("click", function () {
changeSepa.style.height = "2rem";
moreInfo.classList.toggle("open");
if (moreInfo.className == "") {
moreInfo.style.display = "block";
} else {
moreInfo.style.display = "none";
}
});
I’m new to Js.. and I’m trying to change the inner Text of a button to toggle on click between On and Off using addEventListener method.
const btn = document.getElementsByClassName("btn")[0];
const btn2 = document.createTextNode("Off");
btn.addEventListener.toggle("click", modifiedText() {
// enter code here
});
ModifiedText() {
// enter code here
}
<button class=“btn”>On</button>
Just addEventListener on button and get or set the text inside button using textContent property.
const button = document.querySelector(".btn");
button.addEventListener("click", function clickHandler( e ) {
const btnText = e.target.textContent;
if( btnText.toLowerCase() === "on") e.target.textContent = "Off";
else e.target.textContent = "On"
})
<button class="btn">On</button>