I have the following list of divs
<div id="multi-picker">
<div id="opt1">
<input type="checkbox"> Option 1
</div>
<div id="opt2">
<input type="checkbox"> Option 2
</div>
etc...
</div>
All working, but I'm not happy with the keyboard navigation. To navigate from opt1 to opt2 I need to press the tab key. Ideally I want to treat the options as a select and navigate with up/down arrow. Can this be done?
Alternatively... Is there any way to have a multi-select with the options styled with checkboxes to reflect the selection state of each option?
Approach: We can do this task by using nav-up, nav-down, nav-right, and nav-up CSS properties together. These properties are used to navigate through the navigation key from the keyboard. The properties define where to focus when the user is navigating by using the navigation key.
For smaller keyboards and many laptop keyboards, the arrow keys may be moved below the Enter and the right Shift . Also, some compact keyboards may move the arrow keys to the keypad and switch between the keypad and arrow keys by pressing the Num Lock key.
To detect the arrow key when it is pressed, use onkeydown in JavaScript. The button has key code. As you know the left arrow key has the code 37. The up arrow key has the code 38 and right has the 39 and down has 40.
I think you'll need javascript and using a plugin is an easier way to accomplish the task and maintain cross-browser functionality. However, here is a fiddle that, I think, kind of does what you want using just javascript. It defines additional attributes on your select elements and uses an onkeydown function to handle the navigation between the elements.
function keyPressed(e) {
var srcElement = e.target; // get the element that fired the onkeydown function
var dataset = false;
var selectList = false;
var next = "";
var prev = "";
if (srcElement.dataset) { // can we use HTML5 dataset?
dataset = true; // remember for later
// is this an element for which we care
if (srcElement.dataset.selectlist == 'true') {
selectList = true;
}
} else { // can't use HTML5 dataset, use getAttribute
if (srcElement.getAttribute('data-selectlist') == 'true') {
selectList = true;
}
}
// is it a select element and the user pressed either up arrow or down arrow
if (selectList && (e.keyCode == '38' || e.keyCode == '40')) {
// get the next and prev navigation options for this element
if (dataset) {
next = srcElement.dataset.next;
prev = srcElement.dataset.prev;
} else {
next = srcElement.getAttribute('data-next');
prev = srcElement.getAttribute('data-prev');
}
// up arrow was pressed and a prev element is defined
if (e.keyCode == '38' && prev != '') {
document.getElementById(prev).focus();
}
// down arrow was pressed and a next element is defined
if (e.keyCode == '40' && next != '') {
document.getElementById(next).focus();
}
// don't do native processing of the up or down arrow (page scrolling)
e.preventDefault;
}
}
document.onkeydown = keyPressed;
Here is the new html that contains the additional elements:
<div id="multi-picker">
<div id="opt1">
<input id="select1" type="checkbox" data-selectlist="true" data-prev="" data-next="select2"> Option 1
</div>
<div id="opt2">
<input id="select2" type="checkbox" data-selectlist="true" data-prev="select1" data-next=""> Option 2
</div>
</div>
This code is very specific to the problem presented and, though it may solve the problem, it would probably be better to use a general purpose plugin that would allow for more general application across your environment. You may also run into problems related to what your user expects the down and up arrow keys to do versus what you are doing by intercepting them.
In my experience I've run into problems where different browsers and even different end-user platforms present different behavior to the application making implementation consistency spotty. Many of the plugins are designed to eliminate that inconsistency and provide a cleaner, more intuitive interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With