How can I use getElementsByClassName
? I have many cards like this:
<div class="user-card Info-btn" id="Info-btn" style="display: flex; width: 400px;">
<div class="left-card">
<img src="" onError="this.onerror=null;this.src='{{ asset('img/not-found.jpg') }}';" style="display: block; margin-left: auto; margin-right: auto;" alt="">
</div>
<div class="right-card">
<div class="right-top">
<div style="padding-top: 15px;">
<h1 class="user-name"></h1>
<h1 style="color: #B4B4B4; font-size: 10px;"></h1>
</div>
</div>
<div class="right-bottom">
<h1>Admin</h1>
</div>
</div>
</div>
What I want is that when you click a card, a modal will display.
My JS looks like this:
var infomodal = document.getElementById("info-modal");
// Get the button that opens the modal
var infobtn = document.getElementsByClassName("Info-btn")[0];
// Get the <span> element that closes the modal
var infospan = document.getElementsByClassName("infoclose")[0];
// When the user clicks the button, open the modal
infobtn.addEventListener("click", function(){
infomodal.style.display = "block";
})
// When the user clicks on <span> (x), close the modal
infospan.addEventListener("click", function(){
infomodal.style.display = "none";
})
// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event){
if (event.target == infomodal) {
infomodal.style.display = "none";
}
})
It works, but only the first card is able to display its modal and not the other cards.
getElementsByClassName
returns a HTMLCollection
(an array-like structure). Since you extract the first element of it (via [0]
) and add an event listener only to the first element, it is obvious that only the first card is able to display it's modal.
What you want instead is to add an event listener to each infospan
element:
var infomodal = document.getElementById("info-modal");
// Get the button that opens the modal
var infobtn = document.getElementsByClassName("Info-btn"); // <-- removed [0]
// Get the <span> element that closes the modal
var infospan = document.getElementsByClassName("infoclose"); // <-- same here
// When the user clicks a button, open the modal
/*infobtn.addEventListener("click", function(){
infomodal.style.display = "block";
})*/
Array.from(infobtn).forEach(btn => {
btn.addEventListener('click', () => {
infomodal.style.display = 'block';
});
});
// When the user clicks on <span> (x), close the modal
/*infospan.addEventListener("click", function(){
infomodal.style.display = "none";
})*/
Array.from(infospan).forEach(span => {
span.addEventListener('click', () => {
infomodal.style.display = 'none';
});
});
// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event){
if (event.target == infomodal) {
infomodal.style.display = "none";
}
})
EDIT
If you know that the number and ordering of the infospan
elements equals the number and ordering of the infobtn
elements, you can remove one of the .forEach
iterations:
var infomodal = document.getElementById("info-modal");
// Get the button that opens the modal
var infobtn = document.getElementsByClassName("Info-btn"); // <-- removed [0]
// Get the <span> element that closes the modal
var infospan = document.getElementsByClassName("infoclose"); // <-- same here
// When the user clicks a button, open the modal
/*infobtn.addEventListener("click", function(){
infomodal.style.display = "block";
})*/
Array.from(infobtn).forEach((btn, index) => {
var span = infospan[index]; // <-- get the corresponding span
btn.addEventListener('click', () => {
infomodal.style.display = 'block';
});
span.addEventListener('click', () => {
infomodal.style.display = 'none';
});
});
// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event){
if (event.target == infomodal) {
infomodal.style.display = "none";
}
})