Collapse Nav (Broken)

Here's my current code: https://codepen.io/Matt-CopOffMatt/pen/eYXJBpN Currently, I'm having issues with my functionality for collapsing by clicking outside of the menu. The following check:
menuChildren.forEach((child) => {
console.log(e.target, child)
if (e.target === child) {
console.log("Click outside of the menu")
} else {
checkbox.checked = false
menu.classList.remove('visible')
document.removeEventListener("click", checkMenu);
}
});
menuChildren.forEach((child) => {
console.log(e.target, child)
if (e.target === child) {
console.log("Click outside of the menu")
} else {
checkbox.checked = false
menu.classList.remove('visible')
document.removeEventListener("click", checkMenu);
}
});
Should loop through children and determine if the click is a child. If child is clicked, log (not execute the else). However, it seems as though the code is executing directly after calling the click event listener on document (which I assumed shouldn't work like this). What's the most optimal way of fixing this? Also, there's some weird glitch where it stutters when closing. What could be causing that? Thank you
33 Replies
Matt
MattOPβ€’12mo ago
I slowed down the animation for visual reference. I also added overflow: hidden; to the Menu. Still running into an issue where the content isn't fully collapsing -Fixed was caused because of default padding. -Might make more sense to transition with position rather than size
clevermissfox
clevermissfoxβ€’12mo ago
This is a bit of a mess. I've forked it and will rework it in a bit if no one else has gotten to it yet.
Matt
MattOPβ€’12mo ago
I'm still working on trying to get better with JS. I apologize. I just uploaded my updated version (still can't get the click outside box to work properly). I would typically do this with just regular CSS but it needs to be done with JS
Matt
MattOPβ€’12mo ago
Odd, checkbox.checked = false doesn't work, but checkbox.click() does. @hart❀πŸ”₯ Would you possibly give me your thoughts on my updated version? Took me a bit to get it to work
clevermissfox
clevermissfoxβ€’12mo ago
you will need to make it responsive for mobile but looks less messy. Im curious though, if youre toggling classes and using JS anyway, why still use the checkbox? thats mostly used to use css to try to hack this issue without JS. at this point your checkbox is making your JS more verbose than it needs to be.
Matt
MattOPβ€’12mo ago
I wasn't sure how to handle button clicks
clevermissfox
clevermissfoxβ€’12mo ago
this is doing the same thing with about 10 lines of JS. and the clickable elements are buttons so they can be interacted with for keyboard users as well. https://codepen.io/Miss-Fox/pen/XWGXREN?editors=0110
Matt
MattOPβ€’12mo ago
Ah actually, maybe I could just check if class is present This is missing clicking outside of menu to close
clevermissfox
clevermissfoxβ€’12mo ago
you didnt have that implemented in your code so i didnt include it. This was purely an example to show you that you have all the code you needed, you dont need to use a checkbox as its making it more verbose.
Matt
MattOPβ€’12mo ago
Yeah I do. And thank you for the feedback. I'll rework to use a button instead, using input isn't ideal
clevermissfox
clevermissfoxβ€’12mo ago
well then refactor your code to accomplish the same thing but more DRYly.
Matt
MattOPβ€’12mo ago
I honestly think I overthank this πŸ˜…
clevermissfox
clevermissfoxβ€’12mo ago
it happens
Matt
MattOPβ€’12mo ago
Would you happen to know why using a button isn't working?
Matt
MattOPβ€’12mo ago
It seems like the other click event listeners are automatically closing the menu (clicking button, .menu element seems to be changing but not adding a class)
Coder_Carl
Coder_Carlβ€’12mo ago
where exactly is '.menu-close-container' in your code?
Matt
MattOPβ€’12mo ago
<div class="menu-close-container">
<svg class="menu-close" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</div>
<div class="menu-close-container">
<svg class="menu-close" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</div>
Line 14-19 on CodePen This code was working with an input / checkbox. I swapped for a button and reworked some of the JS and now running into an issue where the menu auto collapses
Coder_Carl
Coder_Carlβ€’12mo ago
ah, blind eyes apparently. and yer your event listeners are triggering at the same time. you can do something really hacky like doing a setTimeout of 1ms before adding the event listener to close it when it detects the click otuside function openMenu () { menu.classList.add('visible') document.body.classList.add('body-hidden') close.addEventListener('click', closeMenu) setTimeout( () => { document.addEventListener('click', checkBody) }, 1) }
Matt
MattOPβ€’12mo ago
Yeah it seems like theyre triggering at the same time. How is that possible? or does it consider mouse click down + mouse click up separate ?
Coder_Carl
Coder_Carlβ€’12mo ago
because they do? event listeners are going to resolve before the dom is repainted no it considers mousedown, mouseup, mouseclick all seperate events
Matt
MattOPβ€’12mo ago
Yes but in theory, there isn't a second click to instigate those eventListeners?
Coder_Carl
Coder_Carlβ€’12mo ago
the event exists inside the open menu function that is resolving the function open menu adds the event listener which has access to the event that is currently there in the global scope
Matt
MattOPβ€’12mo ago
Ahh okay that make's sense Hmm, I wonder if I did an inline click function on the element itself if this would still happen
Coder_Carl
Coder_Carlβ€’12mo ago
we can also do something that is considered slightly better practice we can close the event off from other things event.stopPropagation(); function openMenu () { menu.classList.add('visible') document.body.classList.add('body-hidden') event.stopPropagation(); close.addEventListener('click', closeMenu) document.addEventListener('click', checkBody) }
Matt
MattOPβ€’12mo ago
Interesting, I've never seen this before
Coder_Carl
Coder_Carlβ€’12mo ago
you said in an earlier post that you are still learning JS so 🀷 you will find lots of thigns you dont know
Matt
MattOPβ€’12mo ago
Oh wow that's perfect! Works exactly as intended now thank you very much
Coder_Carl
Coder_Carlβ€’12mo ago
πŸ‘
Matt
MattOPβ€’12mo ago
Yes Sir! Thank you a lot I really appreciate it
Want results from more Discord servers?
Add your server