This is a problem that I’m unable to solve. I have a solution, but the variable flag is a global variable.
The problem is under the constraint that flag can’t be global.
Essentially, we press on either ‘jQuery’ or ‘JS Mode’ buttons first and then press ‘Collapse Me’ button in order to execute a collapsible menu.
Each button is supposed to simulate the same functionality but with different code.
For now, I didn’t use jQuery, so pretend that it is.
The code is straightforward enough, but, again, I need a solution where flag is passed on to the third addEvenListener without being global.
let coll = document.getElementsByClassName("collapsible");
let jsBtn = document.getElementById("jsBtn");
let jqBtn = document.getElementById("jqueryBtn");
let flag = null;
jsBtn.addEventListener("click", () => {
flag = "js";
});
jqBtn.addEventListener("click", () => {
flag = "jq";
});
coll[0].addEventListener("click", nestedColl);
function nestedColl() {
console.log(flag);
if (flag == "js") {
collJs(flag);
} else if (flag == "jq") {
pseudoJq(flag);
}
}
function collJs(flag) {
console.log(flag + "collJS");
var content = coll[0].nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
}
function pseudoJq(flag) {
console.log(flag + "pseudoJq");
var content = coll[0].nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
}
.content,
.content1 {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
<button id="jsBtn">JS Mode</button>
<button id="jqueryBtn">jQuery Mode</button>
<button class="collapsible">Collapse Me</button>
<div class="content">
<p>
filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler text. filler
text. filler text. filler text. filler text. filler text. filler text. filler.
</p>
</div>
What did I try and what was I expecting? I wrapped the third addEventListener in a function and the other addEventListeners would call that function to pass on flag. But then the event doesn’t work correctly.
Code that doesn’t work but why?
jsBtn.addEventListener("click", () => {
collFun(flag = "js");
});
jqBtn.addEventListener("click", () => {
collFun(flag = "jq");
});
function collFun() {
console.log(flag);
coll[0].addEventListener("click", nestedColl);
function nestedColl() {
console.log(flag);
if (flag == "js") {
collJs(flag);
} else if (flag == "jq") {
pseudoJq(flag);
}
}
}
4
Answers
You can have each mode button change which function is used as the click listener on the "Collapse me" button, using
removeEventListener()
.you can also add a property to you content element, like so:
Use the
event
that gets passed.event.target
tells you which element triggered the action. You can then read properties of that element.Instead of multiple functions, I’m delegating the click handler to the body.
For the buttons, I add a data attribute to jQuery and Javascript. This will hold each of their representative modes.
I also add a data attribute for flag to the collapse button. This will hold the flag for whatever was clicked on.
Then I use one function for expanding/collapsing. I also attach an active class for future use and to hide expanded content.