1

In this web app I'm building to keep score in some game, I'm trying to change the background color of a certain element when your score reaches 6000 points or more. It should respond to an <input> element of type = 'number'. I think I'm on the right track but so far I can't get it to work (and I'm not 100% sure that onchange is the right event type).

Here is the code I got now.

In the html-file:

<input type="number" id="scorePlayer1" value=0 readonly="true">

In JS:

const scorePlayer1 = document.querySelector("#scorePlayer1");
const scoreBackGrPlayer1 = document.querySelector(".scoreBord #scorePlayer1");


scorePlayer1.addEventListener('change', () => {
    const currentScorePlayer1 = scorePlayer1.value;
    if (currentScorePlayer1 >= 6000) {
        scoreBackGrPlayer1.style.backgroundColor = ("gold");
    };
})

Thanks in advance for your help!

UPDATE: here is a reprex of my current code:

  <input type="number" id="scorePlayer1" value=0 readonly="true">
  <button id="addButton">+ 1000</button>
const addButton = document.querySelector("#addButton");
const scorePlayer1 = document.querySelector("#scorePlayer1");

// Adding 1000 points
addButton.addEventListener('click', () => {
    scorePlayer1.value = +scorePlayer1.value + 1000;
    handleValueChange(scorePlayer1.value);
});

// Change color on points >= 6000
scorePlayer1.addEventListener('input', (e) => {
    const currentScorePlayer1 = e.target.value;
    if (currentScorePlayer1 >= 6000) {
        scorePlayer1.style.backgroundColor = ("gold");
    };
})
  • `change` only fires when the input loses focus. How is the input updated? Or better, how is the `score` incremented? – pilchard Jun 21 '22 at 08:31
  • BTW, `scorePlayer1 ` and `scoreBackGrPlayer1` are the same element, since IDs have to be unique. – Barmar Jun 21 '22 at 08:37
  • @Barmar scoreBackGrPlayer1 is supposed to query the parent of `#scorePlayer1`, an element with a class of `.scoreBord`. – HelterStelter17 Jun 21 '22 at 09:19
  • You can't use a selector to select a parent like that. Use `currentScorePlayer1.closest(".scoreBord")` – Barmar Jun 21 '22 at 09:20
  • @pilchard I use different buttons with onclick events that can manipulate the value (got that working alright). For example, incrementing the score with +100 goes like this: ```plusHPlayer1Button.addEventListener('click', () => { scorePlayer1.value = +scorePlayer1.value + 100; handleValueChange(scorePlayer1.value); });``` – HelterStelter17 Jun 21 '22 at 09:22
  • @Barmar I fiddled around with it and found out I don't need to query the parent at all, so I took the `const scoreBackGrPlayer1` out of the code entirely. I can just address #scorePlayer1 directly to change it's background color (I got that working with a onclick event but not yet with the oninput I'm trying to make now. Thanks for the heads up! – HelterStelter17 Jun 21 '22 at 09:34
  • Is the `scorePlayer1` input ever directly edited by the user? If not I wouldn't use an input at all and would simply handle the score in the button click callback. Post more of your code, ideally as a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) demonstrating the problem – pilchard Jun 21 '22 at 09:49
  • @pilchard no it's not, it's set to `readonly=true`. I updated my question with a reprex (hope it's what you asked for) – HelterStelter17 Jun 21 '22 at 10:49
  • So just put the background change in the `click` handler or in whatever `handleValueChange()` is? – pilchard Jun 21 '22 at 10:53

2 Answers2

1

In you case I would use the input event. In contrast to the change event: "The input event fires when the value of an input, select, or textarea element has been changed."

const scorePlayer1 = document.getElementById('scorePlayer1');


scorePlayer1.addEventListener('input', (e) => {
    if (e.target.value >= 6000) {
        scorePlayer1.style.backgroundColor = 'gold';
    }
})

See the docs.

Norbert Bartko
  • 2,468
  • 1
  • 17
  • 36
  • 1
    Hi Norbert, thanks for your help. I made the changes you suggested but it doesn't work just yet... Someone else pointed out to me that the `const scoreBackGrPlayer1` selected the same ID as `const scorePlayer1` so I got rid of the former one entirely, so now the action in my if-statement is `scorePlayer1.style.backgroundColor = ("gold");` – HelterStelter17 Jun 21 '22 at 09:38
0

Programatically changing the input value won't trigger the input event (or the 'change' event which actually only fires when the input loses focus). You can trigger the event manually (see: Trigger Change event when the Input value changed programmatically?)

But it is much more direct to handle the side effect in the handler itself.

const addButton = document.querySelector("#addButton");
const scorePlayer1 = document.querySelector("#scorePlayer1");

addButton.addEventListener('click', () => {
    let currentScorePlayer1 = scorePlayer1.valueAsNumber;
    let updatedScorePlayer1 = currentScorePlayer1 + 1000;
    
    scorePlayer1.value = updatedScorePlayer1;
    
    if (updatedScorePlayer1 >= 6000) {
        scorePlayer1.style.backgroundColor = ("gold");
    };
    
    //handleValueChange(scorePlayer1.value);
});
<input type="number" id="scorePlayer1" value=0 readonly="true">

<button id="addButton">+ 1000</button>
pilchard
  • 12,414
  • 5
  • 11
  • 23
  • Yes, that does it. Thank you very much! With your alterations as a starting point I also managed to make it work with a subtract button and change the color to red when a player has minus points, and back to neutral when `(points >= 0) && (points < 6000)` – HelterStelter17 Jun 21 '22 at 13:08
  • That's great, I'm glad you were able to extend the pattern! You could also abstract the logic into a separate function to handle any player's score. – pilchard Jun 21 '22 at 13:40
  • O, that's next level... would really clean up my code though. Cause now I have all this different functions for adding and subtracting for every individual player (5 buttons per person x 4 players). Is it hard to do? – HelterStelter17 Jun 21 '22 at 13:56
  • Give it a try and if you get stuck post another question and I'll take a look. – pilchard Jun 21 '22 at 13:57