I'm presenting my projects as flip-cards in my portfolio. Originally, the project data was hard-coded in my index.html, the cards flip on hover on larger screen and on click on smaller screens.
I decided to move all the hard-coded data to an object in my script.js to create a flip-card for each project in that object dynamically. No issue here. (Next to that, I also added a loading background animation to the cards, so that those are only showing their content after a few secs. Also no issue here.)
However, now that I'm creating the flip-cards to the DOM with JS, the event listener attached to the cards is not working as it used to. Logging the cards to the console does show me a full node list of all the created divs, but nothing happens when clicking the cards on smaller screens.
I feel like this is a scope issue but I'm not sure. I've tried placing the event listener function:
createProjectCard(projects), right after creating and appending the flip-cards: no response or error thrown, but node list does contain all the created cardscreateProjectCard(projects), right after the setTimeout() function: no response or error thrown, but node list does contain all the created cardscreateProjectCard(projects) and within the setTimeout() function (at its bottom): here something weird happens, only the cards for which the index is an uneven number can be flipped on click; also, if I console.log('clicked') to test the event listener, all cards are logging 'clicked' instead of just the one I clicked.createProjectCard(projects): no response or error thrown, but node list does contain all the created cardsI'm wondering if this issue comes from nesting innerFlipCards.forEach inside projects.forEach, but I don't know how else to access the innerFlipCards since they are created within projects.forEach.
Old code with hard coded project data, but flip-cards work on mobile: https://codepen.io/awelie_go/pen/KKXPQBJ
New code with dynamic project data, but flip-cards don't work on mobile: https://codepen.io/awelie_go/pen/OJxLQvQ
If anyone has a hint on how to fix this, I would love to hear. Thanks for your time
Seems like there is a couple of issues in the non-working code.
Due to the setTimeout inside of your loop, the cards aren't created immediately, but
const innerFlipCards = document.querySelectorAll(".flip-card-inner");
tries to get a list of them and loop through them, however, since there are no cards yet, the result is empty.
If however we remove the timeout, there is another issue. The same line of code mentioned above (which is followed by a loop through the results), executes on every loop iteration.
What that means is, if you have 3 cards, your first card will have 3 click event handlers, your second will have 2 and third only 1. Which explains why only odd cards worked. It would be similar to if the user clicked the 1st card 3 times quickly.
So how should we remedy this? A more straightforward fix would be to create flip-card-inner div with createElement, add your event listeners to it and append it to your flip-card. That way you can set everything up at creation, instead of having to query for your cards later and worry about timings.