如何在Firefox和IE中使用键盘导航跳过隐藏的单选按钮选项?

3
更新即使尝试了此处的建议,以下问题仍然存在。最新的代码片段演示了隐藏单选按钮的三种方法以及在Firefox和IE中破坏单选组的 / (上/下箭头键盘导航)。
假设我有一个单选组,每个单选按钮都有它的标签在一个DIV中。一旦其中一个单选按钮获得焦点,我就使用箭头键(上/下)浏览我的单选按钮。
我的单选组中有一个单选按钮被隐藏了。它在一个DIV中,该DIV具有display:none; (但我也尝试了visibility:hiddenposition:fixed;opacity:0作为可能的替代方案)。
我注意到,在Chrome中,即使隐藏了单选按钮,我仍然可以使用上/下箭头遍历聚焦列表而不会出现问题,但是在Firefox和IE中,当焦点应转移到隐藏的单选按钮上时,我的导航会出现问题。
要查看这个问题,请按照以下步骤操作:
1. 在Firefox或IE中与Chrome相对比,首先使用鼠标选择单选按钮#1(在每列中都是如此)
2. 现在使用键导航到列表末尾:在Firefox和IE中它会破坏,但在Chrome中可以正常工作。组将取消选择,并且您将失去在Firefox和IE中的焦点。
3. 您还可以尝试按相反顺序从末尾开始操作,结果也一样。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>

<table>
<tr>
<td>
<span style="font-weight:bold;">With display:none</span>
</td>
<td>
<span style="font-weight:bold;">With visibility:hidden</span>
</td>
<td>
<span style="font-weight:bold;">With position:fixed;opacity:0;</span>
</td>

</tr>
<tr>
<td>

<div>
   <input id="opt1a" type="radio" name="group" value="option1">
   <label for="opt1a">Option 1</label>
</div>
<div>
   <input id="opt2a" type="radio" name="group" value="option2">
   <label for="opt2a">Option 2</label>
</div>
<div>
   <input id="opt3a" type="radio" name="group" value="option3">
   <label for="opt3a">Option 3</label>
</div>
<div style="display:none;">
   <input id="optSecret" type="radio" name="group" value="optionSecret">
   <label for="optSecreta">Secret Option</label>
    
</div>
<div>
   <input id="opt5a" type="radio" name="group" value="option5">
   <label for="opt5a">Option 5</label>
</div>

</td>

<td>
<div>
   <input id="opt1b" type="radio" name="group2" value="option1">
   <label for="opt1b">Option 1</label>
</div>
<div>
   <input id="opt2b" type="radio" name="group2" value="option2">
   <label for="opt2b">Option 2</label>
</div>
<div>
   <input id="opt3b" type="radio" name="group2" value="option3">
   <label for="opt3b">Option 3</label>
</div>
<div style="visibility:hidden;">
   <input id="optSecretb" type="radio" name="group2" value="optionSecret">
   <label for="optSecretb">Secret Option</label>
    
</div>
<div>
   <input id="opt5b" type="radio" name="group2" value="option5">
   <label for="opt5b">Option 5</label>
</div>
</td>

<td>
<div>
   <input id="opt1c" type="radio" name="group3" value="option1">
   <label for="opt1c">Option 1</label>
</div>
<div>
   <input id="opt2c" type="radio" name="group3" value="option2">
   <label for="opt2c">Option 2</label>
</div>
<div>
   <input id="opt3c" type="radio" name="group3" value="option3">
   <label for="opt3c">Option 3</label>
</div>
<div style="position:fixed;opacity:0;">
   <input id="optSecretc" type="radio" name="group3" value="optionSecret">
   <label for="optSecretc">Secret Option</label>
    
</div>
<div>
   <input id="opt5c" type="radio" name="group3" value="option5">
   <label for="opt5c">Option 5</label>
</div>
</td>

</tr>
</table>

状态:

  1. display:none; 破坏了隐藏单选按钮的循环,但会导致空间塌陷;
  2. visibility:hidden 破坏了隐藏单选按钮的循环,但保留了空间;
  3. position:fixed;opacity:0 一次性破坏了循环(暂时陷阱),但在按上/下箭头继续后会恢复。但正常循环仍然被破坏。

有关此事有任何更新吗?不幸的是,在IE中情况是相同的。 - gene b.
1
我不知道为什么会这样(我已经询问了几个可能知道的人),但是我知道,就可访问性而言,使用display:none隐藏表单元素被认为是不良实践,部分原因就在于此。标记为重复的解决方案是正确的方法。 - TylerH
1
不,那个帖子中的建议都没有起作用。visibility:hidden会产生相同的行为,只是占据空间。position:fixed;opacity:0;保持了循环,但是会有一个暂时丢失单选按钮的问题,所以你需要按两次向下键重新聚焦。如果我们可以重新打开这个帖子,我就可以展示这个问题。你能否取消“重复”标记,并允许我发布更多信息?这个问题仍未解决。 - gene b.
当问题被关闭时,您仍然可以编辑它;我建议您首先这样做。 - TylerH
1
谢谢,我更新了我的答案,现在你可以看到所有的选项演示 - 但仍然没有解决方案。我解释了状态。 - gene b.
2
我已重新打开了这个问题,并调整了标题,以更直接地反映您的情况。希望您能得到解决方案! - TylerH
3个回答

2

我只能通过手动解决方法来解决它,其中我拦截向上/向下键并使其跳过隐藏元素。在所有3个浏览器(FF/IE/Chrome)中都可以工作,并在必要时进行换行。令人惊讶的是需要一种hack方法,而且没有其他信息可用。

最初的回答:

