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

时间:2012-06-18 18:17:46

标签: javascript jquery

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

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

$(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

});

这个想法是获得所有可聚焦的元素,而不是选择适合箭头和移位焦点的元素。

我无法让这段代码工作(它包含一个错误),而且我并不完全确定它会工作。

Thnx提前

[编辑]:我想我有点模糊。我不仅想要左右移动,而且还要上下移动。

7 个答案:

答案 0 :(得分:24)

我会做的更简单。只需在应该具有此功能的对象中添加一个公共类(f.ex。“move”)并使用:

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

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

        }
    }
);
​

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

此代码很多更简单,希望能够提供您需要的所有功能。

只需确保控件的顺序正确,否则无效。

答案 1 :(得分:1)

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

<强> 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:

// 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');
    }
});​

答案 2 :(得分:1)

经过多次试验和错误,我开发了这个有效的代码:

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);
    }
});

右箭头作为标签

左箭头作为班次选项卡

答案 3 :(得分:0)

通过检查一些文章并叠加流链接

来实现
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/

答案 4 :(得分:0)

这很好用

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var model = {
  circle1: { x: 200, y: 200 },
  circle2: { x: 200, y: 200 }
};

var radius = 50;

function view(ctx, model) {
  function circle(c) {
   ctx.beginPath();

   ctx.beginPath();
   ctx.arc(c.x, c.y, radius, 0, 2 * Math.PI, true); 
   ctx.fillStyle = "#FF6A6A";
   ctx.fill();
   ctx.stroke();
 }

 // clear canvas
 ctx.clearRect(0, 0, canvas.width, canvas.height);

 circle(model.circle1);
 circle(model.circle2);
}

function redraw() {
  view(ctx, model);
}

redraw();

function getCircleForPosition(x, y) {
  function intersect(a, b) {
    var d2 = Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2);
    r2 = Math.pow(radius, 2);
    return d2 < r2;
  }

  return [model.circle1, model.circle2].find(circle => intersect(circle, { x, y }));
}


canvas.addEventListener('mousedown', function(e) {
  model.dragging = getCircleForPosition(e.pageX, e.pageY);
}, 0);
canvas.addEventListener('mouseup', function() {
  model.dragging = undefined;
}, 0);
canvas.addEventListener('mousemove', function(e) {
  if (model.dragging) {
    model.dragging.x = e.pageX;
    model.dragging.y = e.pageY;
    redraw();
  }
}, 0);

答案 5 :(得分:0)

以上解决方案均不适合我。这是我的。看起来很困难,但实际上非常容易。创建链接的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);

    }
);

答案 6 :(得分:0)

此库具有类似的实现: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;
}