Last active
July 18, 2024 00:42
-
-
Save EarthmanWeb/db03416e2ca48769b61bfbda12e17135 to your computer and use it in GitHub Desktop.
Fixes WCAG Accessibility issues with Getwid Accordion to make it work with the tab key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Plugin Name: Accordion Accessibility Enhancements | |
* Description: Adds tab-index enhancements to Getwid accordion items for better accessibility. | |
* Version: 1.16 | |
* Author: Terrance Orletsky / ChatGPT | |
*/ | |
function em_add_inline_js_to_footer() { | |
?> | |
<script type="text/javascript" id="getwid-wcag"> | |
document.addEventListener('DOMContentLoaded', function() { | |
jQuery(document).ready(function() { | |
// Find all the top-level accordion items and set their tab-index to 0 | |
jQuery('.wp-block-getwid-accordion__header-wrapper').attr('tabindex', 0); | |
// Add role="button" to the '.wp-block-getwid-accordion__header-wrapper a' element: | |
// This ensures that the link is recognized as a button for accessibility purposes. | |
jQuery('.wp-block-getwid-accordion__header-wrapper a').attr('role', 'button'); | |
// Add aria-controls="ui-id-2" and aria-expanded="false" to the <a> element: | |
// This associates the button with the content panel and indicates that the panel is initially collapsed. | |
jQuery('.wp-block-getwid-accordion__header-wrapper a').attr('aria-controls', function(index) { | |
return 'ui-id-' + (index + 2); | |
}); | |
jQuery('.wp-block-getwid-accordion__header-wrapper a').attr('style', function(index) { | |
return 'min-height: 24px;min-width: 24px;'; | |
}); | |
// fix WCAG issue: An element with a role that makes its children presentational should not contain focusable elements. | |
jQuery('.wp-block-getwid-accordion__header-wrapper a').attr('tabindex', "-1"); | |
// Add role="tabpanel" to the content wrapper: This identifies the content panel as a tab panel. | |
jQuery('.wp-block-getwid-accordion__content-wrapper').attr('role', 'tabpanel'); | |
// Don't add tabindex to these elements | |
const emExcludeElements = 'p,div,span,strong,ul,ol,li,em,br'; | |
// Find all elements inside each tab and set their tab-index to -1 | |
jQuery('.wp-block-getwid-accordion__content-wrapper').each(function() { | |
// todo - this should be more selective to only target elements that are focusable | |
jQuery(this).find('*').not(emExcludeElements).attr('tabindex', -1); | |
}); | |
// Do the same for any nested elements inside an iframe | |
jQuery('.wp-block-getwid-accordion__content-wrapper iframe').each(function() { | |
// todo - this should be more selective to only target elements that are focusable | |
jQuery(this).contents().find('*').not(emExcludeElements).attr('tabindex', -1); | |
}); | |
// add click events so that the tabindex will be removed when the accordion is clicked, | |
// and added back when the accordion is closed, note that the content wrapper and header are siblings | |
// only do this for the contents of the adjacent one | |
// also bind this to work when the link is selected using the keyboard | |
jQuery('.wp-block-getwid-accordion__header-wrapper').on('click keydown', function(event) { | |
if (event.type === 'click' || (event.type === 'keydown' && event.key != 'Tab' && event.key != 'Shift')) { | |
// override getwid code (really?!) that is setting the rest of the accordion headers to -1 on click | |
jQuery('.wp-block-getwid-accordion__header-wrapper').attr('tabindex', 0); | |
//check for 'aria-expanded="true"' in this string: jQuery(this)[0] | |
// note: this check's logic is reversed because it updates after the click | |
if(jQuery(this)[0].outerHTML.includes('aria-expanded="true"')) { | |
// opened | |
// scroll the anchor to the top of the viewport after a tiny delay to allow the accordion to fully expand | |
setTimeout(() => { | |
jQuery(this).find('a')[0].scrollIntoView({behavior: 'smooth', block: 'start'}); | |
}, 500); | |
// check that the accordion is closed | |
// add the tabindex back to all elements inside the content wrapper | |
jQuery(this).next('.wp-block-getwid-accordion__content-wrapper').find('*').not(emExcludeElements).attr('tabindex', 0); | |
// do the same for any nested elements inside an iframe | |
jQuery(this).next('.wp-block-getwid-accordion__content-wrapper').find('iframe').each(function() { | |
jQuery(this).contents().find('*').not(emExcludeElements).attr('tabindex', 0); | |
}); | |
} else { | |
// closed | |
// remove the tabindex from all elements inside the content wrapper | |
jQuery(this).next('.wp-block-getwid-accordion__content-wrapper').find('*').not(emExcludeElements).attr('tabindex', -1); | |
// do the same for any nested elements inside an iframe | |
jQuery(this).next('.wp-block-getwid-accordion__content-wrapper').find('iframe').each(function() { | |
jQuery(this).contents().find('*').not(excludeElements).attr('tabindex', -1); | |
}); | |
} | |
} | |
}); | |
}); | |
}); | |
</script> | |
<?php | |
} | |
add_action( 'wp_footer', 'em_add_inline_js_to_footer', 2000 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment