I am currently writing a WhatsApp-Chat-Analyzer. Therefore, I have to loop through the chat's participants and create buttons each representing one participant. When creating those buttons parameters or variables have to be handed over to a function which then executes code that further processes the parameters/variables.
However, regardless of what I am trying, the function that is called when clicking the button does not use the right variable; it always uses the first one of the array which is used to loop-over in the for-loop.
At the same time, printing out the variables while creating the buttons does work properly - all the unique variables are printed out and not only the first one.
As far as I know, all this indicates that there is something wrong with the scopes.
Coming from Java, working with javascript variables is very confusing since some of them appear to be global even though they are declared within a function or a loop. That's why I have tried to enclose the function that is handed over to the dynamically created button. Sadly, setting up a function that returns another function and handing over the first function does not work although it actually should work.
Furthermore, I am aware of the fact that "let" should be used in this case instead of "var" to create a local variable.
The following code represents what I am doing and which solution I have tried so far.
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = className + "Hidden";
element.onclick = functionToExecute;
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
If the code worked properly every button should store the variable of the participant it represents. When pressed, the button should then execute the function "handleParticipant" using the variable that was handed over beforehand and print out the participant.
And last but not least; a live demonstration of the problem: https://jsfiddle.net/Muelli21/21cv7eja/
participantvariable ->variablevariable looks like it should take the right value. Do you have a JSFiddle or similar, or can you make a Stack Snippet that demonstrates the problem? (it'll be a lot easier to debug with something runnable)