Reputation: 11
<div class="gallery-container">
<?php while (have_rows('gallery')): ?>
[...]
<div class="toggle-container">
<button class="toggle-button active" onclick="gridView()">Grid</button>
<button class="toggle-button" onclick="listView()">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<?php endwhile; ?>
</div>
What would be the best way to select specific elements on a page when the elements are created with a while loop shown above. It's an ever-growing list and elements can also be removed.
In this example I am generating a page full of small galleries together with the toggle buttons for the Grid/List view next to each gallery.
I am trying to make all of those buttons work with just the gallery they are generated together with.
I know how to select them based on their index manually, but I don't know how I could tweak the code to be able to make it work with every small gallery separately.
This is what I came up with to make it work with the first gallery:
<script>
const button = document.getElementsByClassName('toggle-button');
const element = document.getElementsByClassName('gallery-items');
function listView() {
if ( element[0].classList.contains('grid-items') ){
element[0].classList.remove("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
function gridView() {
if ( !element[0].classList.contains('grid-items') ){
element[0].classList.add("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
</script>
Upvotes: 0
Views: 68
Reputation: 371049
You might consider using event delegation instead: add a click listener to .gallery-container
. If the clicked target is a .toggle-button
, run the appropriate logic, selecting the relevant surrounding elements on click:
document.querySelector('.gallery-container').addEventListener('click', ({ target }) => {
if (!target.matches('.toggle-button')) {
return;
}
const toggleContainer = target.parentElement;
const btns = toggleContainer.children;
if (target === btns[0]) {
btns[0].classList.add('active');
btns[1].classList.remove('active');
} else {
btns[0].classList.remove('active');
btns[1].classList.add('active');
}
const galleryItems = toggleContainer.nextElementSibling;
if (target === btns[0]) {
galleryItems.classList.add('grid-items');
} else {
galleryItems.classList.remove('grid-items');
}
});
.active {
background-color: yellow;
}
.grid-items {
background-color: red;
}
<div class="gallery-container">
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items 2...]
</div>
</div>
Note that there's no need to explicitly test if a classList.contains
a particular class before adding it (though, there's no harm in doing so, it's just unnecessary).
Upvotes: 1