设置表格行元素的焦点

6
我有一个项目列表的表格,我希望能够使用键盘上下按钮来滚动它。目前我可以通过tabindex属性在列表中向下移动并达到类似的效果。同时我也使用ng repeat生成元素的实例。是否有什么提示或线索可以帮助我通过使用上下箭头键来实现对列表进行聚焦和滚动的操作?
以下是示例代码:
table ng-if="!toolbarCtrl.loadingContacts" class="table dataTable hover" id="table3">
                <tbody role="alert" aria-live="polite" aria-relevant="all">
                    <tr class="pointer" tabindex="0" ng-repeat="contact in toolbarCtrl.contactEntities | filter:toolbarCtrl.toolbarSearchStringAfterDelay | orderBy: toolbarCtrl.tab == toolbarCtrl.tabs.RECENT ? '-dateSeen' : (toolbarCtrl.tab == toolbarCtrl.tabs.ALL ? '+data.fileAs' : '')"
                        ng-class="" ng-if="toolbarCtrl.toolbarSearchStringAfterDelay" ng-click="toolbarCtrl.selectContact(contact)"> 
                        <td rel="popover_dark" ng-class="contact.loading ? 'contactDisabled' : '' " data-container="body" data-toggle="popover" data-placement="right" data-content="" data-original-title="" title="" class="sorting_1 has_popover">
                        </td>
                    </tr>
                </tbody>
            </table>

我修改了你的checkKey函数,使其变成了这个:
 controller.checkKey = function (event) {
        $("tr[tabindex=0]").focus();
        var event = window.event;
        if (event.keyCode == 40) { //down
            var idx = $("tr:focus").attr("tabindex");
            idx++;
            if (idx > 6) {
                idx = 0;
            }
            $("tr[tabindex=" + idx + "]").focus();
        }
        if (event.keyCode == 38) { //up
            var idx = $("tr:focus").attr("tabindex");
            idx--;
            if (idx < 0) {
                idx = 6;
            }
            $("tr[tabindex=" + idx + "]").focus();
        }
    }

我离成功很近,但它直接跳到了最后一个元素。这个代码看起来对吗?


我能理解为什么你会得到所有的tabindex="0"...因为你没有使用一个变量来存储tabindex的值,而是每次都将其赋值为0。 - mjw
3个回答

4
以下是处理向上/向下箭头的键盘事件来导航表格行(<tr>)的小技巧。您可能需要调整生成数据中的上下 tabindex 处理,但这取决于您。祝好运!(jsfiddle: https://jsfiddle.net/qkna8jgu/2/ )
示例HTML:
<table>
  <tr tabindex="0">
    <td>first row</td>
  </tr>
  <tr tabindex="1">
    <td>second row</td>
  </tr>
  <tr tabindex="2">
    <td>third row</td>
  </tr>
  <tr tabindex="3">
    <td>fourth row</td>
  </tr>
  <tr tabindex="4">
    <td>fifth row</td>
  </tr>
  <tr tabindex="5">
    <td>sixth row</td>
  </tr>
  <tr tabindex="6">
    <td>seventh row</td>
  </tr>
</table>

jQuery:

$(document).ready(function() {
    $("tr[tabindex=0]").focus();    
    document.onkeydown = checkKey;
});

function checkKey(e) {
    var event = window.event ? window.event : e;
    if(event.keyCode == 40){ //down
      var idx = $("tr:focus").attr("tabindex");
      idx++;
      if(idx > 6){
        idx = 0;
      }
      $("tr[tabindex="+idx+"]").focus();
    }
    if(event.keyCode == 38){ //up
      var idx = $("tr:focus").attr("tabindex");
      idx--;
      if(idx < 0){
        idx = 6;
      }
      $("tr[tabindex="+idx+"]").focus();      
    }
}

我已经接近正确了,但是不同的<tr>是由Angular生成的,因此它们都具有tabindex=0。我知道这应该使它们按视觉逻辑顺序可导航。目前,向下和向上键会将焦点放在列表底部的<tr>实例上。 - NVA
我明白了。除非你能让Angular停止这个行为,否则你可以使用jQuery $("tr[tabindex=0]").each 来修复你的<tr>元素的tabindex值,如果这对你是一个选项的话。 - mjw
我唯一困惑的地方是 $("tr[tabindex=0]").each(function(idx){ $(this).attr("tabindex",idx); }); 这段代码是否将数组中的每个项目都设置为其tabindex的值等于idx? - NVA
没错。我认为,在构建表格的 Angular 代码中,你应该处理 tabindex 值,而不是为每一行分配零值。然而,如果这不够灵活,我今天提供的代码将使用 jquery 循环(each)重新索引 tabindex 值。该代码获取所有 <tr tabindex="0">元素,循环遍历并重新赋值 tabindex 属性值为循环中的索引值。 这样就可以产生正确递增的tabindex值,使得剩余的上/下导航正常工作。 - mjw
我理解的是你的方法重新编号tabindex以i ++递增,因此我在开始时不需要将tabindex属性设置为0。 - NVA
你需要设置 tabindex="0",否则 jQuery 选择器将无法重新索引它们。如果你想删除 tabindex="0",请将 jQuery 选择器更改为 $("tr.pointer"),就像这个 https://jsfiddle.net/qkna8jgu/4/ 示例一样,它会正常工作。 - mjw

0
这是我使用的方法。它在自定义ID上操作jQuery焦点,该ID是使用名称和角度索引创建的。preventDefault仅仅是因为向上和向下键也会使我的页面上下移动,这可以消除这种情况。
controller.checkKey = function (event, index) {
        event.preventDefault();
        if (event.keyCode === 40) {
            $('#item-' + (++index)).focus();
        }
        if (event.keyCode === 38) {
            $('#item-' + (--index)).focus();
        }
    };

这种方法适用于 Angular 范式,上面的 jQuery 示例也非常棒。


0

有一种更简单的方法,而不需要使用索引。您可以仅使用nextElementSibling和previousElementSibling。此示例适用于选择表头。我只是使用普通的JavaScript:

<!DOCTYPE html>
<html>
<body>
<table>
<thead>
    <tr>
        <th tabindex="0">Col 1</th>
        <th tabindex="1">Col 2</th>
    </tr>
</thead>
<tbody>
    <tr>
        <td>first row</td>
        <td>first row</td>
    </tr>
    <tr>
        <td>second row</td>
        <td>first row</td>
    </tr>
    <tr>
        <td>third row</td>
        <td>first row</td>
    </tr>
</tbody>
</table>
<script>
const d = document;
d.addEventListener("DOMContentLoaded", function() {

d.querySelector("th[tabindex='0']").focus();
  
d.addEventListener("keydown", function (event) {
    const t = event.target;
    const k = event.keyCode;
    if (k === 40) { //right
        const next = t.nextElementSibling;
        if (next) { next.focus(); }
    } else if (k === 38) { //left 
        const prev = t.previousElementSibling;
        if (prev) { prev.focus(); }
    }
});
});
</script>
</body>
</html>

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