I'm not sure if my post title is specific enough for the question I'm asking. I couldn't think of any other way to phrase it.
I am building a rudimentary CSM and I'd like to have the following "Edit" button at the side of every entry. When the button is clicked, a drop-down menu is displayed. Each button and corresponding ul tag would have unique IDs based on the post it's attached to.
How can I generalize the following JS code to work with every button, regardless of ID, instead of being dependent on getting element by ID?
Here's the button markup.
<button id="someId" aria-expanded="false">Edit</button>
<ul id="someOtherId" style="display: none; margin-top: 10px;">
<a href="#">
<li >Edit</li>
</a>
<a href="#" >
<li >Unpublish</li>
</a>
<a href="#" >
<li >Delete</li>
</a>
</ul>
Here is the JS.
const toggle = document.getElementById('someId')
const content = document.getElementById('someOtherId')
const show = () => {
toggle.setAttribute('aria-expanded', true)
content.style.display = "block"
}
const hide = () => {
toggle.setAttribute('aria-expanded', false)
content.style.display = "none"
}
toggle.addEventListener('click', event => {
event.stopPropagation()
JSON.parse(toggle.getAttribute('aria-expanded')) ? hide() : show()
})
const handleClosure = event => !content.contains(event.target) && hide()
window.addEventListener('click', handleClosure)
window.addEventListener('focusin', handleClosure)
CodePudding user response:
This can be done with multiple ways, One way to surround each dropdown with a container div
and give it all same class, and then use querySelectorAll
to select all the dropdowns, and loop throw, and on each dropdown, use querySelector
to get the button
and ul
.
const dropdowns = document.querySelectorAll('.dropdown');
dropdowns.forEach(dropdown => {
const toggle = dropdown.querySelector('button')
const content = dropdown.querySelector('ul')
const show = () => {
toggle.setAttribute('aria-expanded', true)
content.style.display = "block"
}
const hide = () => {
toggle.setAttribute('aria-expanded', false)
content.style.display = "none"
}
toggle.addEventListener('click', event => {
event.stopPropagation()
JSON.parse(toggle.getAttribute('aria-expanded')) ? hide() : show()
})
const handleClosure = event => !content.contains(event.target) && hide()
window.addEventListener('click', handleClosure)
window.addEventListener('focusin', handleClosure)
})
<div >
<button aria-expanded="false">Edit</button>
<ul style="display: none; margin-top: 10px;">
<a href="#">
<li >Edit</li>
</a>
<a href="#" >
<li >Unpublish</li>
</a>
<a href="#" >
<li >Delete</li>
</a>
</ul>
</div>
<div >
<button aria-expanded="false">Add</button>
<ul style="display: none; margin-top: 10px;">
<a href="#">
<li >Add</li>
</a>
<a href="#" >
<li >Unpublish</li>
</a>
<a href="#" >
<li >Delete</li>
</a>
</ul>
</div>