0

I have the following code:

let codeBox1 = document.querySelectorAll(".codeBox1");
let codeBox2 = document.querySelectorAll(".codeBox2");
let codeBox3 = document.querySelectorAll(".codeBox3");
let codeBox4 = document.querySelectorAll(".codeBox4");

let OTPdigits = null;

const setOtpInputValue = () => {
 OTPdigits = codeBox1.value + codeBox2.value + codeBox3.value + codeBox4.value;
}

In the past, I was using querySelector and my code was working as well. But now I have to use querySelectorAll because I've added another 4-inputs (number type) to the DOM (one for Email OTP and the new one for Phone OTP).

Now I need to make codeBox1 to be either codeBox1[0] or codeBox1[1] when I access it inside setOtpInputValue() method. The logic should be based on visibility. Sinde always one of the OTP inputs is visible.

Any idea how can I handle that?

Martin AJ
  • 6,261
  • 8
  • 53
  • 111
  • PLease add desired output, not sure what your asking – 0stone0 Dec 22 '22 at 11:19
  • Does this answer your question? [A CSS selector to get last visible div](https://stackoverflow.com/questions/5275098/a-css-selector-to-get-last-visible-div) – Justinas Dec 22 '22 at 11:21
  • Or If I do understand, convert to an array: `[ ...document.querySelectorAll("input") ]` then you can use `arr[0]` etc – 0stone0 Dec 22 '22 at 11:21
  • @0stone0 the value of `OTPdigits` is `NaN` when I call `setOtpInputValue`. Because `codeBox1`, `codeBox2`, and ... are selected by `querySelectorAll`. – Martin AJ Dec 22 '22 at 11:23
  • But what is the desired output of OTPdigits? – 0stone0 Dec 22 '22 at 11:26

1 Answers1

1

Use reduce() to 'combine' the inputs. Use a fallback for the non-visible elements if needed

const allBoxes = [ ...document.querySelectorAll("input") ]

let OTPdigits = allBoxes.reduce(
  (p, c) => (p + c.value)
, '');

console.log(OTPdigits)
<input class='codeBox1' type='number'>
<input class='codeBox2' type='number' value=5>
<input class='codeBox3' type='number' style='display: none'>
<input class='codeBox4' type='number'>

If you just need the visible elements, change the selector to:

[ ...document.querySelectorAll("input:not([style='display:none'])") ]

Or use another way to check if the element is visible, so you can add an if in the reduce:

let OTPdigits = allBoxes.reduce((p, c) => 
    (p + (c.offsetParent === null ? '' : c.value))
, '');
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • Shouldn't initialValue for reduce be `''`? – Rajesh Dec 22 '22 at 11:47
  • Why? Op wants an integer as output right? – 0stone0 Dec 22 '22 at 11:48
  • For example, the otp is "1234", your output would be 10 instead of 1234. If total is the expected output, 1234 is same as 4321 which is wrong. Having input type number helps opening numeric keyboard on mobile devices but that does not mean we do arithmetic addition on them. – Rajesh Dec 22 '22 at 11:49
  • Ahh, your completely right, changed my answer. THanks! – 0stone0 Dec 22 '22 at 12:03
  • Thanks for your answer. I guess my question is not clear enough so your answer doesn't address my question. But I learned some tricks from your answer and Upvoted! – Martin AJ Dec 22 '22 at 12:21
  • If you, [as asked](https://stackoverflow.com/questions/74887742/how-can-i-access-element-selected-from-queryselectorall-based-on-visibility/74887881?noredirect=1#comment132158502_74887742) can provide your expected behaviour, with 1/2 examples, I can probably improve my answer. – 0stone0 Dec 22 '22 at 12:27