nico3333fr / jquery-accessible-accordion-aria Goto Github PK
View Code? Open in Web Editor NEWjQuery Accessible Accordion System, using ARIA
License: MIT License
jQuery Accessible Accordion System, using ARIA
License: MIT License
I'm currently implementing this accordion on a site and I was curious how I'd be able to use a bootstrap navbar containing links that would control the opening and closing of them instead of clicking on the panel itself.
I feel like it would be pretty simple but not sure how to integrate it into your js file.
I've attached a screenshot showing what I'm referring to.
I've also attached the following jquery i have written, but there are bugs in this. It takes two clicks to open the panel, and it also isn't dynamic as I've set the panel to open.
function expandPanelBar(title) { //accordion $("#" + title + " a").on('click', function (event) { $('#accordion #accordion-0_tab').focus().click(); $("html, body").animate({ scrollTop: $("#anchor_" + title + "").offset().top }, 1000); }); }
I feel like it would be great if somehow I could tap into the clickButtonEventHandler on line 113 for the panels.
Thanks!
Here's the HTML for the accordions:
<p>here is some copy</p>
<div class="js-accordion" data-accordion-prefix-classes="toggle_32">
<div class="js-accordion__panel">
<h2 class="js-accordion__header">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
<div class="js-accordion__panel">
<h2 class="js-accordion__header">accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title </h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
<div class="js-accordion__panel">
<h2 class="js-accordion__header">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
</div>
<p>copy block</p>
<div class="js-accordion" data-accordion-prefix-classes="toggle_36">
<div class="js-accordion__panel">
<h2 class="js-accordion__header">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
</div>
After invoking the plugin, here's the markup:
<p>here is some copy</p>
<div class="js-accordion toggle_32" data-accordion-prefix-classes="toggle_32" role="tablist" aria-multiselectable="true">
<button class="js-accordion__header toggle_32__header" type="button" aria-controls="undefined-0" aria-expanded="false" role="tab" id="undefined-0_tab" aria-selected="false">accordion title</button>
<div class="js-accordion__panel toggle_32__panel" aria-labelledby="undefined-0_tab" role="tabpanel" id="undefined-0" aria-hidden="false">
<h2 class="js-accordion__header toggle_32__title" tabindex="0">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
<button class="js-accordion__header toggle_32__header" type="button" aria-controls="undefined-1" aria-expanded="false" role="tab" id="undefined-1_tab" tabindex="-1" aria-selected="false">accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title </button>
<div class="js-accordion__panel toggle_32__panel" aria-labelledby="undefined-1_tab" role="tabpanel" id="undefined-1" aria-hidden="true">
<h2 class="js-accordion__header toggle_32__title" tabindex="0">accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title accordion title </h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
<button class="js-accordion__header toggle_32__header" type="button" aria-controls="undefined-2" aria-expanded="false" role="tab" id="undefined-2_tab" tabindex="-1" aria-selected="false">accordion title</button>
<div class="js-accordion__panel toggle_32__panel" aria-labelledby="undefined-2_tab" role="tabpanel" id="undefined-2" aria-hidden="true">
<h2 class="js-accordion__header toggle_32__title" tabindex="0">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
</div>
<p>copy block</p>
<div class="js-accordion toggle_36" data-accordion-prefix-classes="toggle_36" role="tablist" aria-multiselectable="true">
<button class="js-accordion__header toggle_36__header" type="button" aria-controls="undefined-0" aria-expanded="true" role="tab" id="undefined-0_tab" aria-selected="true">accordion title</button>
<div class="js-accordion__panel toggle_36__panel" aria-labelledby="undefined-0_tab" role="tabpanel" id="undefined-0" aria-hidden="true">
<h2 class="js-accordion__header toggle_36__title" tabindex="0">accordion title</h2>
<div class="js-accordion__content">
<p>accordion body</p>
</div>
</div>
</div>
You'll notice that the aria-controls
, id
and aria-labeledby
attributes follow the "undefined-[id]" pattern. This would work just fine, but having two accordions in a single page, they affect each other.
I read the docs and your example page, but I don't see anything that controls this value. Although, I'm sure I missed something. Any advice?
When using jQuery 3.x, calling $('.js-accordion').accordion();
causes the following error:
TypeError: can't assign to property "guid" on ".js-accordion__panel": not an object debugger eval code:2:39624
(That's Firefox dev edition's wording.)
After this error occurs, the accordions still work — you can click on them and they will expand and collapse just fine — but any other jQuery code that comes after the .accordion()
call will fail to run, which can break the page if jQuery is supposed to do anything else after the accordions are created.
My browser debugger shows that line 101 of the plugin triggers the error:
this.$buttons = $(this.options.buttonsSelector, this.$wrapper);
The error happens inside jQuery 3.x's jQuery.event
object's helper function .add()
, on lines 4976-4979:
// Make sure that the handler has a unique ID, used to find/remove it later
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
Edit: The 3.x version of the jQuery Migrate plugin doesn't fix the problem.
When using attribute data-accordion-multiselectable="none" to open one panel at a time, and having tall panels, it happens that panels are opened in a way that content is completely off-screen.
For instance: first panel is opened by default (data-accordion-opened="true") -> click on the second button closes the first panel and opens the second, but it goes up and the content of second panel disappears from view, so I have to scroll back to top of the panel.
Can you suggest a solution? How we could bind a scroll event so that opened panel is scrolled at the beginning?
Is there a way to allow only one panel at a time? Also I've noticed when I call a page in a page dynamically, leave and then return the accordion requires multiple clicks to open/close.
Any ideas?
Hallo,
Using the tab button, I can navigate up to the first accordion panel, open it hitting enter and surf around it using the tab button again.
That's it... !
There is no way I can surf the rest of the tabs: No arrow, or Ctrl + Arrow or Tab will allow something like that.
I am using Firefox ESR 45.3.0.
The html code is the following:
<div class="js-accordion" data-accordion-prefix-classes="newChallenge-accordion">
{% for key, value in result_dict.items %}
<section class='category'>
<h2 class="js-accordion__header" >Panel Title</h2>
<div class="js-accordion__panel">
{% for each in value %}
<section class='entry'>
<ul class='container'>
<li class='inline-12'>First Column</li>
<li class='inline-22'><a class='button' href='http://blah.com'>Button Link</a></li>
</ul>
</section>
{% endfor %}
</div>
</section>
{% endfor %}
</div>
Issue reproductible here: https://codepen.io/nico3333fr/pen/QMxaqq
Add enable
and disable
methods.
enable
and disable
can be managed by matchmedia listener.
It's useful if we need to display an accordion on small screen but not on wide.
In both Firefox and Chrome, the CTRL+PgUP and CTRL+R/L Arrow fails to move to the panel header. I understand the conflict with FF for CTRL+PgUp which causes the user to move between FF tabs, but there is no such apparent conflict in Chrome. Implementing the CTRL+Arrow navigation specified in the 1.1 APG would appear to be a method you could implement.
It shoud be nice to have a destroy
method, which remove all aria attributes and show hidden panels.
Hello,
I had an issue when using multiple accordions on the same page, without giving them IDs. In this case, whenever I clicked on an accordion item, it opened the corresponding item in the first accordion on the page.
Adding IDs solved the issue.
If IDs are mandatory, maybe the plugin could add generate them when it is instantiated.
Thanks
When nesting one accordion in an accordion panel, extra accordion header buttons are being added to the nested panels.
Source:
<section class="js-accordion" data-accordion-prefix-classes="accordion" data-accordion-multiselectable="none">
<h2 class="js-accordion__header" data-accordion-opened="true">Header</h2>
<div class="js-accordion__panel">
<p>content</p>
<section class="js-accordion" data-accordion-prefix-classes="accordion" data-accordion-multiselectable="none">
<h2 class="js-accordion__header" data-accordion-opened="true">Header</h2>
<div class="js-accordion__panel">
<p>content</p>
</div>
<h2 class="js-accordion__header">Header</h2>
<div class="js-accordion__panel">
<p>content</p>
</div>
</section>
</div>
</section>
DOM:
<section aria-multiselectable="false" role="tablist" class="accordion" data-accordion-prefix-classes="accordion" data-accordion-multiselectable="none">
<button aria-selected="true" id="accordion1_tab1" role="tab" aria-expanded="true" aria-controls="accordion1_panel1" class="js-accordion__header accordion__header">Header</button>
<div aria-hidden="false" id="accordion1_panel1" role="tabpanel" aria-labelledby="accordion1_tab1" class="js-accordion__panel accordion__panel">
<h2 tabindex="0" class="accordion__title" data-accordion-opened="true">Header</h2>
<p>content</p>
<section aria-multiselectable="false" role="tablist" class="accordion" data-accordion-prefix-classes="accordion" data-accordion-multiselectable="none">
<button tabindex="-1" aria-selected="false" id="accordion2_tab1" role="tab" aria-expanded="false" aria-controls="accordion2_panel1" class="js-accordion__header accordion__header">Header</button>
<div aria-hidden="true" id="accordion2_panel1" role="tabpanel" aria-labelledby="accordion2_tab1" class="js-accordion__panel accordion__panel">
<button aria-selected="false" tabindex="0" id="accordion1_tab2" role="tab" aria-expanded="true" aria-controls="accordion1_panel2" class="accordion__header accordion__title">Header</button>
<h2 tabindex="0" class="accordion__title" data-accordion-opened="true">Header</h2>
<p>content</p>
</div>
<button tabindex="-1" aria-selected="false" id="accordion2_tab2" role="tab" aria-expanded="false" aria-controls="accordion2_panel2" class="js-accordion__header accordion__header">Header</button>
<div aria-hidden="true" id="accordion2_panel2" role="tabpanel" aria-labelledby="accordion2_tab2" class="js-accordion__panel accordion__panel">
<button aria-selected="false" tabindex="0" id="accordion1_tab3" role="tab" aria-expanded="false" aria-controls="accordion1_panel3" class="accordion__header accordion__title">Header</button>
<h2 tabindex="0" class="accordion__title">Header</h2>
<p>content</p>
</div>
</section>
</div>
</section>
Hi there,
I'd like to be able to listen to some events on the accordion, in order to refresh other parts of my page when an accordion item is open or closed.
This would be similar to Bootstrap Collapse events.
So I would be able to do something like:
$('.js-accordion').on('open.js-accordion', onAccordionItemOpened);
$('.js-accordion').on('close.js-accordion', onAccordionItemClosed);
Are you open to this idea? Do you want me to implement it?
Thanks in advance.
If you pass multiselectable
as an option like any other, its value gets overridden by specificOptions.multiselectable
(the data-accordion-multiselectable
) attribute.
I think it makes sense to not override it as long as no data attribute is present, e.g. when I use $( '$( '.foobar' ).accordion( { multiselectable: false } );
, I expect multiselectable
to be false.
Inside Accordion.prototype.initEvents
, the selector being used is this.options.panelSelector
.
However, the correct one would be this.options.panelsSelector
(panels
vs. panel
).
See
andSee the « publishing npm package » documentation.
The Ctrl+Up keys executed in a panel are not working properly (should give focus back to button)
See https://a11y.nicolas-hoffmann.net/accordion/ for demo.
Currently it is impossible to :
accordion
.Feature request / enhancement: make it work with <details>
& <summary>
tag structure.
Bower is still showing a tag of 2.5.1 while the version here is 2.6. Can you please update so I can user bower to update my local version. https://libraries.io/bower/jquery-accessible-accordion-aria
There is an error or a typo ?
I don't find the implementation of the method keydownPanelEventHandler who is called in Accordion.prototype.initEvents()
this.$wrapper.on('keydown', this.options.panelsSelector, $.proxy(this.keydownPanelEventHandler, this));
I would like to propose a semantic enhancement:
It seems safe to presume that each accordion tab represents a thematic grouping of content, and therefore it would be semantically correct to enclose it in a <section>
element:
<div class="js-accordion" data-accordion-prefix-classes="your-prefix-class">
<section>
<h2 class="js-accordion__header">First tab</h2>
<div class="js-accordion__panel">
<p>Content of 1st tab</p>
</div>
</section>
<section>
<h2 class="js-accordion__header">Second tab</h2>
<div class="js-accordion__panel">
<p>Content of 2nd tab</p>
</div>
</section>
<section>
<h2 class="js-accordion__header">Third tab</h2>
<div class="js-accordion__panel">
<p>Content of 3rd tab</p>
</div>
</section>
</div>
Currently this is not possible because it breaks the keyboard navigation.
I have found out that the code needing refactoring is the $accordion
selector around the document but my JQuery skills do not permit me more.
For example, changing the relevant lines to $accordion = $this.parent().parent(),
I achived to navigate with the keyboard only to the first and last tab.
In both FF and Chrome, when I tab from a header on an expanded panel, the focus leaves the header but does not appear to go anywhere. Especially for 'rookie' users, this is highly confusing at some point. The user must press TAB again to put focus on the first focusable element.
This 'missing' focus item occurs using SHIFT+TAB as well.
It would be nice to have an open/close all method to act on everything in the accordion at once.
Hello. I'm getting this error only on one set of accordions. As you can see in the URL below, one set renders perfectly fine https://www.raleys.com/stores/raleys-west-capitol-west-sacramento-california/
Is there any way to make a recursive accordion menu?
Disabling the multiselectable feature doesn't seem to work. Pasted the HTML from my site's page source. I'm using v2.2.1.
<div class="js-accordion faq-accordian" data-accordion-multiselectable="none" data-accordion-prefix-classes="faq-accordian" role="tablist" aria-multiselectable="true">
Hi, I found a small mistake in documentation. It is stated that if want to have an accordion content opened by default, we should add the attribute data-accordion-opened="true" on a hx, but should be added on a div (panel).
Thanks for a great plugin - fantastique!
My screen reader is NVDA. I can expand the Header with Enter
keypress, but how can I get my screen reader to access the content within the panel? It should be accessible by Down
keypress, but looks like it's not.
I tested with the accordions here.
Hi,
I was just wondering if there's a reason to copy the text content of the header to the button, instead of the HTML ?
var $button = this.options.button.clone().text($header.text());
It prevents the potential styling applied on the original header element (like the use of tags (strong
, span
, etc...) or graphics (SVG icons)) to be replicated to the new button element.
But maybe there's an issue I don't see in keeping the HTML ?
Bonjour,
Je suis face à un problème de génération de code avec votre code concernant l'accordéon.
Problème actuellement ->
Code de base :
<h2 class="js-accordion__header article-title">Titre de la partie 1
<span class="open">Ouvrir</span>
<span class="close" >Fermer</span>
</h2>
Code généré :
<button id="accordion-0-0_tab" class="js-accordion__header block-accordion__header" type="button" aria-controls="accordion-0-0" aria-expanded="true" role="tab" aria-selected="true">
Titre de la partie 1 Ouvrir Fermer
</button>
Demande de solution ->
Est-il possible de garder les balises présentes dans le h2 lorsque l'on génère le button ?
Exemple de code généré :
<button id="accordion-0-0_tab" class="js-accordion__header block-accordion__header" type="button" aria-controls="accordion-0-0" aria-expanded="true" role="tab" aria-selected="true">
Titre de la partie 1
<span class="open">Ouvrir</span>
<span class="close" >Fermer</span>
</button>
Merci
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.