Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shift focus with arrow keys in JavaScript

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.

like image 553
Kay Lamerigts Avatar asked Jun 18 '12 18:06

Kay Lamerigts


3 Answers

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/

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

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

like image 186
Cranio Avatar answered Nov 04 '22 11:11

Cranio


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

like image 25
user2462210 Avatar answered Nov 04 '22 11:11

user2462210


Preview - 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');
    }
});​
like image 1
Jānis Avatar answered Nov 04 '22 11:11

Jānis