我只能通过手动解决方法来解决它,其中我拦截向上/向下键并使其跳过隐藏元素。在所有三种浏览器(Firefox、IE和Chrome)中都可以使用,并在必要时进行换行。令人惊讶的是需要一种hack方法,而且没有其他信息可用。

$('#container').on('keydown', 'input', function(e) {

    var groupname = $(this).attr('name');
    var groupindex = $('[name="' + groupname +  '"]').index($(this));
    var groupsize = $('[name="' + groupname + '"]').length;     

    // For Down Arrow, if subsequent input in group is hidden, focus the one after it (wrap around if necessary)
    if (e.keyCode == 40 && 
        $('[name="' + groupname + '"]').eq(groupindex + 1).length && 
        $('[name="' + groupname + '"]').eq(groupindex + 1).is(':hidden')) 
    {
        e.preventDefault();
        $('[name="' + groupname + '"]').eq((groupindex + 2) % groupsize).focus();
        $('[name="' + groupname + '"]').eq((groupindex + 2) % groupsize).prop('checked', true);
        $('[name="' + groupname + '"]').trigger('change'); // Trigger Change Event manually for any dependencies
        return false;
    }
    // For Up Arrow, if preceding input in group is hidden, focus and select the one before it (wrap around if necessary)
    else if (e.keyCode == 38 && 
            $('[name="' + groupname + '"]').eq(groupindex - 1).length && 
            $('[name="' + groupname + '"]').eq(groupindex - 1).is(':hidden')) 
    {
        e.preventDefault();
        $('[name="' + groupname + '"]').eq((groupindex - 2) % groupsize).focus();
        $('[name="' + groupname + '"]').eq((groupindex - 2) % groupsize).prop('checked', true);
        $('[name="' + groupname + '"]').trigger('change'); // Trigger Change Event manually for any dependencies
        return false;
    }

    return true;
});

最初的回答

完整演示代码片段

 $('#container').on('keydown', 'input', function(e) {
  
  var groupname = $(this).attr('name');
  var groupindex = $('[name="' + groupname +  '"]').index($(this));
  var groupsize = $('[name="' + groupname + '"]').length;  
  
  // For Down Arrow, if subsequent input in group is hidden, focus the one after it (wrap around if necessary)
  if (e.keyCode == 40 && 
   $('[name="' + groupname + '"]').eq(groupindex + 1).length && 
   $('[name="' + groupname + '"]').eq(groupindex + 1).is(':hidden')) 
  {
   e.preventDefault();
   $('[name="' + groupname + '"]').eq((groupindex + 2) % groupsize).focus();
   $('[name="' + groupname + '"]').eq((groupindex + 2) % groupsize).prop('checked', true);
   $('[name="' + groupname + '"]').trigger('change'); // Trigger Change Event manually for any dependencies
   return false;
  }
  // For Up Arrow, if preceding input in group is hidden, focus and select the one before it (wrap around if necessary)
  else if (e.keyCode == 38 && 
    $('[name="' + groupname + '"]').eq(groupindex - 1).length && 
    $('[name="' + groupname + '"]').eq(groupindex - 1).is(':hidden')) 
  {
   e.preventDefault();
   $('[name="' + groupname + '"]').eq((groupindex - 2) % groupsize).focus();
   $('[name="' + groupname + '"]').eq((groupindex - 2) % groupsize).prop('checked', true);
   $('[name="' + groupname + '"]').trigger('change'); // Trigger Change Event manually for any dependencies
   return false;
  }
  
  return true;
 });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>

<div id="container">

  <div>
      <input type="radio" id="opt1" value="1" name="group">
      <label for="opt1">Option 1</label>
  </div>
  <div>
      <input type="radio" id="opt2" value="2" name="group">
      <label for="opt2">Option 2</label>
  </div>  
  <div>
      <input type="radio" id="opt3" value="3" name="group">
      <label for="opt3">Option 3</label>
  </div>  
  <div style="display:none;">
      <input type="radio" id="optSecret" value="secret" name="group">
      <label for="optSecret">Option Secret</label>
  </div>  
  <div>
      <input type="radio" id="opt5" value="5" name="group">
      <label for="opt5">Option 5</label>
  </div>    

</div>


1
我最近遇到了这个问题,我发现如果您将要隐藏的单选按钮的disabled属性设置为true,并设置display:none,那么您将能够使用上/下箭头键在同一单选按钮组中循环显示单选按钮而没有问题。这适用于Firefox,Chrome和IE 11(不确定它是否适用于旧版本的IE)。

1

如果您需要跳过多个隐藏的单选框,就像我一样,我修改了已接受的答案以适应跳过多个隐藏的单选框。

$("#container").on('keydown', 'input', function(e) {

        var groupname = $(this).attr('name');
        var group = $('[name="' + groupname +  '"]:visible');
        var groupindex = group.index($(this));
        var groupsize = group.length;

        // For Down Arrow, if subsequent input in group is hidden, focus the one after it (wrap around if necessary)
        if (e.keyCode == 40) {
            e.preventDefault();
            group.eq((groupindex + 1) % groupsize).focus();
            group.eq((groupindex + 1) % groupsize).prop('checked', true);
            group.eq((groupindex + 1) % groupsize).trigger('change'); // Trigger Change Event manually for any dependencies
            return false;
        }
        // For Up Arrow, if preceding input in group is hidden, focus and select the one before it (wrap around if necessary)
        else if (e.keyCode == 38 && group.eq(groupindex - 1).length) {
            e.preventDefault();
            group.eq((groupindex - 1) % groupsize).focus();
            group.eq((groupindex - 1) % groupsize).prop('checked', true);
            group.eq((groupindex - 1) % groupsize).trigger('change'); // Trigger Change Event manually for any dependencies
            return false;
        }
        return true;
    });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接