DEV Community

Cover image for Toggle at top of the page, to expand/collapse all headers -elegant solution?
SaulH
SaulH

Posted on

Toggle at top of the page, to expand/collapse all headers -elegant solution?

Hi folks,

I'm about to implement something a bit like the expand-all | collapse-all on this page (hopefully less tacky!):

http://www.dynamicdrive.com/dynamicindex17/ddaccordion_suppliment.htm

BUT, I'm still very green, so I was hoping some folks here can lend a fair bit of their experience & time?

Screenshot of the project as implemented thus far is attached...
Alt Text

I also have a copy of the main relevant files I'm working on, but it's all a bit private. So I hope you don't mind, but to those happy to help, I can share them via a pwd-protected OneDrive link?

That screenshot doesn't show it yet, but I have already done a fair bit of the CSS side of things (using ARIA).

To further flesh out what I'm thinking, I also have a bunch of pseudo-code:

Each of the collapsible tables should have a class, I’d need to;

1 - Create a button in dashboard.ejs that calls a function. This function should:
2 - Use a global Boolean declared at the start of Dashboard.js to indicate if the tabs should >be open or closed
3- Get an array of all of the elements with the above class
4 - For each element, check if it is currently open or closed, and simulate a click on the >element if I need to change it to match the Boolean
5 - Change the appearance of the button to indicate what clicking on it should do
(so, if clicking on it would expand everything, something like “EXPAND”, or “COLLAPSE” for >the opposite)

Some further pseudo-code…

1- Button/s for Expand/Collapse all tables
2 - two-dimension array for storing if table is open or closed (e.g [table-name, >true/false]).
3 - Update array if individual table is opened or closed
4 - Refresh table array on location refresh

Does this sound about right, missing steps or sub-steps? And what 'actual' code [CSS/HTML/js] must I use to implement it?

Top comments (12)

Collapse
 
saulhj profile image
SaulH • Edited

@madsstoumann
I'm trying to use aria-controls of CSS, even that is not quite working yet (will show a vid), but more importantly, is getting the js tied into it.
Alt Text

dev-to-uploads.s3.amazonaws.com/i/...

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

No, aria-expanded is just nformation, it doesn't do anything on it's own.
Check out the markup in my Codepen, the <details>-tag has the collapse/expand functionality built-in. And then you need a single button with a JS-method, that toggles the [open]-state (like the example in my comment).

Collapse
 
saulhj profile image
SaulH

Seems I could also go this way? ...
getbootstrap.com/docs/4.5/componen...

And this one's mostly the same, cept with more of an MD aesthetic:
mdbootstrap.com/docs/jquery/javasc...
mdbootstrap.com/snippets/jquery/te...

Collapse
 
saulhj profile image
SaulH

@madsstoumann I don't see anything there, that enables me to do what I'm trying to do? O_o

TY/BR.

Thread Thread
 
madsstoumann profile image
Mads Stoumann

Then I might have misunderstood you?
I've made a new, small Codepen-example with a "Toggle All"-button:

codepen.io/stoumann/full/gOMJqyg

Thread Thread
 
saulhj profile image
SaulH • Edited

I think that's it, very close to what I was inching towards, thanks!

Hmm, could be tricky to readapt for my web app project (not all my work), a rats nest of different toolsets/frameworks etc, you name it.
But I will give it a shot...

The thing is though...

Our page has all of the headers collapsed when it first loads, will it know this, & thus, ensure the toggle button appear as "expand all"?
And then, however many times one toggles "expand all"/"collapse all", will it maintain knowledge of the 'state' - of all the table headers?
Within the current sesh of course; if the page is reloaded, presumably it'll go back to them all being collapsed, & wipe the state record.

Upon testing...
Your Codepen-example suggests it will satisfy all of the above^, BUT, it could be different when trying to merge into the entire project.

Thread Thread
 
saulhj profile image
SaulH

@madsstoumann

3 main files [.js, .scss, & .ejs] to give a better picture of the site -as currently implemented:
1drv.ms/u/s!AgX5ZmkXXVySlGRig44rsd...

And some screenshots & a video...
1drv.ms/u/s!AgX5ZmkXXVySlGZ53YwLwO...

Both are password protected, I'll message it to you or anyone who's happy to help.

Currently, there's code that keeps a count of opened table headers, & once a 4th one's opened;
It collapses the first of the 3 before the fourth. This functionality is now not wanted.
So I'd need to remove the current code, or readapt it...

All that's wanted now is a button near the top of the page, that toggles "expand-all/collapse-all".
One that fits in nicely with the current web app's aesthetic...

Thread Thread
 
saulhj profile image
SaulH

That's annoying, there used to be a way to message, but cant seem to do so for you now. Have a record of another person have msg'd previously, must've been switched off. Do you have Twitter?

Thread Thread
 
saulhj profile image
SaulH

@madsstoumann

Totally lost, tried to implement what you suggested, can't get it to work, tried several other approaches. :(

Thread Thread
 
saulhj profile image
SaulH

@madsstoumann ? Thanks again.

Thread Thread
 
madsstoumann profile image
Mads Stoumann • Edited

Hi again,
Sorry for the late reply, busy with work.
The reason why I suggested the <details>-tag is because the <details>-tag has the open-state. You should look into how to control that from your app. Probably something like: <details {{open}}>, where {{open}} will come from your state-object. Good luck!
/Mads

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

HTML's built-in "toggler" is the <details>-tag - I have a demo with various styles here:

codepen.io/stoumann/pen/ExydEYL

This tag has a boolean attribute called "open":

<details class="your-class" open>
Enter fullscreen mode Exit fullscreen mode

To select all open elements, use:

document.querySelectorAll('.your-class[open]');
Enter fullscreen mode Exit fullscreen mode

To select all closed elements, use:

document.querySelectorAll('.your-class:not([open])');
Enter fullscreen mode Exit fullscreen mode

So, as an example, to set all open elements to closed:

const open = document.querySelectorAll('.your-class[open]');
open.forEach(elm => { elm.open = false; });
Enter fullscreen mode Exit fullscreen mode

/Mads