javascriptinputevent-listener

Why the input eventlistener with change is not getting the value


I have these three inputs of type number where you can only add one number and you can replace it by pressing any other number between 0 and 9. I have 2 eventlisteners on these inputs the first is to be able to change the value of the inputs by pressing a number between 0 and 9 (by using 'keyup').
The second eventlistener is there for detecting input and then calculating the total of the three input, when the correct total is calculated an alert is thrown. What I have noticed is if I want a total of 27 for example I need to add 9 + 9 + 9 in inputs.
However if I add 9 + 8 + 9 but then without deleting the 8 and just replacing it by pressing 9 I don't get the alert. To get the total the better seems to do it within the event listener with 'keyup'.
So why is that? When pressing the 9 button it is still an input event as well?

const element1 = document.querySelector('.element1')
let total = 0
let desiredTotal = 27

    let allInputs = Array.from(element1.getElementsByTagName('input'))
    allInputs.forEach((input)=>{
        input.style.border = '2px solid blue'
        input.addEventListener('keyup', (e)=>{
            if(e.target.value.length === 1 && parseFloat(e.key) >= 0 && parseFloat(e.key) <=9){
                    e.target.value = e.key
            }
        })
    })


    allInputs.forEach((input)=>{
        let value
        input.addEventListener('input', (e)=>{
            let value = parseFloat(input.value)
            total += value
            console.log(total)
            if(total === 27) alert('you won!')
        })

    })
input{
    width: 2ch;
}

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

input[type=number] {
  appearance: textfield;
}
<body>
    <div class="element1">
        <input type="number" name="" id="input1" onKeyPress="if(this.value.length===1 || event.key == 'e') {return false}">
        <input type="number" name="" id="input2" onKeyPress="if(this.value.length===1 || event.key == 'e') {return false}">
        <input type="number" name="" id="input3"onKeyPress="if(this.value.length===1 || event.key == 'e') {return false}">
    </div>
    <p>Try to obtain a total of 27</p>
    <p>Try to place 9 9 and then 9 you get the alert</p>
    <p>Try to place 9 6 and then 9 but then change(without deleting) but pressing on the 6 containing input the number 9 you won't get the alert</p>
</body>


Solution

  • Don't mix HTML input onKeyPress and JS EventListener.
    Do everything in JS

    document.querySelectorAll('.element1 input').forEach( (inElm,_,All) =>
      {
      inElm.addEventListener('keydown', e =>
        {
        if (/\d/.test(e.key)) e.target.value = e.key; // accept only digitals 
     
        if (e.key !== 'Tab')  e.preventDefault();    // do ignore input event
    
        let Total = 0;
        All.forEach( inN => Total += inN.valueAsNumber );
    
        console.clear();
        console.log( 'Total', Total );
        });
      });
    input[type="number"] {
      width      : 2ch;
      border     : 2px solid blue;
      text-align : center;
      margin     : .5em;
      appearance : textfield;
      }
    <div class="element1">
      <input type="number" value="0" >
      <input type="number" value="0" >
      <input type="number" value="0" >
    </div>
    <p>Try to obtain a total of 27</p>