Scrolling <ul> with arrow keys
by swordys
HTML
<ul>
<li class="selected">Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
<li>Element 6</li>
<li>Element 7</li>
<li>Element 8</li>
<li>Element 9</li>
<li>Element 10</li>
<li>Element 11</li>
<li>Element 12</li>
<li>Element 13</li>
<li>Element 14</li>
<li>Element 15</li>
</ul>
CSS
ul {
height: 120px;
overflow-y: scroll;
font-size: 18px;
}
li.selected {
background: #ccc;
}
JavaScript
var ul = document.querySelector('ul');
var nodes = document.querySelectorAll('li');
var selected = 0;
[].forEach.call(nodes, function(el) {
el.addEventListener('click', function() {
select(this);
})
});
document.addEventListener('keydown', function(e) {
if (e.keyCode === 38) { // up
select(nodes[selected - 1]);
}
if (e.keyCode === 40) { // down
select(nodes[selected + 1]);
}
e.preventDefault();
});
function select(el) {
var s = [].indexOf.call(nodes, el);
if (s === -1) return;
selected = s;
var elHeight = $(el).height();
var scrollTop = $(ul).scrollTop();
var viewport = scrollTop + $(ul).height();
var elOffset = elHeight * selected;
console.log('select', selected, ' viewport', viewport, ' elOffset', elOffset);
if (elOffset < scrollTop || (elOffset + elHeight) > viewport)
$(ul).scrollTop(elOffset);
document.querySelector('li.selected').classList.remove('selected');
el.classList.add('selected');
}