【问题标题】:JQuery - Focus not working when navigating via Tab in Firefox and IEJQuery - 在 Firefox 和 IE 中通过 Tab 导航时焦点不起作用
【发布时间】:2015-11-07 00:04:11
【问题描述】:

我有一个简单的导航栏,我打算首先使用它的键盘可访问导航。导航栏的工作原理是这样的:

  • 使用 Tab 键,您应该能够浏览每个 导航类别及其元素。

  • 使用 Right* 和 **Left 键,您只能浏览导航类别。

  • 使用 向下 键还可以打开导航类别。

  • 使用 ESC 键关闭(隐藏)当前可见的导航类别。

这是我开发的jsFiddle

为简单起见,请关注 JavaScript 代码,因为我无法控制的需求原因导致 HTML 代码无法更改。我认为问题在于 Firefox/IE 处理 focus 事件的方式与 Chrome 不同。

$(document).ready(function(){
    var utilitymenu = new menuBar("#utility-nav"),
        navInner = new menuBar("#nav-inner"),
        mainHeader = $(".main-header");

    // Adding tabindex to all clickable anchor links
    mainHeader.find("a").each(function(i, elem){
        $(elem).attr("tabindex", i+1);
    });
});

function menuBar(id){
    var linksBlock = id + " > li",
        linksBlockSelector = " > li",
        submenuHeader = linksBlock + " > a",
        submenu = linksBlock + " div[class*='sub-menu']",
        submenuSelector = "div[class*='sub-menu']",
        textBlock = submenu + " > ul",
        textBlockSelector = submenuSelector + " > ul",
        submenuElem = textBlock + " > li a",
        keepMenuClosed = false;

    // Adding ARIA attributes to the different sections of the navigation menus
    $(linksBlock).attr({
        "role": "navigation",
        "aria-haspopup": "true",
        "aria-labelledby": "menu-title",
        "aria-describedby": "menu-description"
    });
    $(submenuHeader).attr({
        "aria-haspopup": "true",
        "id": "menu-title"
    });
    $(submenuHeader).each(function(i, elem){
        $(elem).attr("aria-label", $(elem).text().trim());
    });
    $(submenu).attr({
        "tabindex": "-1",
        "id": "menu-description"
    });
    $(textBlock).attr({
        "aria-expanded": "false",
        "aria-hidden": "true"
    });

    // Hides visible menus when clicking outside the menu area
    $(document).click(function(event) {
        if(!$(event.target).closest().length){
            $(submenu + ":visible").hide().find(textBlock).attr("aria-expanded", "false");
            $(submenu + ":visible").hide().find(textBlock).attr("aria-hidden", "true");
        }
    });

    // Drop Down Menu event handler (not inner elements)
    $(linksBlock)
    .focus(function(){
        if($(this).find(submenuSelector).is(":hidden") && !keepMenuClosed){
            $(this).find(submenuSelector).toggle();
            $(this).find(textBlockSelector).attr("aria-expanded", "true");
            $(this).find(textBlockSelector).attr("aria-hidden", "false");
            keepDropdownClosed = false;
        }
        else if($(this).find(submenuSelector).is(":visible")){
            $(this).find(submenuSelector).toggle();
            $(this).find(textBlockSelector).attr("aria-expanded", "false");
            $(this).find(textBlockSelector).attr("aria-hidden", "true");
        }
    })
    .mouseover(function(){
        $(this).find(submenuSelector).show();
        $(this).find(textBlockSelector).attr("aria-expanded", "true");
        $(this).siblings().find(submenuSelector).hide();
        $(this).siblings().find(textBlockSelector).attr("aria-expanded", "false");
        $(this).find(textBlockSelector).attr("aria-hidden", "true");
    })
    .mouseout(function(){
        $(this).find(submenuSelector).hide();
        $(this).find(textBlockSelector).attr("aria-expanded", "false");
        $(this).find(textBlockSelector).attr("aria-hidden", "true");
    })
    .keydown(function(event){
        switch(event.keyCode){
            //tab key
            case 9:
                keepMenuClosed = true;
                if($(this).find(submenuSelector).is(":visible")){
                    $(this).find(submenuSelector).toggle();
                    $(this).find(textBlockSelector).attr("aria-expanded", "false");
                    $(this).find(textBlockSelector).attr("aria-hidden", "true");
                }
                else if($(this).find(submenuSelector).is(":hidden")){
                    $(this).find(submenuSelector).toggle();
                    $(this).find(textBlockSelector).attr("aria-expanded", "true");
                    $(this).find(textBlockSelector).attr("aria-hidden", "false");
                }
                break;

            // esc key
            case 27:
                if($(this).find(submenuSelector).is(":visible")){
                    $(this).find(submenuSelector).toggle();
                    $(this).find(textBlockSelector).attr("aria-expanded", "false");
                    $(this).find(textBlockSelector).attr("aria-hidden", "true");
                    $(this).closest(linksBlock).focus();
                }
                break;

            // key left
            case 37:
                if($(this).find(submenuSelector).is(":hidden")){
                    $(this).prev().find(" > a").focus();
                    keepMenuClosed = true;
                }
                break;

            // key right
            case 39:
                if($(this).find(submenuSelector).is(":hidden")){
                    $(this).next().find(" > a").focus();
                    keepMenuClosed = true;
                }
                break;

            // key up/down
            case 38, 40:
                event.preventDefault();
                $(this).find(submenuSelector).show();
                break;
        }
    });
    // Sub Menu Elements keyboard handler
    $(submenuElem)
    .keydown(function(event){
        switch(event.keyCode){
            // tab key
            case 9:
                $(this).parent().next().find("a").focus();
                break;
            // esc key
            case 27:
                if($(this).closest(submenuSelector).is(":visible")){
                    $(this).closest("div").siblings("a ").focus();
                }
                break;
            // key up
            case 38:
                event.preventDefault();
                $(this).parent().prev().find("a").focus();
                break;
            // key down
            case 40:
                event.preventDefault();
                $(this).parent().next().find("a").focus();
                break;
        }
    });
}

