在 JavaScript 中使用箭头键移动焦点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11088674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:24:10  来源:igfitidea点击:

Shift focus with arrow keys in JavaScript

javascriptjquery

提问by Kay Lamerigts

I want to be able to navigate through all the focusable elements on my webpage with the arrow key. So when the down-key is pressed the focus should shift to the focusable element beneath the current focussed element. You get the idea for the other arrow keys, when there is not a focusable element to shift to, the focus should remain the same.

我希望能够使用箭头键浏览网页上所有可聚焦的元素。因此,当按下向下键时,焦点应移至当前聚焦元素下方的可聚焦元素。您了解其他箭头键的想法,当没有可聚焦的元素转移到时,焦点应保持不变。

This is what I got so far:

这是我到目前为止得到的:

$(document).keydown(function(e){    

if (e.keyCode == 37) { //left

   var offset = $("*:focus").offset();

   var allElements = $("#container").find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]');

   var arr = jQuery.makeArray(allElements);

   var topLeft = offset.left
   var minus = topLeft;
   var currentElement = $("*:focus");

   for(var i = 0; i < arr.length; i++)
   {

      if ( (arr[i].offset().left < offset.left)  // This doesn't work for some reason
        && ((offset.left - arr[i].offset().left) < minus))
      {
        currentElement = arr[i];
        minus = offset.left - arr[i].offset().left;
        topLeft = arr[i].offset().left;
      }


      currentElement.focus();
   }


   alert( "left pressed" );
   return false;
}

// Other Keys

});

});

the idea was to get all the focus-able elements and than pick select the one that is suited for the arrow and shift focus.

我们的想法是获得所有可聚焦的元素,然后选择适合箭头和移动焦点的元素。

I'm not able to get this code to work (it contains a error) and I'm not completly sure it will even work.

我无法让这段代码工作(它包含一个错误),我不确定它甚至会工作。

Thnx in advance

提前谢谢

[EDIT]: I guess I was a little vague. I do not only want to go left and right, but also up and down.

[编辑]:我想我有点含糊。我不仅要左右走,还要上下。

回答by Cranio

What I would do is much simpler. Just add a common class among the objects who should have this functionality (f.ex. "move") and use:

我要做的事情要简单得多。只需在应该具有此功能的对象中添加一个公共类(例如“移动”)并使用:

$(document).keydown(
    function(e)
    {    
        if (e.keyCode == 39) {      
            $(".move:focus").next().focus();

        }
        if (e.keyCode == 37) {      
            $(".move:focus").prev().focus();

        }
    }
);
?

See example: http://jsfiddle.net/uJ4PJ/

参见示例:http: //jsfiddle.net/uJ4PJ/

This code is muchsimpler and hopefully has all the functionality you need.

这段代码简单得多,希望拥有您需要的所有功能。

Just make sure the controls are in the correct orderor this won't work properly.

只需确保控件的顺序正确,否则将无法正常工作。

回答by user2462210

After much trial and error, I developed this code that works :

经过多次反复试验,我开发了这个有效的代码:

function navigate(origin, sens) {
    var inputs = $('#form').find('input:enabled');
    var index = inputs.index(origin);
    index += sens;
    if (index < 0) {
        index = inputs.length - 1;
    }
    if (index > inputs.length - 1) {
        index = 0;
    }
    inputs.eq(index).focus();
}

$('input').keydown(function(e) {
    if (e.keyCode==37) {
        navigate(e.target, -1);
    }
    if (e.keyCode==39) {
        navigate(e.target, 1);
    }
});

right arrow acts as tab

右箭头充当标签

left arrow acts as shift tab

左箭头充当移位选项卡

回答by Jānis

Preview - http://jsfiddle.net/FehKh/;)

预览 - http://jsfiddle.net/FehKh/;)

html:

html:

<a href='jqwja' class="focusable">jajaj</a>
<a href='jjaasd' class="focusable focused">jajasdaaj</a>
<a href='jjqwea' class="focusable">jajaacasj</a>
<input value='iddqd' name="DoomII" class="focusable" />?

js:

js:

// init
$('.focused').focus();

// actual code
$(document).keydown(function(e){    
    if (e.keyCode == 37) { // left
        if($('.focused').prev('.focusable').length)
            $('.focused').removeClass('focused').prev('.focusable').focus().addClass('focused');
    }
    if (e.keyCode == 39) { // right
        if($('.focused').next('.focusable').length)
            $('.focused').removeClass('focused').next('.focusable').focus().addClass('focused');
    }
});?

回答by Ahmad Shakil

Implemented above by checking some articles and stack over flow links

上面通过检查一些文章和stack over flow链接来实现

jQuery.fn.elementAfter = function(other) {
for(i = 0; i < this.length - 1; i++) {
    if (this[i] == other) {
        return jQuery(this[i + 1]);
    }
}
return jQuery;
} ;

jQuery.fn.elementBefore = function(other) {
if (this.length > 0) {               
    for(i = 1; i < this.length; i++) {
        if (this[i] == other) {
            return jQuery(this[i - 1]);
        }
    }
}
return jQuery;
};

https://jsfiddle.net/bkLnq5js/79/

https://jsfiddle.net/bkLnq5js/79/

