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>
CodePudding user response:
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:
- we select all the buttons and cache them in the
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 index0
, second button will be at the index1
and so on). - initially, all the button do not have the
data-is-focused
attribute which will be considered as if that attribute is set to0
. - once
"b"
is pressed we make some checks:- get the currently focused button by finding the index of the button that has the
data-is-focused
attribute set to1
. - if no button is focused then we manually set the index to
0
so we focus the first button. - Otherwise, if we find the currently focused button, we increment the index.
- if we reach the last button, the index equals the number of buttons - 1 (remember, indexes start from 0) then we simply set
0
to the index of the button to be focused.
- get the currently focused button by finding the index of the button that has the
To illustrate, here's a live demo, that handles returning back to the first button once we reach the last one (as described above):
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>
CodePudding user response:
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();
}
});
CodePudding user response:
const boxes = document.querySelectorAll('button');
boxes.forEach(box => {
box.addEventListener('click', function handleClick(event) {
//extra logic
var idnumber = parseInt(event.target.getAttribute("id"));
var btnid = idnumber 1;
if (idnumber == 5) {
removeStyle();
document.getElementById("1").setAttribute('style', 'background-color: yellow;');
} else {
removeStyle();
document.getElementById(btnid).setAttribute('style', 'background-color: yellow;');
}
});
});
function removeStyle() {
boxes.forEach(box => {
box.setAttribute('style', 'background-color: none;');
});
}
<button id="1">Button 1</button><br>
<button id="2">Button 2</button><br>
<button id="3">Button 3</button><br>
<button id="4">Button 4</button><br>
<button id="5">Button 5</button><br>