Reputation: 494
I have a set of buttons that trigger different functions on the page. The user can hover on the desired button and click on it, as normal, or can navigate through the buttons with the up and down arrow keys and press the enter key to trigger the corresponding function.
Using the arrow keys, the button that is currently focused has a different color from the others (green). Buttons that are hovered are also green.
As things are right now, it is possible for more than one button to be green: The hovered one and the focused one. I don't want this to happen.
The ideal solution would be to change the focus to whichever button is hovered. Is this possible? If so, how can I achieve this? Preferebly without resorting to jQuery.
This is what I am working with:
var inputs = document.getElementsByClassName("move");
for (var i = 0; i < inputs.length; i++)
inputs[i].addEventListener("keyup", function(event) {
if (event.keyCode == 38) {
if (this.previousElementSibling) {
this.previousElementSibling.focus();
}
} else if (event.keyCode == 40) {
if (this.nextElementSibling) {
this.nextElementSibling.focus();
}
}
}, false);
.move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}
.move:hover, .move:focus {
background-color: greenyellow;
}
<input class="move" type="button" value="1" autofocus />
<input class="move" type="button" value="2" />
<input class="move" type="button" value="3" />
Upvotes: 0
Views: 1845
Reputation: 4936
I'm not a big fan of using mouseover to shift focus. If you don't want the hover state to display if a field has focus you can add a wrapping div and use focus-within.
As focus-within is not supported in ie and edge you can add mimic this using a .enable-hover class you toggle on focus/blur
const wrapper = document.querySelector('.group');
[].slice
.call(document.querySelectorAll('.move'))
.map(input => {
input.addEventListener('focus', e => {
wrapper.classList.remove('enable-hover')
});
input.addEventListener('blur', e => {
wrapper.classList.add('enable-hover')
});
input.addEventListener('keyup', e => {
if (e.keyCode == 38 && input.previousElementSibling)
input.previousElementSibling.focus();
if (e.keyCode == 40 && input.nextElementSibling)
input.nextElementSibling.focus();
});
})
.group:not(:focus-within) > .move:hover,
.group.enable-hover > .move:hover,
.move:focus {
background: greenyellow;
}
.move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}
<div class="group">
<input class="move" type="button" value="1" autofocus />
<input class="move" type="button" value="2" />
<input class="move" type="button" value="3" />
</div>
Upvotes: 1
Reputation: 6151
You can use the mouseover
event with focus
function for that. Should work fine...
var inputs = document.getElementsByClassName("move");
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("keyup", function(event) {
if (event.keyCode == 38) {
if (this.previousElementSibling) {
this.previousElementSibling.focus();
}
} else if (event.keyCode == 40) {
if (this.nextElementSibling) {
this.nextElementSibling.focus();
}
}
}, false);
inputs[i].addEventListener("mouseover", function(event) {
this.focus();
}, false);
}
.move {
display: block;
width: 200px;
padding: 10px;
text-align: center;
background-color: aquamarine;
margin-top: 10px;
}
.move:hover, .move:focus {
background-color: greenyellow;
}
<input class="move" type="button" value="1" autofocus />
<input class="move" type="button" value="2" />
<input class="move" type="button" value="3" />
Upvotes: 1