回答by Axel EsZu

This works great

这很好用

$('p').each(function(index) {
  $(this).attr('tabindex', index)
}).on('keyup', function(e) {
  e.preventDefault;
  if (e.keyCode == 39) {
    $('[TabIndex="' + Number(Number($(this).attr('tabindex')) + 1) + '"]').focus();
  }
  if (e.keyCode == 37) {
    $('[TabIndex="' + Number(Number($(this).attr('tabindex')) - 1) + '"]').focus();
  }
});

回答by baron_bartek

None of above solutions worked for me. This one is mine. It look difficult but it's accually real easy. Create arrayof link and change focus using the array index. (I needed up/down arrow so keycodes are different). It also works with dynamiclyadded links (cause I needed it this way, that is why I use on)

以上解决方案都不适合我。这个是我的。看起来很难,但实际上很容易。array使用数组创建链接并更改焦点index。(我需要向上/向下箭头,所以键码不同)。它也适用于dynamicly添加的链接(因为我需要这种方式,这就是我使用的原因on

$('#links_container').on("keydown", ".link",
    function(e)
    {    

        //start - list of <a>
        var flag = false;
        var smallMeni = document.getElementById('links_container');
        var allElements2 = smallMeni.getElementsByTagName('a'); //.link
        //end

        //start - key down
        if (e.keyCode == 40) 
        {           
            for (var i=0;i<allElements2.length;i++)
            {

                if(flag == true){

                    flag = false

                    allElements2[i].focus();

                    //alert(i)
                }
                else
                {
                    if ( document.activeElement === allElements2[i] )
                    {
                        //alert(i);
                        flag = true;
                    }           
                }

            }
        }
        //end

        //start - key up
        if (e.keyCode == 38) 
        {           
            for (var i=0;i<allElements2.length;i++)
            {

                if ( document.activeElement === allElements2[i] )
                {
                    if (i>0)
                    {
                        allElements2[i-1].focus();                  
                    }
                }           

            }
        }           

        //alert(i);

    }
);

回答by nithin guptha

this library has similar implementation: keyboard-navigator.
shifts focus by getting next directional node by comparing coordinates.
but you will have to supply this function with all the nodes that you want to navigate upon(fromNodes).

这个库有类似的实现:keyboard-navigator
通过比较坐标获取下一个方向节点来转移焦点。
但是您必须为要导航的所有节点(fromNodes)提供此功能。

getNextDirectionalNode = function (activeNode,fromNodes,direction,coordinatesDeviationFactor=0){
var filteredNodes = []
var indexOfReturningElem = 0;

if(direction == "down"){
    for(var i=0; i<fromNodes.length; i++)
    {
        if( this.inDeviationRange(fromNodes[i].getBoundingClientRect().x,activeNode.getBoundingClientRect().x,coordinatesDeviationFactor) &&
            (fromNodes[i].getBoundingClientRect().y > activeNode.getBoundingClientRect().y)
          )
        {
            filteredNodes.push(fromNodes[i])
        }
    }
    indexOfReturningElem = 0;
    if( indexOfReturningElem >= 0 && (indexOfReturningElem <= filteredNodes.length-1) ){
        return filteredNodes[indexOfReturningElem];
    }
}

if(direction == "up"){
    for(var i=0; i<fromNodes.length; i++)
    {
        if( this.inDeviationRange(fromNodes[i].getBoundingClientRect().x,activeNode.getBoundingClientRect().x,coordinatesDeviationFactor) &&
            (fromNodes[i].getBoundingClientRect().y < activeNode.getBoundingClientRect().y)
          )
        {
            filteredNodes.push(fromNodes[i])
        }
    }
    indexOfReturningElem = filteredNodes.length - 1;
    if( indexOfReturningElem >= 0 && (indexOfReturningElem <= filteredNodes.length-1) ){
        return filteredNodes[indexOfReturningElem];
    }
}

if(direction == "right"){
    for(var i=0; i<fromNodes.length; i++)
    {
        if( this.inDeviationRange(fromNodes[i].getBoundingClientRect().y,activeNode.getBoundingClientRect().y,coordinatesDeviationFactor) &&
            (fromNodes[i].getBoundingClientRect().x > activeNode.getBoundingClientRect().x)
          )
        {
            filteredNodes.push(fromNodes[i])
        }
    }
    indexOfReturningElem = 0;
    if( indexOfReturningElem >= 0 && (indexOfReturningElem <= filteredNodes.length-1) ){
        return filteredNodes[indexOfReturningElem];
    }
}

if(direction == "left"){
    for(var i=0; i<fromNodes.length; i++)
    {
        if( this.inDeviationRange(fromNodes[i].getBoundingClientRect().y,activeNode.getBoundingClientRect().y,coordinatesDeviationFactor) &&
            (fromNodes[i].getBoundingClientRect().x < activeNode.getBoundingClientRect().x)
          )
        {
            filteredNodes.push(fromNodes[i])
        }
    }
    indexOfReturningElem = filteredNodes.length - 1;
    if( indexOfReturningElem >= 0 && (indexOfReturningElem <= filteredNodes.length-1) ){
        return filteredNodes[indexOfReturningElem];
    }
}

return null;
}