Javascript accordion for blog posts, assigning div id


#1

Hello,
thanks in advance for any advice.
I’m quite new to this, learning html and css and trying to make a theme for grav that serves my purposes.
I’m using the w3.css framework because I’ve found their web site useful and they keep the vocabulary simple.

For my blog posts I want to display a headline that can be clicked on to show the first paragraph of the post so on arrival the blog is a list of headlines. Click one and it expands, click another and it expands.

I’m using this accordion feature of w3.css and I’ve put that code, slightly modified into my blog_item.html.twig file where I want to list the blog posts.

It’s working, cosmetically, I can see the list of blog posts. When I click the top one it opens the accordion. When I click it again it closes. But when I click the next one it opens the top one again, and clicking it closes the top one.

To explain again, there are three blog posts: 1, 2, and 3. Clicking 1 opens the accordion for 1. Clicking 2 opens the accordion for 1. Clicking 3 opens the accordion for 1.

I’m assuming that this has something to do with the id that is used in the script - Demo1 - (see the w3c accordian page here) and that the process of listing the blog entries in blog.html.twig is repeatedly using the same id - Demo1.

Am I correct? Is there some way of applying a new id for each blog post so that this does not occur?

Or am I way off?

Thanks so much for any suggestions. bye
Adam


#2

@adamburton The problem is indeed what you have found yourself: uniqueness of the accordion identifiers. So, you are not that far off…

In Twig you can access several properties of each blog item, for example title and slug. These can be used in the accordion to replace the title and identifier.

The basic structure of the accordion seems to be as follows:

<button onclick="myFunction('Demo1')" class="w3-btn w3-block w3-black w3-left-align">Open Section 1</button>
<div id="Demo1" class="w3-container w3-hide">
  <h4>Section 1</h4>
  <p>Some text..</p>
</div>

The script used by the accordion searches the DOM for an element with the same id provided to myFunction('my-id').

In Twig when looping through the blog items, you could substitute the value ‘Demo1’ by the slug of the blog item. And you could substitute the <h4> by the title of the blog item. In pseudocode this could look like:

{% for blogItem in page.collection %}
   <button onclick="myFunction('{{ blogItem.slug }}')" class="w3-btn w3-block w3-black w3-left-align">Open {{ blogItem.title}}</button>
   ...
   <div id="{{ blogItem.slug }}" class="w3-container w3-hide">
      <h4>{{ blogItem.title }}</h4>
   ...
{% endfor %}

You might want to turn this into a Twig partial called by the blog page.

Hope this will give you a little push in the right direction…


#3

@pamtbaau - thanks, that’s really helpful.

All of that has worked except one slight problem. It needs apostrophes around the {{ blogItem.slug }} in the onclick command - I think. It doesn’t work for me without them.

Also, my blog item slug is not blogItem.slug it is page.slug - I’m not sure why - is it how I am creating pages?

I need to read up on how to “turn something into a Twig partial” - I think I get the basics of it from messing around but I’m worried that bits of code I’m adding to these twig pages are in the wrong place / badly organised.

Also, I’ve just shoved the javascript for the accordion at the bottom of base.html.twig, underneath
{% block bottom %}
{{ assets.js('bottom') }}

and I feel like it should go somewhere else.

Anyway, thanks for that pamtbaau, really good.

bye
Adam


#4

@adamburton Glad to hear the push was indeed in the right direction for you…

Thanks for pointing out the omission of the single quotes required in the function call. I’ve corrected the example.

With respect to the ‘blogItem.slug’ vs ‘page.slug’:
I don’t know how your template code looks like and where you get your blog item collection from… Would you mind sharing it?

With respect to the position of the script:
Including scripts at the bottom of the page is usually a good place. Your script will not be needed until the entire page is loaded and the user can click the accordion.


#5

@pamtbaau - thanks so much.

I’m planning on putting the theme on github but I need to work out how to do that first. When I’ve done so I’ll post a link here. I’m very much at the beginning of a steep learning curve.

Unless, there is a specific file I can paste here somehow, I’m not sure which it is that you need.

thanks, bye
Adam


#6

@pamtbaau - hello

I’ve uploaded my theme to github - I think. I’m not really familiar with the platform.
I’ll hopefully be able to work out how to use it properly but you’re welcome to have a look at what I’ve uploaded.

Perhaps I’ve not uploaded the parts of grav that you need to see to understand my blog item collection. So perhaps it’s no help, but anyway, thanks.

I have a question about the page.menu that I’m trying to set up in my theme but I’ll ask that in a separate post.

thanks for looking, bye
Adam


#7

@adamburton I have looked at the theme in your repo and on first sight I found no obvious issues. You might have feared a steep learning curve, but it all seems to go just fine…


#8

@pamtbaau - thanks, that’s good to know. Your advice is making it much more manageable, and knowing that there’s somewhere to ask questions, where the questions actually get answered, really makes a difference for someone like me who doesn’t have the background knowledge.

cheers, see ya,
Adam