Tagged: accessibility, menu items, w3c
-
AuthorPosts
-
January 29, 2024 at 12:35 pm #1432379
Hi, I have a site at https://oxfordwestend.co.uk/. I need the site to be accessible, and I’ve almost completed that. The bit that’s evading me is the dropdown menu in the navigation. Currently, all menu items are accessible by hitting the tab key. This isn’t quite correct – the top level of navigation should be tab-able via the keyboard, but when a dropdown is activated, the menu items should be navigable using the arrow keys (not tab) with a tab only taking you to the next item in the top level and closing any open dropdowns.
Can someone let me know how I can tweak the theme to allow this to work correctly.
Thanks in advance
Dominic
February 3, 2024 at 6:35 pm #1432883Hey domchocolate,
Thank you for your patience and the link to your site, to tab though the menu, skipping sub-menu items unless the down or up arrow keys are used please try this javascript in your child theme functions.php file in Appearance ▸ Editor:function tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used() { ?> <script> document.addEventListener('DOMContentLoaded', function () { const menuItems = document.querySelectorAll('.menu-item-has-children'); // Adjust this selector to match your menu structure // Initially set tabIndex to -1 for all sub-menu items to skip them in tab navigation menuItems.forEach(item => { let subMenuItems = item.querySelectorAll('.sub-menu a'); // Adjust this selector for your sub-menus subMenuItems.forEach(subMenuItem => { subMenuItem.tabIndex = -1; }); item.addEventListener('keydown', function (e) { // Only proceed if the event target is a menu item that contains a sub-menu let subMenu; if (e.target.classList.contains('menu-item-has-children')) { subMenu = e.target.querySelector('.sub-menu'); // Adjust this selector for your sub-menus } else { // This ensures we get the sub-menu even if a child of the menu item was focused subMenu = e.target.closest('.menu-item-has-children').querySelector('.sub-menu'); } let subMenuItems = subMenu.querySelectorAll('a'); // Assumes sub-menu items are anchor tags let focusedElement = document.activeElement; let currentIndex = Array.from(subMenuItems).indexOf(focusedElement); switch(e.key) { case 'ArrowDown': // Move focus to the next sub-menu item if (currentIndex < subMenuItems.length - 1) { subMenuItems[currentIndex + 1].tabIndex = 0; subMenuItems[currentIndex + 1].focus(); e.preventDefault(); // Prevent scrolling the page } else { // Optionally wrap around to the first item subMenuItems[0].tabIndex = 0; subMenuItems[0].focus(); e.preventDefault(); // Prevent scrolling the page } break; case 'ArrowUp': // Move focus to the previous sub-menu item if (currentIndex > 0) { subMenuItems[currentIndex - 1].tabIndex = 0; subMenuItems[currentIndex - 1].focus(); e.preventDefault(); // Prevent scrolling the page } else { // Optionally wrap around to the last item subMenuItems[subMenuItems.length - 1].tabIndex = 0; subMenuItems[subMenuItems.length - 1].focus(); e.preventDefault(); // Prevent scrolling the page } break; } // Reset tabIndex to -1 for items not focused to ensure they're skipped during tab navigation subMenuItems.forEach(subMenuItem => { if (subMenuItem !== document.activeElement) { subMenuItem.tabIndex = -1; } }); }); }); }); </script> <?php } add_action( 'wp_footer', 'tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used', 99 );
I tested this on your site by injecting it in the browser and it worked good with your desktop menu.
Best regards,
Mike- This reply was modified 9 months, 2 weeks ago by Mike. Reason: updated to correct error
February 5, 2024 at 11:18 am #1432984Thanks, Mike. Appreciate the hard work.
I’m afraid there’s an error in that code somewhere – when I put it in my dev environment I got a fatal error – “There has been a critical error on this website. Learn more about troubleshooting WordPress.” And –
An error of type E_PARSE was caused in line 108 of the file /nas/content/live/oxwedev/wp-content/themes/enfold-child/functions.php. Error message: syntax error, unexpected token "-", expecting "(" -
Line 108 is:
function tab_though_menu_skipping_sub-menu_items_unless_down_or_up_arrow_keys_are_used() { ?>
And when I try and add it using WP Code snippets I get the same error.
February 5, 2024 at 11:21 am #1432985Hi,
Thank you for the update.
The error seems to be generated because of the function name. Please remove the dash or hyphen from the “sub-menu” and replace it with an underscore.
function tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used() { ?>
Best regards,
IsmaelFebruary 5, 2024 at 11:58 am #1432994Thanks Ishmael
But now I just get an error here instead:An error of type E_COMPILE_ERROR was caused in line 109 of the file /nas/content/live/oxwedev/wp-content/themes/enfold-child/functions.php. Error message: Cannot redeclare tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used() (previously declared in /nas/content/live/oxwedev/wp-content/plugins/insert-headers-and-footers/includes/class-wpcode-snippet-execute.php(287) : eval()’d code:2)
February 5, 2024 at 5:07 pm #1433015OK, I’ve got the code so it no longer shows an error. And I can see the javascript in the page source.
But it’s not having the desired effect on my site. Any ideas?
There’s an error around line 1416 – Uncaught SyntaxError: missing ) after argument list – could it be that?
Username and password below
- This reply was modified 9 months, 2 weeks ago by domchocolate.
February 5, 2024 at 6:59 pm #1433025Hi,
Thanks for the link to your test site, but the standard login url is not working /wp-admin/ so we can’t examine. Please check.Best regards,
MikeFebruary 5, 2024 at 7:11 pm #1433028Sorry that username and password are to get to the frontend only further details below in private content. Thanks again.
February 5, 2024 at 7:27 pm #1433032Hi,
Thanks, I disabled the function in your child theme and added the javascript to your WPCode plugin and found that the console.log code was causing an error:
console.log(Pressed key: ${e.key});
so I disabled it as it was only for testing.
Now the code works, please clear your browser cache and check.Best regards,
MikeFebruary 5, 2024 at 7:29 pm #1433033Hi Mike
So the code back is now just a javascript snippet and I can delete all the code from the functions.php, is that right? I need to duplicate this on my live server.
Dominic
- This reply was modified 9 months, 2 weeks ago by domchocolate.
February 5, 2024 at 7:36 pm #1433037Hi,
Sorry for the confusion, I removed the WPCode snippet and enabled the child theme function again.
This is the working solution:function tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used() { ?> <script> document.addEventListener('DOMContentLoaded', function () { const menuItems = document.querySelectorAll('.menu-item-has-children'); // Adjust this selector to match your menu structure // Initially set tabIndex to -1 for all sub-menu items to skip them in tab navigation menuItems.forEach(item => { let subMenuItems = item.querySelectorAll('.sub-menu a'); // Adjust this selector for your sub-menus subMenuItems.forEach(subMenuItem => { subMenuItem.tabIndex = -1; }); item.addEventListener('keydown', function (e) { // Only proceed if the event target is a menu item that contains a sub-menu let subMenu; if (e.target.classList.contains('menu-item-has-children')) { subMenu = e.target.querySelector('.sub-menu'); // Adjust this selector for your sub-menus } else { // This ensures we get the sub-menu even if a child of the menu item was focused subMenu = e.target.closest('.menu-item-has-children').querySelector('.sub-menu'); } let subMenuItems = subMenu.querySelectorAll('a'); // Assumes sub-menu items are anchor tags let focusedElement = document.activeElement; let currentIndex = Array.from(subMenuItems).indexOf(focusedElement); switch(e.key) { case 'ArrowDown': // Move focus to the next sub-menu item if (currentIndex < subMenuItems.length - 1) { subMenuItems[currentIndex + 1].tabIndex = 0; subMenuItems[currentIndex + 1].focus(); e.preventDefault(); // Prevent scrolling the page } else { // Optionally wrap around to the first item subMenuItems[0].tabIndex = 0; subMenuItems[0].focus(); e.preventDefault(); // Prevent scrolling the page } break; case 'ArrowUp': // Move focus to the previous sub-menu item if (currentIndex > 0) { subMenuItems[currentIndex - 1].tabIndex = 0; subMenuItems[currentIndex - 1].focus(); e.preventDefault(); // Prevent scrolling the page } else { // Optionally wrap around to the last item subMenuItems[subMenuItems.length - 1].tabIndex = 0; subMenuItems[subMenuItems.length - 1].focus(); e.preventDefault(); // Prevent scrolling the page } break; } // Reset tabIndex to -1 for items not focused to ensure they're skipped during tab navigation subMenuItems.forEach(subMenuItem => { if (subMenuItem !== document.activeElement) { subMenuItem.tabIndex = -1; } }); }); }); }); </script> <?php } add_action( 'wp_footer', 'tab_though_menu_skipping_sub_menu_items_unless_down_or_up_arrow_keys_are_used', 99 );
Best regards,
MikeFebruary 5, 2024 at 7:39 pm #1433038OK – just to be clear – I can just copy and paste this into my functions on my live site. Is that right?
Thanks again
Dominic
February 5, 2024 at 7:43 pm #1433039Hi,
Yes, sorry for the other errors, but you should not have any issues now. Do you see it woking on your test site?Best regards,
MikeFebruary 5, 2024 at 7:44 pm #1433040Yep, it’s working on both sites – thanks so much. This is an excellent fix!
February 5, 2024 at 7:47 pm #1433042Hi,
Glad we were able to help, if you have any further questions please create a new thread and we will gladly try to help you. Thank you for using Enfold.Best regards,
Mike -
AuthorPosts
- The topic ‘Dropdown menu accessibility (arrow keys NOT tab)’ is closed to new replies.