Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scrolling a UL element with keyboard navigation, odd jumping behavior

Tags:

jquery

scroll

I have a UL and when the arrow keys are pressed, I change the selection of the LI element by applying an .active class. This works fine, but now I need the UL to scroll as I move beyond the visible bounds. I have the following code which I also included in a working jsfiddle that duplicates my issue. Any help is appreciated.

$(document.documentElement).keyup(function (e) {
      var $generatorListItems = $('#genSelectFilter>li');
      var code = e.keyCode || e.which;
      var $element = $('#genSelectFilter>li.active');
      var listLength = $generatorListItems.length;
      var index = $element.index();
      var childIdx = 0;

      if (code == 40) {
        // arrow down
        if (index < listLength) {
          $generatorListItems.removeClass('active');
          childIdx = index + 2;
          $('#genSelectFilter').find('>li:nth-child(' + childIdx + ')').addClass('active');
          $('#genSelectFilter').animate({
            scrollTop: $('#genSelectFilter>li:nth-child(' + childIdx + ')').position().top
          }, 'slow');
        }

      } else if (code == 38) {
        // arrow up
        if (index > 0) {
          $generatorListItems.removeClass('active');
          $('#genSelectFilter').find('>li:nth-child(' + index + ')').addClass('active');
          $('#genSelectFilter').animate({
            scrollTop: $('#genSelectFilter>li:nth-child(' + index + ')').position().top
          }, 'slow');
        }

      }
});
like image 287
Gregg Avatar asked Nov 20 '25 01:11

Gregg


1 Answers

I fixed your code a little:

if (code == 40) {
    // arrow down
    if (index < listLength) {
        $element = $element.removeClass('active').next().addClass('active');
        $('#genSelectFilter').animate({
            scrollTop: $element.position().top + $("#genSelectFilter").scrollTop()
        }, 'slow');
    }
    e.preventDefault();
} 
else if (code == 38) {
    // arrow up
    if (index > 0) {
        $element = $element.removeClass('active').prev().addClass('active');
        $('#genSelectFilter').animate({
            scrollTop: $element.position().top + $("#genSelectFilter").scrollTop()
        }, 'slow');
    }
    e.preventDefault();
}

So you should use keydown event and prevent default behavior in case of up/down buttons to prevent default browser scrolling. I also changed animation part. Changing active class can also be simpler:

$element.removeClass('active').next().addClass('active');

Demo: http://jsfiddle.net/CEXcY/3/

like image 180
dfsq Avatar answered Nov 22 '25 04:11

dfsq



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!