Archived topic
Trying to get a button to "toggle" a div (grid)
15 replies · Started by Henry on December 27, 2020
What I am trying to achieve is when a button is toggled, then a Grid (div) is opened and closed.
This has been answered here, but I wasn't able to get it to work...
The CSS and the Jquery are 100% there...
Can anyone spot what is wrong with my logic here?
This is the Grid (with CSS class applied)
https://www.screencast.com/t/wOW9R9Kbtzb
This is the Button - and I added the CSS at the button AND div level just to test it, neither worked...
https://www.screencast.com/t/KssTXmufNrw
And here:
https://www.screencast.com/t/pOcldbkDsSc
Thanks for all your help!
I am sure it is a simple thing?
Hi,
I've checked your site and it has script related errors on its console.
WordPress requires jQuery instead of $. Try replacing all of the $ in your script to jQuery.
Example: (taken from the post you're referencing, replaced all of the $ to jQuery ).
jQuery( '.toggle-heading' ).on( 'click', function( e ) {
e.preventDefault();
jQuery( '.toggle-text' ).removeClass( 'show-text' );
jQuery( this ).next( '.toggle-text' ).toggleClass( 'show-text' );
} );
Thanks, @Elvin, however, it's definitely not quite there. Would you mind taking a look? For some reason, the button toggles the grid (via a "div") but it arranges the icons in a single column?
When I remove all the JQuery it reverts to how it is meant to.
Also, I'd like the button to be Show AND Hide - at the moment it just "shows" and then remains open.
(PS I understand if this is beyond the scope of this support, I am just curious to see if you have an answer).
Can I offer a different approach?
You can keep everything else but let's use pure vanilla JS so we don't have to bother about jQuery libraries.
Try this script instead:
var toggleBtn = document.querySelector('.toggle-heading');
var toggleTgt = document.querySelector('.toggle-text');
toggleBtn.addEventListener("click", function() {
toggleTgt.classList.toggle('show-text');
});
Here's a demo of it in action: https://share.getcloudapp.com/5zudjj7b
Works great thanks very much @elvin
One last thing though - any idea why the HTML/GeneratePress layout goes to the single-column format?
I arranged the icons in a grid with x6 columns...
I've tried to view the source and use the inspector tool but I can't seem to find where the issue could be
Ah that's because you're toggling from display: none; to display: block; instead of display: flex;
That said, change this CSS:
.toggle-text.show-text {
display: block;
}
to this
.toggle-text.show-text {
display: flex;
}
It should display as you intended. (2x6)
Wow! @Elvin
Fantastic
Really amazing stuff...thanks again!
No problem. Glad it works for you. :D
Hi there,
It really depends on your HTML structure.
I like using closest() to find the parent and then search for the toggle content inside.
<div class="container">
<button>Toggle</button>
<div>Content</div>
</div>
var toggleBtn = document.querySelector('button');
toggleBtn.addEventListener("click", function( event ) {
const parent = event.target.closest( 'div' );
const target = parent.querySelector( 'div' );
target.classList.toggle('show-text');
});
Hello,
Thanks for your reply.
This is the HTML structure (that is present many time in the same page):
<div class="gb-inside-container">
<div class="gb-container toggle-heading">
<p class="gb-headline gb-headline-text">Block title</p>
<span class="gb-button gb-button-text">More</span>
</div>
<div class="gb-container toggle-content">
<p class="gb-headline gb-headline-text">Block content</p>
</div>
</div>
Here is some CSS:
.toggle-content {
display: none;
}
.toggle-content.show-content {
display: flex;
}
And the JS (with jQuery):
jQuery( '.toggle-heading' ).on( 'click', function( e ) {
e.preventDefault();
jQuery( this ).next( '.toggle-content' ).toggleClass( 'show-content' );
} );
For the moment, only that solution works.
Hi there,
With your current structure, going by your logic, using this Vanilla JS code should work as well:
<script>
var toggleBtn = document.querySelector('.toggle-heading');
var toggleTgt = document.querySelector('.toggle-content');
toggleBtn.addEventListener("click", function() {
toggleTgt.classList.toggle('show-text');
});
</script>
Here is a test of the code working from my Test website: https://share.getcloudapp.com/L1uRz72Q
Hope this helps! Kindly let us know how it goes. :)
If this doesn't work, may we know how you're adding your JS code? From my end, I'm adding it through a Hook Element hooked to wp_footer as such: https://share.getcloudapp.com/xQuq9W5g
Hi,
Yes that code works well, but just for the first occurence of my toggle block.
My problem is that I have many occurences of that block in my page:
<div class="gb-inside-container">
<div class="gb-container toggle-heading">
<p class="gb-headline gb-headline-text">Block title 1</p>
<span class="gb-button gb-button-text">More</span>
</div>
<div class="gb-container toggle-content">
<p class="gb-headline gb-headline-text">Block content 1</p>
</div>
</div>
<div class="gb-inside-container">
<div class="gb-container toggle-heading">
<p class="gb-headline gb-headline-text">Block title 2</p>
<span class="gb-button gb-button-text">More</span>
</div>
<div class="gb-container toggle-content">
<p class="gb-headline gb-headline-text">Block content 2</p>
</div>
</div>
<div class="gb-inside-container">
<div class="gb-container toggle-heading">
<p class="gb-headline gb-headline-text">Block title 3</p>
<span class="gb-button gb-button-text">More</span>
</div>
<div class="gb-container toggle-content">
<p class="gb-headline gb-headline-text">Block content 3</p>
</div>
</div>
There, second and third blocks can not be opened when clicking on.
If that’s the case, here is a JS you may try:
<script>
document.querySelectorAll('.toggle-heading').forEach(item => {
item.addEventListener('click', event => {
var placeholder = event.target.closest('div').nextElementSibling;
while (placeholder) {
if (placeholder.classList.contains('toggle-content')) {
placeholder.classList.toggle('show-text');
break;
}
placeholder = placeholder.nextElementSibling;
}
})
})
</script>
Hope this helps! :)
Thank you. I made few modifications to obtain a good result. That works!
I changed var placeholder = event.target.closest('div').nextElementSibling; to var placeholder = item.nextElementSibling;.
<script>
document.querySelectorAll('.toggle-heading').forEach(item => {
item.addEventListener('click', event => {
var placeholder = item.nextElementSibling;
while (placeholder) {
if (placeholder.classList.contains('toggle-content')) {
placeholder.classList.toggle('show-content');
break;
}
placeholder = placeholder.nextElementSibling;
}
})
})
</script>
Thank you very much!