0

I'm trying to make it so that hovering over any of the squares inside the play area adds the class "darken" to them. The play area generates as expected, but instead of adding the class, any time I hover over the squares in question I get "Uncaught TypeError: cannot read properties of undefined (reading 'add') at HTMLDivElement.".

I've tried both the line with the event listener in the "createPlayArea" function and the commented out variable + function combo below and I end up with the exact same error in my chrome console.

const squareAmount = 50;
const dimensions = '10px';

function createPlayArea() {
    for (i = 0; i < (squareAmount * squareAmount); i++) {
        let squares = document.createElement('div')
        squares.setAttribute('style', 'display: flex; flex-wrap: wrap;')
        squares.classList.add('square')
        squares.style.height = dimensions;
        squares.style.width = dimensions;
        squares.addEventListener('mouseover', square => square.classList.add('darken'))
        playArea.appendChild(squares)
    }
}

createPlayArea()

// let playSquares = document.querySelectorAll('.square')

// function pen() {
//     playSquares.forEach(square => square.addEventListener('mouseover', function (e) {
//         e.classList.add('darken')
//     }))
// }

// pen()
<style>
.square {
  background-color: gray;
}

.darken {
  background-color: black;
}
</style>

<div id="playArea">

</div>

What I was expecting is for the .darken class to be added to the squares that get hovered over. All I got was this stupid error :')

zouabi
  • 649
  • 1
  • 7
  • 16
  • inside an event handler, since `e` is the event, not the element, use `e.target.classList.add` or `this.classList.add` or even `square.classList.add` – Jaromanda X Aug 20 '23 at 03:46
  • Appears horribly ambiguous, what is the add() method you are calling, does it set an attribute class=. In the square (presumably DIV) with the style object. Is "add". And "class list" your custom code or part of standard supplied objects. make one square, you don't need a for()? – Samuel Marchant Aug 20 '23 at 03:48
  • @JaromandaX excellent answer! You both solved my problem and taught me something new, thank you. I'm trying to accept your comment as an answer, but I don't see the grey checkmark that's supposed to be beside what you wrote according to google... I'm new here - if I'm missing something, please let me know. Also if you don't mind, what was wrong with the ```squares.addEventListener('mouseover', square => square.classList.add('darken'))``` during the createPlayArea() function? Isn't that equivalent to the pen() function, just added during the creation of the elements instead of after? – Nightman9001 Aug 20 '23 at 04:20
  • nah, I'm not going to post it as an answer, it's a comment because it was a suggestion only - I think this sort of confusion has been asked/answered before, I just can't find it – Jaromanda X Aug 20 '23 at 04:23
  • @JaromandaX Ah I see... I looked through about a dozen questions with similar titles and couldn't find anything relevant, my apologies if this is a duplicate. – Nightman9001 Aug 20 '23 at 04:25
  • no need to apologise, some problems are harder to search for than others – Jaromanda X Aug 20 '23 at 04:30
  • Don't set the `squares`' `style` property. Instead put the CSS in `.square`'s style. – MfyDev Aug 20 '23 at 04:46
  • Put brackets in the arrow function `squares.addEventListener('mouseover', square => square.classList.add('darken'))` like this `squares.addEventListener('mouseover', square => {square.classList.add('darken'))}`, this will prevent the function from returning some unwanted values. – MfyDev Aug 20 '23 at 04:52
  • Also, don't access the 'play area' using ID population. Instead declare your own variable, e.g. `let area = document.getElementById("playArea")`. – MfyDev Aug 20 '23 at 04:56
  • @MfyDev Good feedback, thanks! Can you clarify what you're referring to when you say "ID population"? I haven't heard that term used before. – Nightman9001 Aug 20 '23 at 05:01
  • @Nightman9001 That means that all elements with `id` are added under that ID to the `window` object. For example, `
    ` is accessable through `window.myID`. It's a bad practice to make your app depend on this "feature". You can [read more here](https://stackoverflow.com/a/3434388/22217619).
    – MfyDev Aug 21 '23 at 06:36

1 Answers1

0

Courtesy of JaromandaX, I've come to realize that

playSquares.forEach(square => square.addEventListener('mouseover', function (e) {
e.classList.add('darken')
}

should have been

playSquares.forEach(square => square.addEventListener('mouseover', function () {this.classList.add('darken')}

//OR

playSquares.forEach(square => square.addEventListener('mouseover', function () {square.classList.add('darken')}

//It looks like the following should work too but I ended up with an error here as well.

playSquares.forEach(square => square.addEventListener('mouseover', function () {e.target.classList.add('darken')}