Function working on most but not all buttons with addEventListener click event

I’m a relative beginner and sure I’m doing something wrong, but I’ve racked my brains and can’t figure out what…

I’ve got an onscreen keyboard, with the row causing issues as follows:

<div>
                <button id="deleteButton">Delete</button>
                <button class="letterButton" id="Z">Z</button>
                <button class="letterButton" id="X">X</button>
                <button class="letterButton" id="C">C</button>
                <button class="letterButton" id="V">V</button>
                <button class="letterButton" id="B">B</button>
                <button class="letterButton" id="N">N</button>
                <button class="letterButton" id="M">M</button>
                <button id="submitButton">Enter</button>
            </div>

In my JavaScript, I have this function:

const buttons = document.querySelectorAll("button");
buttons.forEach((button) => {
    button.addEventListener('click', () => {
        button.classList.add('temporary-color-change');
        setTimeout(() => {
            button.classList.remove('temporary-color-change');
        }, 1000);
    });
});

The CSS is here:

#deleteButton,
#submitButton {
    min-width: 30px;
    border-radius: 8px;
    background-color: #068FFF;
    color: #151922;
    font-size: 12px;
    font-weight: bold;
    padding: 5px 5px;
    border: 2px solid #068FFF;
    width: 60px;
    height: 30px;
}

.temporary-color-change {
    background-color: #151922;
    color: #068FFF;
}

The function should change the colour of each button as it’s clicked (to give feedback to the user that it has been clicked).

However, the function only works on the letter buttons and not on deleteButton or submitButton. I’ve console-logged the Nodelist and found it is correctly identifying all buttons, including delete and submit. The only difference that I can see is that delete and submit have their own other functions, but these are also called with addEventListener(“click”) and shouldn’t interfere as far as I can tell. The other functions also have nothing to do with CSS or colours. These other functions on delete and submit do work correctly.

I’ve done a considerable amount of Googling and can’t find anything that solves the problem. Any ideas?

Your problem probably has a simple solution which I see a member replying to at present. What I would comment on is the nine event listeners which actually consume a goodly amount of resources. One is better than nine.

To do this, we register the listener on the parent container and allow all clicks to bubble up to that element. We then poll the event target where the click is detected and apply the handler code to that node.

If this sounds interesting, then look up ‘delegation’ to see how this is implemented. Pretty sure this has been written about in the forums, as well.

1 Like

Please go ahead and share your solution. I know the cause of the issue, but I think you have a stronger grasp on this topic and would be able to offer a more helpful explanation.

I expect there is a lot of streamlining that could be done with the code, but I am trying to get it all basically working first and then work on performance and such. The bug in question is one of the few that remain, and I’m sure there’s something simple I’m overlooking, but I haven’t been able to figure out what.

Then I will defer to your insight. Please go ahead and post your reply.

id has a higher specificity than class.

For the Delete and Submit buttons, you have written a CSS rule which targets these buttons based on their id. Among other properties, the rule also designates values for the background-color and color properties.

In your JavaScript, you are attaching click event listeners to these two buttons.

When the Delete or Submit button is clicked, it fires the event listener. A temporary-color-change class is added to these buttons for a brief time. In your CSS, you have a rule for temporary-color-change class.

But the specificity of a rule based on id is higher than the specificity of a rule based on class. So, your temporary_color_change CSS rule doesn’t over-ride the values you assigned in the id rule.

1 Like

Thanks for your answer. However, that’s one of the things I tried earlier to fix it (assigning those two buttons a class instead of an ID) and the problem persists even when I remove all references to their IDs in the code.

Suppose you changed your HTML from

<button id="deleteButton">Delete</button>
<button id="submitButton">Enter</button>

to

<button class="deleteButton">Delete</button>
<button class="submitButton">Enter</button>

and amended your CSS to:

.deleteButton,
.submitButton {
    min-width: 30px;
    border-radius: 8px;
    background-color: #068FFF;
    ...
}

.temporary-color-change {
    background-color: #151922;
    color: #068FFF;
}

then it would work PROVIDED the temporary-color-change rule is below the .deleteButton, .submitButton { rule because now both rules have equal specificity and the latter rule overrides the earlier rule.

Not the best way to rectify the issue, so I am interested in seeing mtf’s solution.

1 Like

So I had added another class to the buttons before (useful-button, because I’m not that creative) and it still wasn’t working, but what actually fixed it from your answer was moving the temporary-button-class down below the others. I had no idea that the order of CSS rules would affect the code in that way. Thanks so much :slight_smile:

When two selector rules with equal specificity are in conflict, the one that is farther down the cascade takes precedence.

1 Like