隐藏 Div 制表符(辅助功能)

Hidden Div Tab-through (accessibility)

我有一个部分隐藏了点击时显示的 div。我想要实现的是可访问性合规性,如果我通过选项卡浏览并打开其中一个部分,它将通过选项卡浏览该部分的内部内容,然后 return 到最初停止的位置。

例如。如果我翻阅并打开第 1 部分,我希望能够翻阅第 1 部分的内部内容,然后返回到打开第 2 部分的按钮,依此类推...

我用我的 html / 脚本创建了一个 fiddle https://jsfiddle.net/rjvw915r/10/

HTML 示例:

<div id="dropdown-menus">
  <div id="section1-drop" class="drop-section hidden-panel">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
  </div>

  <div id="section2-drop" class="drop-section hidden-panel">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
  </div>
</div>

<ul id="dropdown-links" class="menu main-tabs">
  <li>
    <a class="panel-btn" 
       href="javascript:dropMenu('section1');" 
       id="drop-link-section1">section 1</a>
  </li>
  <li>
    <a class="panel-btn" 
       href="javascript:dropMenu('section2');" 
       id="drop-link-section2">section 2</a>
  </li>
</ul>

JavaScript:

function dropMenu(menusection) {
    if ( !($('#dropdown-menus #' + menusection + '-drop').is(':hidden')) ) {

        // Select panel is open. Closes the panel.
        $('#dropdown-menus #' + menusection + '-drop').slideUp(500);
        $('#dropdown-menus #' + menusection + '-drop').removeClass('active');
        $('a#drop-link-' + menusection).removeClass('active');

        // Scroll to top of buttons.
        var aid = $("#dropdown-links");
        $('html,body').animate({scrollTop: aid.offset().top-480},400,function(){});

    } else if ( $('#dropdown-menus .drop-section').hasClass('active') 
                && $('#dropdown-menus #' + menusection + '-drop').is(':hidden') ) {

        // Another panel is open. 
        // Closes currently open panel and opens selected panel.
        $('.menu a.active').removeClass('active');
        $('#dropdown-menus .active').slideUp(500,function(){
            $('#dropdown-menus #' + menusection + '-drop').slideDown(500);
            $('#dropdown-menus #' + menusection + '-drop').addClass('active');
            $('a#drop-link-' + menusection).addClass('active');
        }).removeClass('active');

        // Scroll to top of panel.
        var aid = $("#dropdown-menus");
        $('html,body').animate({scrollTop: aid.offset().top-155},400,function(){});

    } else {

        // No panel currently open. Opens selected panel.
        $('#dropdown-menus #' + menusection + '-drop').slideDown(500);
        $('#dropdown-menus #' + menusection + '-drop').addClass('active');
        $('a#drop-link-' + menusection).addClass('active');

        // Scroll to top of panel.
        var aid = $("#dropdown-menus");
        $('html,body').animate({scrollTop: aid.offset().top-155},400,function(){});
    }
}

谢谢!

您可以使用 click 事件在单击 link 或按下回车键时执行 javascript 操作。

<div id="dropdown-menus">
  <div id="section1-drop" class="drop-section hidden-panel">
    <a href="#">Link 1</a>
    <a href="#">Link 2</a>
  </div>

  <div id="section2-drop" class="drop-section hidden-panel">
    <a href="#">Link 3</a>
    <a href="#">Link 4</a>
  </div>
</div>

<ul id="dropdown-links" class="menu main-tabs">
  <li>
    <a class="panel-btn" 
       data-section="section1-drop"
       id="drop-link-section1">section 1</a>
  </li>
  <li>
    <a class="panel-btn" 
       data-section="section2-drop"
       id="drop-link-section2">section 2</a>
  </li>
</ul>

在上面,我删除了 href 属性并添加了一个 data-section 元素来指定此 link 激活的部分。这更具语义性和可读性,现在我们可以在 jQuery.

中设置我们的处理程序

定义焦点处理程序:

// Setup the focus handler for the root links
$('.panel-btn').on('click', function(e) {
    var link = $(this);
    var section = link.attr('data-section');

    // Pass in the current link and the section name to dropMenu
    dropMenu($(this), section);
});

我稍微清理了您的下拉菜单功能,以阐明发生了什么

function dropMenu(link, menusection) {

  // Get the section specified by the menusection id
  var section = $('#' + menusection);

  // Get the open section by checking for the active class
  var openSection = $('#dropdown-menus').find('.drop-section.active');

  // Anonymous function for activating a section and focussing the 
  // first link within the section
  var showSection = function() {
    // Slide the section into view
    section.slideDown(500).addClass('active');

    // Focus the first link in the section.
    section.find('a').first().focus();
  }

  // If there is a section open, we want to slide it up first,
  // then call showSection when that has completed.

  if(openSection.length > 0) {

    // If the open section is the one that was clicked, we want
    // to simply close that section rather than open another
    if(openSecion[0] === section[0]) {
        openSection.slideUp(500).removeClass('active');
    }
    else {
        openSection.slideUp(500, showSection).removeClass('active');
    }
  }

  // Otherwise, we can just show the section straight away.
  else {
    showSection();
  }
}

