简体   繁体   English

引导下拉子菜单的键盘导航

[英]Keyboard navigation to bootstrap dropdown sub menu

I am converting a dropdown menu to be WCAG compliant and it needs to be navigable by keyboard as well as mouse.我正在将下拉菜单转换为符合 WCAG 标准,并且它需要可以通过键盘和鼠标进行导航。 As far as I can tell the bootstrap developers have removed sub menu functionality some time ago as it was not mobile friendly.据我所知,引导开发人员前段时间已经删除了子菜单功能,因为它不适合移动设备。 My requirements are desktop only .我的要求只是桌面

I have taken the code from this answer and tried in vain to get it to navigate to the sub menu using the keyboard.我已经从这个答案中获取了代码,但徒劳地试图让它使用键盘导航到子菜单。

When I update the library to bs4.5 The key navigation on the top-level dropdown is all fine.当我将库更新到 bs4.5 时,顶级下拉菜单上的键导航一切正常。 It even navigates to the first element in the sub menu, but pressing the up and down keys on this menu simply hides the popup.它甚至可以导航到子菜单中的第一个元素,但是按此菜单上的向上和向下键只会隐藏弹出窗口。

I've caught the keydown event and blocked the menu from hiding but I have no idea how to move the navigation within the submenu.我已经捕获了keydown事件并阻止了菜单隐藏,但我不知道如何在子菜单中移动导航。 The code does not appear to be using the active class attribute, as I might have expected.正如我所料,该代码似乎没有使用active的 class 属性。

My requirements are as follows.我的要求如下。

  • The sub menu is key navigable by UP/DOWN子菜单可通过 UP/DOWN 键导航
  • The sub menu elements can be 'clicked' using the enter key.可以使用回车键“单击”子菜单元素。

Here is what i looks like after pressing enter to activate the sub menu.这是我按下回车键激活子菜单后的样子。

在此处输入图像描述

Here is what it looks like when you press the down arrow to move to the sub menu.这是按下向下箭头移动到子菜单时的样子。

在此处输入图像描述

The code (which is pretty much the code from the linked question minus the sub-sub menus)代码(几乎是链接问题中的代码减去子菜单)

<html>
    <head>
        <style>
            .dropdown-submenu {
                position: relative;
            }

            .dropdown-submenu a::after {
                transform: rotate(-90deg);
                position: absolute;
                right: 6px;
                top: .8em;
            }

            .dropdown-submenu .dropdown-menu {
                top: 0;
                left: 100%;
                margin-left: .1rem;
                margin-right: .1rem;
            }
        </style>
    </head>
    <body>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
        <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <a class="navbar-brand" href="#">Navbar</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNavDropdown">
                <ul class="navbar-nav">
                    <li class="nav-item active">
                        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
                    </li>
                    <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Dropdown link
                        </a>
                        <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                        <li><a class="dropdown-item" href="#">Action</a></li>
                        <li><a class="dropdown-item" href="#">Another action</a></li>
                        
                        <li class="dropdown-submenu" aria-haspopup="true" aria-expanded="false">
                            <a class="dropdown-item dropdown-toggle" href="#" id="subMenuLink">Submenu</a>
                            <ul class="dropdown-menu">
                                <li><a class="dropdown-item" href="http://www.google.com">Submenu action</a></li>
                                <li><a class="dropdown-item" href="">Another submenu action</a></li>
                            </ul>
                        </li>
                        </ul>
                    </li>
                </ul>
            </div>
        </nav>
    </body>
    <script>        
        $('.dropdown-menu a.dropdown-toggle').on('click', function(e) {
            if (!$(this).next().hasClass('show')) {
                $(this).parents('.dropdown-menu').first().find('.show').removeClass('show');
            }

            var $subMenu = $(this).next('.dropdown-menu');
            $subMenu.toggleClass('show');

            $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) {
                $('.dropdown-submenu .show').removeClass('show');
            });

            return false;
        });         
    </script>
</html>

How can I navigate within the sub menu?如何在子菜单中导航?

I was able to get the focus caret to move within the sub menu using the following code.我能够使用以下代码使焦点插入符号在子菜单中移动。 This was inspired by looking at the source code for the bootstrap dropdown plugin.这是通过查看引导下拉插件的源代码得到的启发。

If we attach a keydown handler to the submenus dropdown list, we can get the list of available items in the list as native elements, then get the current index by searching for the target of the key event.如果我们将 keydown 处理程序附加到子菜单下拉列表,我们可以获取列表中可用项目的列表作为原生元素,然后通过搜索键事件的目标来获取当前索引。 Then we can increment or decrement the index as required and set the focus to the new item.然后我们可以根据需要增加或减少索引并将焦点设置到新项目。

$('.dropdown-submenu .dropdown-menu').on('keydown', function(e) {            

    const items = $(this).find('.dropdown-item').get();
    let index = items.indexOf(event.target)

    if (e.which == 38) {
        index --;
        event.preventDefault()
        event.stopPropagation()
    } else 
    if (e.which == 40) {
        index ++;
        event.preventDefault()
        event.stopPropagation()
    }

    if(index < 0 || index > (items.length - 1)) {
        return
    }

    items[index].focus()
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM