通过 li 的箭头键导航(无 jquery)

Posted

技术标签:

【中文标题】通过 li 的箭头键导航(无 jquery)【英文标题】:arrow keys navigation through li (no jquery) 【发布时间】:2016-02-20 19:33:35 【问题描述】:

我正在尝试找出一种方法来创建一个非常基本的自动完成功能,而无需第三方依赖。到目前为止,我已经使用 ajax 调用填充了一个结果列表,并且每个 li 上的鼠标 onclick 事件都按预期完成了这些字段。 我需要实现的是一个基于纯js的上/下/输入键导航系统,经过几个小时的搜索我放弃了。 this fiddle 非常完美地解释了我的情况,不同之处在于它确实需要 jQuery。

我不想在这里粘贴我自己的任何代码,因为最终目的是学习该过程,但由于我要链接到 jsfiddle,所以我必须这样做,所以这里是小提琴。

小提琴html

<div id="MainMenu">
    <ul>
        <li class="active"><a href="#">PATIENT TEST</a></li>
        <li><a href="#">QC TEST</a></li>
        <li><a href="#">REVIEW RESULTS</a></li>
        <li><a href="#">OTHER</a></li>
    </ul>
</div>

<a href="#" id="btnUp">Up</a>
<a href="#" id="btnDown">Down</a>

小提琴 JS:

$(document).ready(function () 
    $('#btnDown').click(function () 
        var $current = $('#MainMenu ul li.active');
        if ($current.next().length > 0) 
            $('#MainMenu ul li').removeClass('active');
            $current.next().addClass('active');
        
    );

    $('#btnUp').click(function () 
        var $current = $('#MainMenu ul li.active');
        if ($current.prev().length > 0) 
            $('#MainMenu ul li').removeClass('active');
            $current.prev().addClass('active');
        
    );

    $(window).keyup(function (e) 
        var $current = $('#MainMenu ul li.active');
        var $next;

        if (e.keyCode == 38) 
            $next = $current.prev();
         else if (e.keyCode == 40) 
             $next = $current.next();
        

        if ($next.length > 0) 
            $('#MainMenu ul li').removeClass('active');
            $next.addClass('active');
        
    );

);

非常感谢任何愿意为我指明正确方向的人。

【问题讨论】:

到目前为止你尝试过什么?使用 document.addEventListener() 是一个好的开始。 【参考方案1】:

事实证明这比我预期的要简单,我想出了以下代码,看起来做得很好。

需要考虑的事项有:

必须在每个元素上指定 HTML 属性“tabindex”才能应用 .focus() 要获得 ENTER->submit 感觉,您必须定位 li 中的链接元素 (不过,我通过此处未包含的 onclick 事件来实现此目的) 这适用于极其简单的列表结构,到目前为止我还没有使用嵌套下拉菜单对其进行测试 注意: 这很可能不适合复制/粘贴情况,但据我所知,这种方法在程序上是正确的,并且可以让您开始开发更复杂的解决方案

这是基本的 HTML:

<input type="text" name="main_input" id="input" />
<ul id="list">
 <li class="listElement"><a href="#" tabindex="1">li content</a></li>
 <li class="listElement"><a href="#" tabindex="1">li content</a></li>
 <li class="listElement"><a href="#" tabindex="1">li content</a></li>
</ul>

这是 JS 函数,当上面的列表被填充并显示时触发:

    function scrollList() 
      var list = document.getElementById('list'); // targets the <ul>
      var first = list.firstChild; // targets the first <li>
      var maininput = document.getElementById('input');  // targets the input, which triggers the functions populating the list
      document.onkeydown = function(e)  // listen to keyboard events
        switch (e.keyCode) 
          case 38: // if the UP key is pressed
            if (document.activeElement == (maininput || first))  break;  // stop the script if the focus is on the input or first element
            else  document.activeElement.parentNode.previousSibling.firstChild.focus();  // select the element before the current, and focus it
            break;
          case 40: // if the DOWN key is pressed
            if (document.activeElement == maininput)  first.firstChild.focus();  // if the currently focused element is the main input --> focus the first <li>
            else  document.activeElement.parentNode.nextSibling.firstChild.focus();  // target the currently focused element -> <a>, go up a node -> <li>, select the next node, go down a node and focus it
          break;
        
      
    

对于代码布局有点混乱,我提前道歉,我想出的函数有点复杂,为了解释的目的,我已经去掉了大部分。

不用说,我期待有关上述解决方案的任何评论,包括错误、改进或已知的兼容性问题。

【讨论】:

为避免 node.firstChild 返回 #text 或 #comment 节点的问题,ParentNode.firstElementChild 可用于仅返回第一个元素节点。 如果想以此作为参考,请注意 event.keyCode 已被弃用,而 event.key 是要走的路 (developer.mozilla.org/en-US/docs/Web/Events/keypress)【参考方案2】:

你写的

tabindex="1"

为什么不只是 tabindex="0"? 仅当您想更改默认导航顺序时才需要使用大于 0 的正数。

【讨论】:

已经很长时间了,所以我不能肯定地说,但是正如我在答案中指出的那样,此代码已被编辑为(排序)适合我原始来源的问题,其中有更多.这可能是剩下的……

以上是关于通过 li 的箭头键导航(无 jquery)的主要内容,如果未能解决你的问题,请参考以下文章

WPF:如何在不禁用箭头键导航的情况下禁用选项卡导航?

使用 vanilla js 使用箭头键遍历嵌套 uls 时跳过 ul 的第一个 li

使用箭头键的 Angular2 导航

如何对 FLTK 中的小部件进行排序以使箭头键导航正常工作?

csharp 使用箭头键调试导航功能

手机箭头键怎么设置