这一切都非常标准,但您现在需要处理部分之间的移动,就像您希望使用 Tab 键在本机发生的那样。问题在于,由于您的 'drop sections' 位于根 link 之上,因此从拖放部分中的最后一个 link 跳转将始终将您带回到第 1 部分,因为那是下一个可跳转的元素在文档中。为防止这种情况,我们需要解决一些默认功能并实现我们自己的功能。

首先,您需要配置一个 keydown 处理程序以在跳转发生之前捕获它

// Setup a keydown handler to handle tabbing on section links
$('.drop-section').on('keydown', 'a', function(e) {
  if(e.keyCode === TAB_KEY) {
    var link = $(this);

    // Flag determins whether to prevent default tab behaviour
    var preventDef = false;

    // Travel to previous link on SHIFT + TAB
    if(e.shiftKey) {
      preventDef = travelPrevious(link);
    }

    // Travel to next link on TAB
    else {
      preventDef = travelNext(link);
    }

    // Prevent default focus behaviour
    if(preventDef) {
      e.preventDefault();
    }
  }
});

然后我们需要函数来处理下一个选项卡和上一个选项卡

// Handles travelling to the next link
function travelNext(link) {
  var next = link.next();

  if(next.length > 0) {
    // Continue with default behaviour of moving to next link
    return false;
  }

  // Drop section parent ID
  var parentId = link.parents('.drop-section').attr('id');

  // Root link whose data-section attribute matches parent ID
  var rootLink = $('.panel-btn[data-section=' + parentId + ']').parent();

  // Next root link to move to.
  var nextLink = rootLink.next().find('a');

  // Focus on the next root link, which will fire dropMenu for 
  // the next section.
  nextLink.focus();

  // Prevent default behaviour
  return true;
}

function travelPrevious(link) {
  var prev = link.prev();

  if(prev.length > 0) {
    // Continue with default behaviour of moving to previous link
    return false;
  }

  // Drop section parent ID
  var parentId = link.parents('.drop-section').attr('id');

  // LI container for Root link whose data-section attribute matches parent ID
  var rootLink = $('.panel-btn[data-section=' + parentId + ']').parent();

  // Previous root link to move to.
  var prevLink = rootLink.prev().find('a');

  // Focus on the previous root link, which will fire dropMenu for 
  // the previous section.
  prevLink.focus();

  // Prevent default behaviour
  return true;
}

这仍然不是一个完整的解决方案,因为它无法处理到达所有部分的结尾或开头的问题。这应该是一个开始,我相信它可以回答您的第一个问题。如果您对此有其他疑问,请单独询问。

这是一个fiddle例子 https://jsfiddle.net/rjvw915r/17/

更新

如果您的 link 以 non-standard 方式包含在 drop-section 中,上述方法将无法正常工作,因为它使用 nextprev 寻找直接兄弟姐妹的函数。如果每个 a 标签都包含在 divli 包装器中,则它们没有直接兄弟姐妹。

我们可以通过回顾已知的父元素并通过选择器找到所有兄弟元素来解决这个问题。在 keydown 函数中,我们将添加一些额外的代码来检索这些元素,并将它们传递给旅行函数。

$('.drop-section').on('keydown', 'a', function(e) {
    if(e.keyCode === TAB_KEY) {
        var link = $(this);

        // Retrieve all available links within the parent.
        var linkCollection = link.parents('.drop-section').find('a');

        ...

在每个旅行函数中,我们将这些 link 传递给

preventDef = travelPrevious(link, linkCollection);

... 

preventDef = travelNext(link, linkCollection);

通过找到当前link的索引,我们可以确定它之前或之后是否有任何兄弟姐妹。

travelNext 函数中,我们检查它后面是否有任何 links

// Find where the current link sits within the collection
var linkIndex = linkCollection.index(link);
var nextIndex = linkIndex + 1;

if(nextIndex < linkCollection.length) {
  // Continue with default behaviour of moving to next link.
  return false;
}

travelPrevious 函数中,我们检查它之前是否有任何 links

// Find where the current link sits within the collection
var linkIndex = linkCollection.index(link);
var nextIndex = linkIndex - 1;

if(nextIndex >= 0) {
  // Continue with default behaviour of moving to previous link
  return false;
}

查看更新 fiddle https://jsfiddle.net/rjvw915r/18/