Site logo

Archived topic

Trying to get a button to "toggle" a div (grid)

15 replies · Started by Henry on December 27, 2020

Viewing posts 1–15 of 16

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

Hello,

Thank you for that post and that code who helped me a lot!

The first version of the code (jQuery) allows to have multiple "toggle area" on a page (because of 'next()' I think).
Is that possible with the vanilla JS you gave us here?

Thank you!

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!

This archived topic is closed to new replies.