I have a page that has a number of divs on it and I am writing a function that loops over all of them, assigns them a random ID and attaches some event listeners to each. However, I am getting the problem outlined above when I check my code using JSHint. I have looked at other threads for this issue, but I do not fully understand how to apply the answers from there in my code. Below is a section that is relevant to this warning:
//global variables
var buttons = document.getElementsByClassName("btn");
var firstClick = 1; //set firstClick flag to 1 on load
var buttonIDs = [];
var clickedButtonID = null;
var clickedButtonColour = null;
var clickedButtonTitle = null;
function addListenersToAllBtns() {
//loop over all buttons on page, assign them unique IDs and attach their EventListeners
for (let i = 0; i < buttons.length; i++) {
let btn_id = guidGenerator();
buttonIDs[i] = btn_id;
buttons[i].setAttribute("id", btn_id);
//add to child node to only have the left side of the button clickable
buttons[i].childNodes[1].addEventListener("click", function () {
//save button information
clickedButtonID = btn_id;
clickedButtonTitle = buttons[i].childNodes[1].childNodes[1].innerHTML;
//button class format is ".btn colour"
clickedButtonColour = buttons[i].getAttribute("class").split(" ")[1];
console.log("The ID of the clicked button is: ", clickedButtonID, "\n",
'The colour of the clicked button is ', clickedButtonColour);
if (firstClick == 1) {
firstClick = 0;
window.addEventListener("resize", positionHabitCard);
document.addEventListener('DOMContentLoaded', positionHabitCard, false);
}
});
buttons[i].childNodes[1].addEventListener("click", showHabitCard);
}
}
I have tried taking the function definition outside the for loop like below and passing it to addEventListener but then it cannot access buttons[i] and has issues with btn_id (says it is undefined).
function getButtonData() {
//save button information
clickedButtonID = btn_id;
clickedButtonTitle = buttons[i].childNodes[1].childNodes[1].innerHTML;
//button class format is ".btn colour"
clickedButtonColour = buttons[i].getAttribute("class").split(" ")[1];
console.log("The ID of the clicked button is: ", clickedButtonID, "\n",
'The colour of the clicked button is ', clickedButtonColour);
if (firstClick == 1) {
firstClick = 0;
window.addEventListener("resize", positionHabitCard);
document.addEventListener('DOMContentLoaded', positionHabitCard, false);
}
}
Could someone more experienced take a look at this and help me out? I am very much a newbie when it comes to JS, so please excuse any glaring errors I may have missed.
Thank you very much in advance.
It's a warning, not an error. I can't really say it's an accurate warning though.
First of all, it's only really "confusing" if you are still using
vardeclarations inside a loop.vardeclarations are only local tofunctions and the global scope. So there's no such thing as avardeclaration for any loop. You can place avardeclaration inside a loop but that won't create multiple variables of it. Instead any reference down the line (say like in a function body) will reference the one and only variable created by the declaration inside the loop.That can be confusing because any one reference can update the variable. So, the first function created by the first iteration could alter a variable that is being used by every other function inside the loop.
With ES6 you have
letandconstwhich introduce block scope which also works within loops. That means a declaration inside a loop that iteratesntimes can createnvariables and each reference inside the block will only apply to that iteration.You are using
letdeclarations inside the loop so you don't really have a problem there. However, if you were to changelet iforvar iorlet btn_idforvar btn_idyou'd would see that all your functions created in the loop apply the logic for the last button. That is because every iteration would alteriandbtn_id(as there would only be one variable per each across all functions).