TLDR

我只想了解为什么导航只在 Chrome 中有效,而在 IE 和 Firefox 中无效。我在这里做错了什么/根本没有做什么?我一直在查看 IE/FF focuspreventDefault 的已知问题,但无济于事。我不认为我的 ARIA 代码会导致问题,但我已准备好探索所有建议!

编辑

@Adam 的建议下,我添加了以下代码来显示我在 Firefox/IE 上遇到的问题:

$(this).keydown(function(e){
    if(e.keyCode === 9){
        alert($(':focus').toArray());
    }
});

它显示了问题的根源。我目前正在修改我的代码,以更好地区分我听键盘敲击的方式;以及在我的元素集中时表现出更好的聆听。

【问题讨论】:

    标签: javascript jquery html internet-explorer accessibility


    【解决方案1】:

    当你隐藏一个元素时,它会失去焦点

    当您在submenuElem 上按下tab 键时,该事件也会被linksBlock 拦截

    出于该特定原因,当您使用以下行时

     $(this).parent().next().find("a").focus();
    

    它触发 focus() 事件,然后执行将隐藏子菜单的切换。这里失去了焦点。

    $(linksBlock)
    .focus(function(){
       [...]
    
       else if($(this).find(submenuSelector).is(":visible")){
       $(this).find(submenuSelector).toggle();
    

    然后,第二个事件被触发到主块,它将显示没有设置焦点的隐藏元素:

    $(linksBlock)
    .keydown(function(event){
         [...]
                else if($(this).find(submenuSelector).is(":hidden")){
                    $(this).find(submenuSelector).toggle();
    

    【讨论】:

    • 这有点让我大吃一惊,我需要坐下来分析一下,因为即使我明白你在说什么,我也不知道如何解决它
    • 我试图区分我处理动作的方式,我缩小了算法范围,以便我只在 menumenu 元素中收听击键i>、子菜单子菜单元素。这应该真的有助于解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多