campuspress / divi-accessibility

Improve Divi accessibility in accordance with WCAG 2.0 guidelines.
https://wordpress.org/plugins/accessible-divi/
GNU General Public License v2.0
127 stars 29 forks source link

Notify user of accordion state changes #7

Open josephfusco opened 7 years ago

josephfusco commented 7 years ago

For screen reader reliant users, there is no notification provided when the state of the accordion region changes (e.g., “Accordion 1 collapsed”)

alexstine commented 4 years ago

This is next up as it's a big issue, I will attempt to fix it in next release.

mrwweb commented 1 year ago

I suspect there's room for improvement, but I made a pass at starting to fix this. There are a few notable drawbacks:

  1. This only fixes Toggle modules and doesn't account for the one-open-at-a-time Accordion modules. For our sites, we removed the Accordion module from editors so they can't use it.
  2. There's probably a better way to do this, but I had to put a timeout on the script initialization to make sure it runs last.
'use strict';
(function () {
    let toggleIndex = 0;

    function toggleFixInit() {
        const toggleModules = document.querySelectorAll('.et_pb_toggle');
        toggleModules.forEach( toggle => {
            setupAria(toggle);
            toggle.addEventListener('click',toggleAria);
        });
    }

    function setupAria(toggle) {
        const toggleId = 'toggle-content-'  + toggleIndex;
        const label = toggle.querySelector('.et_pb_toggle_title');
        const content = toggle.querySelector( '.et_pb_toggle_content' );
        const initialState = toggle.classList.contains('et_pb_toggle_close') ? 'false' : 'true'

        const button = document.createElement('button');
        button.innerText = label.innerText;
        button.setAttribute( 'aria-expanded', initialState );
        button.setAttribute( 'aria-controls', toggleId );
        button.style.all = 'unset';

        /* Don't allow focus on container */
        toggle.removeAttribute('tabindex');

        /* Required for aria-controls */
        content.id = toggleId;

        /* put focusable button inside heading with aria-expanded */
        label.innerHTML = button.outerHTML;
        label.addEventListener( 'keyup', fakeClick );

        toggleIndex++;
    }

    function toggleAria(e) {
        const button = e.currentTarget.querySelector( 'button[aria-expanded]' );
        const newState = button.getAttribute( 'aria-expanded' ) === 'true' ? 'false' : 'true';

        button.setAttribute( 'aria-expanded', newState );
    }

    /* The accordion only works on ENTER by default, so this fakes ENTER when SPACE (keycode === 32) is hit */
    function fakeClick(e) {
        if( e.keyCode === 32 ) {
            e.target.parentNode.click();
        }
    }

    /* timeout lets Divi scripts go first. Otherwise things like weird tabindex from Divi get left behind */
    document.addEventListener('DOMContentLoaded', () => { setTimeout( toggleFixInit, 1500 ) } );
})();

I hope this can solve a problem for someone or at least be the start of a better solution!

alexstine commented 1 year ago

CC @maniu