I am new to JavaScript and have almost no idea of how functional programming works. I am running into a problem.
const cards = document.querySelectorAll('.card')
const descriptionCards = document.querySelectorAll('.description-card')
async function displayParagraph(descriptionId) {
function timer(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
await timer(500)
document.querySelector(descriptionId).style.display = 'block'
}
cards.forEach(card => {
const cardIndex = card.id['card-'.length]
card.addEventListener('mouseover', () => {
document.querySelector('#description-card-' + cardIndex).style.height = '302px'
displayParagraph('#description-' + cardIndex)
})
card.addEventListener('mouseout', () => {
document.querySelector('#description-card-' + cardIndex).style.height = '0px'
document.querySelector('#description-' + cardIndex).style.display = 'none'
})
})
descriptionCards.forEach(descriptionCard => {
const cardIndex = descriptionCard.id['description-card-'.length]
descriptionCard.addEventListener('mouseover', () => {
document.querySelector('#description-card-' + cardIndex).style.height = '302px'
document.querySelector('#description-' + cardIndex).style.display = 'block'
})
descriptionCard.addEventListener('mouseout', () => {
document.querySelector('#description-card-' + cardIndex).style.height = '0px'
document.querySelector('#description-' + cardIndex).style.display = 'none'
})
})
.absolute {
position: absolute;
}
.first-row {
left: 100px;
}
.first-column {
top: 407px;
}
.card {
background: #FFFFFF;
width: 320px;
height: 240px;
border: 0;
border-radius: 25px;
box-shadow: 0px 1px 15px 10px #00000040;
z-index: 1;
}
.card img {
margin: auto;
}
/* Descriptions */
.description-card {
position: absolute;
top: 215px;
width: 100%;
height: 0px;
background: #FFFFFF;
border-radius: 0px 0px 25px 25px;
transition: all 500ms;
}
.description {
position: absolute;
top: 45px;
font-size: 16px;
display: none;
}
#description-a {
left: 28px;
width: 263px;
}
<div class="first-row first-column absolute">
<div id="card-a" class="card">
<img src="organizations/panthera.png" alt="Panthera">
</div>
<div id="description-card-a" class="description-card">
<p id="description-a" class="description">Panthera is the only organization in the world that is devoted exclusively to the conservation of the world’s 40 wild cat species and their ecosystems. Utilizing the expertise of the world’s premier cat biologists, Panthera develops and implements global strategies for the most imperiled large cats: tigers, lions, jaguars, snow leopards, cheetahs, pumas, and leopards.</p>
</div>
</div>
This works perfectly. But the problem, as you can see, is that I am repeating the code for what happens when I am hovering over the card or the description-card. Basically, I want the same behaviour when I am hovering over either the card or the description-card. Naturally, this is a good place to use functions to avoid repeating code. So I tried doing this:
const cards = document.querySelectorAll('.card')
const descriptionCards = document.querySelectorAll('.description-card')
async function displayParagraph(descriptionId) {
function timer(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
await timer(500)
document.querySelector(descriptionId).style.display = 'block'
}
function hovering() {
document.querySelector('#description-card-' + cardIndex).style.height = '302px'
displayParagraph('#description-' + cardIndex)
}
function notHovering() {
document.querySelector('#description-card-' + cardIndex).style.height = '0px'
document.querySelector('#description-' + cardIndex).style.display = 'none'
}
cards.forEach(card => {
const cardIndex = card.id['card-'.length]
card.addEventListener('mouseover', hovering)
card.addEventListener('mouseout', notHovering)
})
descriptionCards.forEach(descriptionCard => {
const cardIndex = descriptionCard.id['description-card-'.length]
descriptionCard.addEventListener('mouseover', hovering)
descriptionCard.addEventListener('mouseout', notHovering)
})
.absolute {
position: absolute;
}
.first-row {
left: 100px;
}
.first-column {
top: 407px;
}
.card {
background: #FFFFFF;
width: 320px;
height: 240px;
border: 0;
border-radius: 25px;
box-shadow: 0px 1px 15px 10px #00000040;
z-index: 1;
}
.card img {
margin: auto;
}
/* Descriptions */
.description-card {
position: absolute;
top: 215px;
width: 100%;
height: 0px;
background: #FFFFFF;
border-radius: 0px 0px 25px 25px;
transition: all 500ms;
}
.description {
position: absolute;
top: 45px;
font-size: 16px;
display: none;
}
#description-a {
left: 28px;
width: 263px;
}
<div class="first-row first-column absolute">
<div id="card-a" class="card">
<img src="organizations/panthera.png" alt="Panthera">
</div>
<div id="description-card-a" class="description-card">
<p id="description-a" class="description">Panthera is the only organization in the world that is devoted exclusively to the conservation of the world’s 40 wild cat species and their ecosystems. Utilizing the expertise of the world’s premier cat biologists, Panthera develops and implements global strategies for the most imperiled large cats: tigers, lions, jaguars, snow leopards, cheetahs, pumas, and leopards.</p>
</div>
</div>
But this does not work as cardIndex is not defined in the hovering and notHovering functions. I can't figure out how to pass cardIndex into the hovering and notHovering functions since I am not supposed to call the functions but the pass in the function names as variables into the addEventListener functions.
card.addEventListener('mouseover', ()=>hovering(cardIndex))and make hovering accept cardIndex as parametercardIndexout as aconstinside yourdescriptionCards.forEachcode, pass that as function argument, becauseconstare block scoped: it doesn't exist outside that block, unless you forward it as argument. In the code you show, thehoverfunction is trying to access something calledcardIndex, but nothing with that name exist.