箭头键导航通过李(没有jquery)

nxe*_*xet 5 html javascript css ajax autocomplete

我试图想出一种方法来创建一个非常基本的自动完成,而没有第三方依赖.到目前为止,我已经用ajax调用填充结果列表,并且在每个li上使用鼠标onclick事件,脚本完成所谓的字段.
我需要实现的是一个基于纯js的上/下/输入键导航系统,经过几个小时的搜索,我放弃了.这个小提琴非常完美地解释了我的情况,区别在于它确实需要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>
Run Code Online (Sandbox Code Playgroud)

小提琴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');
        }
    });

});
Run Code Online (Sandbox Code Playgroud)

非常感谢任何愿意指出我正确方向的人.

nxe*_*xet 15

事实证明这比我预期的要简单,而且我已经提出了以下代码,这些代码显然可以很好地完成工作.

要考虑的事项是:

  • 必须在要应用的.focus()的每个元素上指定HTML属性"tabindex"
  • 要有一个ENTER->提交的感觉,你必须在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>
Run Code Online (Sandbox Code Playgroud)

这里是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;
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)

对于有点混乱的代码布局提前道歉,我想出的功能有点复杂,我为了解释目的而剥离了大部分内容.

毋庸置疑,我期待有关上述解决方案的任何评论,包括错误,改进或已知的兼容性问题.

  • _为了避免node.firstChild返回#text或#comment节点的问题,可以使用ParentNode.firstElementChild仅返回第一个元素节点._ (2认同)
  • 如果想将其用作参考,请注意 event.keyCode 已弃用,而 event.key 是要走的路 (https://developer.mozilla.org/en-US/docs/Web/Events/keypress) (2认同)