Reputation: 3625
I have a web page that is displaying a set of images using a table for simple layout. What I'd like to do is allow a user to click the image and have that image appear magnified in a modal.
The html row holding a graphic:
<tr>
<td>Graphic One</td>
<td><img class="graph" src="/chart1.jpg">
<div class="modal">
<div class="modal-content">
<span class="close-btn">×</span>
<img src="/chart1.jpg">
</div>
</div>
</td>
</tr>
This is repeated to create more rows with graphics. Here's the script:
<script>
let modalBtn = document.querySelector(".graph")
let modal = document.querySelector(".modal")
let closeBtn = document.querySelector(".close-btn")
modalBtn.onclick = function(){
modal.style.display = "block"
}
closeBtn.onclick = function(){
modal.style.display = "none"
}
window.onclick = function(e){
if(e.target == modal){
modal.style.display = "none"
}
}
</script>
This only seems to activate the first graphic on the page, though, so I'm assuming that the querySelector() stops at the first instance found.
How can I apply this to every row with an image in the table?
Upvotes: 0
Views: 51
Reputation: 66113
If you want to apply it to every table row, all you need is to select all the <td>
and then iteratively apply the same logic as you have above to the elements found inside it.
To access the individual elements, you can simply use Element.querySelector()
instead, assuming Element
refers to the <td>
. It helps to give this <td>
element that contains all these elements a class, so you can narrow down the selection, e.g. <td class="action">
:
<tr>
<td>Graphic One</td>
<td class="action">
<img class="graph" src="/chart1.jpg">
<div class="modal">
<div class="modal-content">
<span class="close-btn">×</span>
<img src="/chart1.jpg">
</div>
</div>
</td>
</tr>
...then you can do this:
document.querySelectorAll('.action').forEach(el => {
let modalBtn = el.querySelector(".graph");
let modal = el.querySelector(".modal");
let closeBtn = el.querySelector(".close-btn");
modalBtn.addEventListener('click', e => {
// Stop click event from bubbling up
e.stopPropagation();
modal.style.display = 'block';
});
closeBtn.addEventListener('click', e => {
// Stop click event from bubbling up
e.stopPropagation();
modal.style.display = 'none';
});
});
// Listen to click event on the window ONCE, outside the forEach loop
window.addEventListener('click', () => {
document.querySelectorAll(".modal").forEach(el => {
el.style.display = 'none';
});
});
You can see that I have left out the window click event listener in the for each loop. The reason is that you can simply rely on event.stopPropagation
to stop the click event from bubbling to the window object. That means, you simply have to bind the click event once on the window.
Also, I would not suggest using Element.onclick = Function
to add event listeners, because that means you can only assign one handler this way. Use Element.addEventListener
instead.
Upvotes: 1