Scrolling inner div on key down and up
By using tabIndex="-1"
attribute on each of the children of a container, the browser will automatically scroll the container to have the child with the current focus in-view.
Demo (vanilla javascript):
var listElm = document.querySelector('ul')
// Mark first list item
listElm.firstElementChild.focus()
// Event listener
window.addEventListener('keydown', onKeyDown)
// Event callback
function onKeyDown(e){
e.preventDefault()
var selectedElm = document.activeElement,
goToStart,
// map actions to event's key
action = {ArrowUp:"previous", Up:"previous", ArrowDown:"next", Down:"next"}
selectedElm = selectedElm[action[e.key] + "ElementSibling"];
// loop if top/bottom edges reached or "home"/"end" keys clicked
if( !selectedElm || e.key == 'Home' || e.key == 'End' ){
goToStart = action[e.key] == "next" || e.key == 'Home'
selectedElm = listElm.children[goToStart ? 0 : listElm.children.length - 1]
}
selectedElm.focus()
}
ul{
list-style: none;
border : 1px solid silver;
max-height: 170px;
padding : 0;
margin : 0;
scroll-behavior: smooth; /* nice smooth movement */
overflow : hidden; /* set to hidden by OP's request */
}
li{ padding:.5em; margin:0; }
li:focus{ background:LIGHTSALMON; outline:none; }
<ul>
<li tabIndex="-1">item 1</li>
<li tabIndex="-1">item 2</li>
<li tabIndex="-1">item 3</li>
<li tabIndex="-1">item 4</li>
<li tabIndex="-1">item 5</li>
<li tabIndex="-1">item 6</li>
<li tabIndex="-1">item 7</li>
<li tabIndex="-1">item 8</li>
<li tabIndex="-1">item 9</li>
<li tabIndex="-1">item 10</li>
<li tabIndex="-1">item 11</li>
<li tabIndex="-1">item 12</li>
<li tabIndex="-1">item 13</li>
<li tabIndex="-1">item 14</li>
<li tabIndex="-1">item 15</li>
</ul>
To make this list accessible (ARIA) read this
You can update your script to find the relative position of the selected element and scroll to it:
$(".someInput").on("keyup", function(e) {
$(".wrapper").show();
if (e.which == 40) {
$('.element:not(:last-child).element-hover').removeClass('element-hover').next().addClass('element-hover');
} else if (e.which == 38) {
$('.element:not(:first-child).element-hover').removeClass('element-hover').prev().addClass('element-hover');
}
//scroll to element:
$(".wrapper .inner_div").scrollTop(0);//set to top
$(".wrapper .inner_div").scrollTop($('.element-hover:first').offset().top-$(".wrapper .inner_div").height());//then set equal to the position of the selected element minus the height of scrolling div
});
http://jsfiddle.net/kMzR9/3/
There are several ways to implement it. and the exact solution for you need to consider your context.
Anyway, one possible solution is to use in the container div 'position: relative' and in the inner div (which hold the content) use 'position: absolute' and 'top: 0px'. When user press on the up/down arrows you changing the top property accordingly.
CSS:
.container {
position: relative;
height: 50px;
width: 200px;
overflow: hidden;
border: 1px solid blue;
}
.content {
position: absolute;
top: 0px;
}
JavaScript:
function moveContent(px) {
var top = $('.content').position().top;
$(".content").css("top", top+px);
}
$(document).keydown(function(e){
if (e.keyCode == 38) {
moveContent(-5);
}
if (e.keyCode == 40) {
moveContent(5);
}
});
HTML:
<div class="container">
<div class="content">
hello 1<br/>
hello 2<br/>
hello 3<br/>
hello 4<br/>
hello 5<br/>
hello 6<br/>
</div>
</div>
See my example in: http://jsfiddle.net/Kq2Qq/3/