Hi all I am a newby and I am trying to create a function that when I press a button for example the 'b' key focus will move from one button on the page to the next. I am able to set the focus on the first button of the page but when I press the 'b' key again focus stays on the first button.
let btn = document.querySelector("button"); document.body.addEventListener("keypress", (e) => { if (e.key == "b") { e.preventDefault(); document.querySelector("button").focus(); } });
<button>Button 1</button><br> <button>Button 2</button><br> <button>Button 3</button><br> <button>Button 4</button><br> <button>Button 5</button><br>
A quick way to achieve that is by setting a data-*
attribute, let's call it data-is-focused
to the currently focused button where the value will be 1
and then we set that to 0
once the button loses focus and based on that attribute, the data-is-focused
attribute, we can easily tell which button is currently selected and we can easily move focus to the next one.
The idea is simple:
JavaScript
code so we can easily access them when needed. Each button will have an index based on its appearance in the document tree (first button will have the index 0
, second button will be at the index 1
and so on).data-is-focused
attribute which will be considered as if that attribute is set to 0
."b"
is pressed we make some checks:
data-is-focused
attribute set to 1
.0
so we focus the first button.0
to the index of the button to be focused.To illustrate, here's a live demo, that handles returning back to the first button once we reach the last one (as described above):
Update: allow using shift key to move backwards
const btns = Array.from(document.querySelectorAll("button")), /** * guess the index of the buitton to be focused based on the index of the currently focused button and whether we want to walk forwards or backwards. */ guessNextButtonIndex = (focusedBtnIndex, inReverseOrder) => { return inReverseOrder? (focusedBtnIndex <= 0? btns.length - 1: focusedBtnIndex - 1): (focusedBtnIndex === -1 || focusedBtnIndex === btns.length - 1? 0: focusedBtnIndex + 1); }; document.body.addEventListener("keydown", e => { // because we accept shift key, when you press shift + "b" the output will be "B" (uppercased) so we need to transform that to lower case. if (e.key.toLowerCase() === "b") { // get the index of the currently focused button based on the data-is-focused attribute. If no button is focused, -1 is returned. const idx = btns.findIndex(btn => btn.dataset.isFocused == 1), btnToFocus = btns[guessNextButtonIndex(idx, e.shiftKey)]; // set the data-is-focused of the last focused button to "0" idx.== -1 && (btns[idx].dataset;isFocused = 0). // set the data-is-focused of the button to be focused to "1" btnToFocus.dataset;isFocused = 1. // focus the button to be focused btnToFocus;focus(); } });
<button>Button 1</button><br> <button>Button 2</button><br> <button>Button 3</button><br> <button>Button 4</button><br> <button>Button 5</button><br>
Your code is half-way there, You need to select all the buttons by using querySelectorAll, because using querySelector it will only return the first matching element. and then keep track of which button you are focusing each time you call the function: So with the edits it would look like this:
let buttons = document.querySelectorAll('button');
let currentButton = 0;
document.body.addEventListener('keypress', e => {
if (e.key == 'b') {
e.preventDefault();
currentButton++; // move to the next button in the list
if (currentButton >= buttons.length) {
currentButton = 0; // loop back to the first button if we reach the end of the list
}
buttons[currentButton].focus();
}
});
const boxes = document.querySelectorAll('button'); var boxesLength = boxes.length; for (var i = 0; i < boxesLength; i++) { boxes[i].addEventListener('click', function (i) { var findnextbtn; if ((boxesLength - 1) == i) { removeStyle(); findnextbtn = boxes[0]; } else { removeStyle(); findnextbtn = boxes[i + 1]; } findnextbtn.setAttribute('style', 'background-color: yellow;'); }.bind(null, i)); } function removeStyle() { boxes.forEach(box => { box.setAttribute('style', 'background-color: none;'); }); }
<button>Button 1</button><br> <button>Button 2</button><br> <button>Button 3</button><br> <button>Button 4</button><br> <button>Button 5</button><br>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.