Reputation: 1
I'm trying to apply a feature that hides or shows the back of dynamically created cards when clicked (and vice versa). The first function worked, but it only applied to the template, so I found that the way to solve it was to delegate the event to an element that was already present in the HTML, I tried to do it but it's not working.
This is the feature I've been working on
let isFlipped = false;
const mainContainer = document.getElementById("root");
mainContainer.addEventListener('click', function(){
if(event.target.matches('.button-container')) {
const card=event.target.closest('.card-container');
turnCard(card);
if (event.target.matches('.back')) {
const card=event.target.closest('.card-container');
returnCard(card);
}
}
})
function turnCard(card) {
const frontCard=document.querySelector("#front-card");
const backCard=document.querySelector("#back-card");
if (isFlipped) {
backCard.classList.toggle('hide');
frontCard.classList.toggle('hide');
}
isFlipped = !isFlipped;
}
function returnCard (card){
const frontCard=document.querySelector("#front-card");
const backCard=document.querySelector("#back-card");
if(!isFlipped){
backCard.classList.toggle('hide');
frontCard.classList.toggle('hide');
isFlipped = !isFlipped;
}
}
and this is the cards structure
data.forEach(element => {
const cardItem = document.createElement('li');
cardItem.innerHTML += `<li class="card-container" itemscope itemtype="https://schema.org">
<article id="front-card">
<h2>${element.name}</h2>
<div class="top-card">
<img alt="Plant Name" src="${element.imageUrl}">
<dl itemscope itemtype="https://schema.org" class="facts">
<div class="amounts">
<dt itemprop="water-amount" class="amount">Water</dt>
<dd>
<img alt="Gota" src="resources/Icons/agua-activa.png" >
<img alt="Gota" src="resources/Icons/agua-activa.png" >
<img alt="Gota" src="resources/Icons/agua-inactiva.png" class="inactiva">
</dd>
</div>
<div class="amounts">
<dt itemprop="light-amount" class="amount">Light</dt>
<dd>
<img alt="Sol" src="resources/Icons/luz-activa.png" >
<img alt="Sol" src="resources/Icons/luz-inactiva.png" class="inactiva" >
<img alt="Sol" src="resources/Icons/luz-inactiva.png" class="inactiva" >
</dd>
</div>
<div class="amounts">
<dt itemprop="care-amount" class="amount">Care</dt>
<dd>
<img alt="Semaforo" src="resources/Icons/cuidado-activa.png" >
<img alt="Semaforo" src="resources/Icons/cuidado-inactiva.png" class="inactiva" >
<img alt="Semaforo" src="resources/Icons/cuidado-inactiva.png" class="inactiva" >
</dd>
</div>
</dl>
</div>
<p>${element.shortDescription}</p>
<div class="button-container">
<button>Detalles</button>
</div>
</article>
<article id="back-card" class="hide">
<h2>${element.name}</h2>
<div class="top-card">
<img alt="Plant Name" src="${element.imageUrl}">
<dl itemscope itemtype="https://schema.org">
<dt class="scientific">${element.scientificName}</dt>
<dt class="detail">Botanical Family</dt><dd>${element.botanicalFamily}</dd>
<dt class="detail">Usage</dt><dd>${element.applications}</dd>
</dl>
</div>
<div class="bottom-card">
<dl id="description">
<dt>Climate data</dt><dd>${element.climaticData}</dd>
<dt>Description</dt><dd>${element.description}</dd>
<dt>Maintenance</dt><dd>${element.maintenance}</dd>
</dl>
<div id="icons">
<div class="stats">
<img class="stats1" alt="Estadisticas 1" src="resources/Icons/estadisticas-1.png">
<img class="stats2" alt="Estadisticas 1" src="resources/Icons/estadisticas-2.png">
</div>
<div class="back">
<img alt="Regresar" src="resources/Icons/Regresar.png">
</div>
</div>
</div>
</article>
</li>`
cardList.appendChild(cardItem);
});
return cardList;
};
Upvotes: 0
Views: 60
Reputation: 471
First, in your HTML, ids should be unique. so instead of
<article id="front-card">
and
<article id="back-card" class="hide">
Go instead with
<article class="front-card">
and
<article class="back-card hide">
Next, the selectors in these lines are matching multiple elements instead of just the ones you want.
const frontCard=document.querySelector("#front-card");
const backCard=document.querySelector("#back-card");
You've passed in the card element to the function, so you can use it to select just the ones you want like this (note I've switch to class selectors assuming you will make the HTML change above):
const frontCard=card.querySelector(".front-card");
const backCard=card.querySelector(".back-card");
Upvotes: 1