I have the code below, which works well:
window.addEventListener('load', () => {
const values = ['input_1', 'input_2', 'input_3', 'input_4', 'input_5', 'input_6', 'input_7', 'input_8'];
document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
});
But I need a way to not have to go back to this code and add more elements to the variable like "input_9", "input_10" etc when I add more input boxes to my HTML code.
Basically a way to make that variable to accept any amount of "input_X" elements (like "input_∞" - I know ∞ does not exist in JS, just making a point).
Or maybe something else like a for
loop like the one below but it is not working because the input gets set to random input instead of the last active one, after the extension reloads:
window.addEventListener('load', () => {
const inputElements = document.querySelectorAll('.box-ipt');
const values = [];
for (let i = 0; i < inputElements.length; i ) {
values.push(`input_${i 1}`);
}
inputElements.forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box2', values[Array.prototype.indexOf.call(inputElements, input)]));
});
I also tried this but it breaks the extension/browser:
window.addEventListener('load', () => {
let i = 1;
for (;;) {
const values = [`input_${i}`];
document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box2', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
i ;
}
});
Any suggestions?
PS:I know the title sucks. Please suggest something else if you have a better idea.
EDIT:
More context to the JS code I have:
// Set focus after checking local storage for last focus
window.addEventListener('load', () => {
const baseanimdur = getComputedStyle(window.parent.document.documentElement).getPropertyValue('--base-anim-dur').replace('s', '');
const focusDelay = getComputedStyle(document.documentElement).getPropertyValue('--parent-grid-searchbox-focus-onload');
setTimeout(() => {
const inputValue = localStorage.getItem("myInputFocused_box1") || "";
const inputNumber = inputValue.match(/\d /)?.[0];
const input = inputNumber ? document.querySelectorAll(".box-ipt")[inputNumber - 1] : document.querySelectorAll(".box-ipt")[0];
input.focus();
}, baseanimdur / focusDelay);
});
// Function on get active input on Search BT click in order to if input box empty then BT click goes back to focused box
window.getActiveInputOnBTClick = () => {
const inputNumber = localStorage.getItem("myInputFocused_box1").match(/\d /)?.[0];
const input = inputNumber ? document.querySelectorAll(".box-ipt")[inputNumber - 1] : document.querySelectorAll(".box-ipt")[0];
input.focus();
};
/////////////// REFOCUS WHEN CLICKING BODY ( EMPTY SPACE ) ///////////////
window.addEventListener('load', () => {
const body = document.querySelector('body');
document.addEventListener('click', event => {
event.composedPath().includes(body) ? getActiveInputOnBTClick() : getActiveInputOnBTClick();
});
});
/////////////// Set local storage item for memorizing last focus
window.addEventListener('load', () => {
const values = ['input_1', 'input_2', 'input_3', 'input_4', 'input_5', 'input_6', 'input_7', 'input_8'];
document.querySelectorAll('.box-ipt').forEach((input) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', values[Array.prototype.indexOf.call(document.querySelectorAll('.box-ipt'), input)]));
});
CodePudding user response:
I think you should be looking to utilize the "index" of the forEach
loop to accomplish this. When you use querySelectorAll
to get all the inputs
in a page- the array you receive indexes each element in the order it appears on the page.
You could simply save that index to local storage and call focus()
on that element when you load the page. This scales to infinite inputs.
I can't make a code snippet using localStorage- but try running this locally:
//wait for page to load
window.addEventListener("load", () => {
//get all the Input elements on the page.
const inputEls = [...document.querySelectorAll("input")];
//set our focusPosition to either 0, or the localStorage Variable
const lastFocus = Number(localStorage.getItem("lastFocus")) || 0;
//iterate over each input element, using 'i' for the index
inputEls.forEach((el, i) => {
//if the index is equal to the lastFocus variable, focus that element
if (i == lastFocus) {
el.focus();
}
//add an event listener using the index to save that number to local storage
el.addEventListener("focus", () => {
localStorage.setItem("lastFocus", Number(i));
});
});
});
This kind of solution will work for any amount of inputs on the page, without any special naming or tagging.
The HTML of the page can literally just be
<input />
<input />
<input />
<input />
<input />
<input />
<input />
and this will work fine.
EDIT:
Here is a codePen for this example. The only change I added to the codePen is to wait 400ms after the page loads to change focus- as codepen loads other things and steals focus after the page loads. Click any input, and refresh the page - the input will refocus. https://codepen.io/brandonetter/pen/PoBzWQd
CodePudding user response:
As Brandon writes, you can just use the optional index
parameter of the forEach
loop to get the index of the input within the list. To achieve the same behaviour as before, just construct the name 'input_n' from the index by adding 1.
By generating the exact same format and numbering as before you don't need to adapt the other parts of the existing code.
window.addEventListener('load', () => {
document.querySelectorAll('.box-ipt').forEach((input, index) => input.onfocus = (event) => localStorage.setItem('myInputFocused_box1', 'input_' (index 1)));
});