Make modal gallery and change the image when .onclick - javascript

I've been trying to make a img gallery where you can click any img and a popup appears with a different img. I have found how to do a modal gallery but I have been having trouble to show a different image when it opens.
Here is my code:
<div class="trabajos">
<!-- Trigger the Modal -->
<ul id="gallery">
<li class="gallery"><img id="myImg" src="./public/design/Who1.jpg" alt="Grand Hotel Budapest poster & postcards" style="width:250px"></li>
<li class="gallery"><img id="myImg" src="./public/design/Legibilidad.jpg" alt="Legibilidad, Typography work" style="width:250px"></li>
<li class="gallery"><img id="myImg" src="./public/design/puraLuz1.jpg" alt="Pura Luz poster at Microteatro" style="width:250px"></li>
<li class="gallery"><img id="myImg" src="./public/design/nightflyers1.jpg" alt="Graphics for the Netflix series Nightflyers" style="width:250px"></li>
<li class="gallery"><img id="myImg" src="./public/design/photography.jpg" alt="Photography" style="width:250px"></li>
</ul>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- The Close Button -->
<span class="close">×</span>
<!-- Modal Content (The Image) -->
<img class="modal-content" id="img01">
<!-- Modal Caption (Image Text) -->
<div id="caption"></div>
</div>
</div>
<script>
// Get the modal
var modal = document.getElementById("myModal");
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("myImg");
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
var urls=["./public/design/Who2.png", "./public/design/legibilidad2.png", "./public/design/puraLuz2.png", "./public/design/nightflyers2.png", "./public/design/fotografia2.png"];
for(j=0; j<urls.length; j++){
function changeImage() {
img.src = urls[j];
}
}
for(i=0; i<img.length; i++){
img[i].onclick = function(){
changeImage();
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
</script>
Thank you for your time! I really appreciate it

Below is a code snippet that maybe does what you're looking for, albeit in an opinionated way.
The idea here is that we can store the alternate image that you'd like to use within the modal in the HTML directly, instead of in JavaScript. The reason I did this instead is because I believe it might a bit easier to read the code and if you'd like to change things, it's a bit easier to do that as well.
If you have any specific questions, I'm happy to add more details as needed.
var gallery = document.querySelector("ul")
var modal = document.querySelector(".modal");
var closeButton = document.querySelector("button");
gallery.addEventListener('click', function (event) {
// the event.target could be the `li` or the `img`, but we only want the `img`
var image = event.target.closest('li').querySelector('img')
modal.setAttribute('style', 'display: block;')
modal.querySelector('.modal-content').setAttribute('src', image.getAttribute('data-modal-src'))
})
closeButton.addEventListener('click', function (event) {
modal.removeAttribute('style')
})
body {
margin: 0;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
ul li:hover {
cursor: pointer;
opacity: 0.7;
}
ul li img {
width: 250px;
}
.modal {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 10px;
background-color: rgba(0, 0, 0, 0.6);
}
.modal-content {
max-width: 100%;
max-height: 100%;
}
.close {
position: absolute;
top: 0;
left: 0;
cursor: pointer;
}
<div class="trabajos">
<!-- Trigger the Modal -->
<ul>
<li><img src="https://via.placeholder.com/350x150" data-modal-src="https://via.placeholder.com/350x450" alt="Grand Hotel Budapest poster & postcards"></li>
<li><img src="https://via.placeholder.com/350x150" data-modal-src="https://via.placeholder.com/350x450" alt="Legibilidad, Typography work"></li>
<li><img src="https://via.placeholder.com/350x150" data-modal-src="https://via.placeholder.com/350x450" alt="Pura Luz poster at Microteatro"></li>
<li><img src="https://via.placeholder.com/350x150" data-modal-src="https://via.placeholder.com/350x450" alt="Graphics for the Netflix series Nightflyers"></li>
<li><img src="https://via.placeholder.com/350x150" data-modal-src="https://via.placeholder.com/350x450" alt="Photography"></li>
</ul>
<!-- The Modal -->
<div class="modal">
<!-- The Close Button -->
<button class="close">×</button>
<!-- Modal Content (The Image) -->
<img class="modal-content">
<!-- Modal Caption (Image Text) -->
<div class="caption"></div>
</div>
</div>

Related

How to open a modal with Javascript when an image box is clicked and it closes when clicked outside the box?

I have created a modals with Javascript. For now when I click the image the modal opens and when I click on cross button it closes. What I want is instead of picture when user clicks on image box not on specifically image, the modal should open and when user clicks outside modal box anywhere it should close not only with cross button.
Html:
<section id="about-intro">
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-sm-12 col-lg-11 about-start">
<div class="about-content">
<div class="about-box">
<div class="upp-title">
<div class="upp-headshot">
<picture> <img src="image"
href="#myModal1" class="rounded-circle" alt="Responsive image"/> </picture>
</div>
<div class="upp-info">
<h3><span class="about-name">abc</span>
</h3>
<p><span class="about-des">xyz</span></p>
</div>
</div>
<!-- The Modal -->
<div id="myModal1" class="modal">
<!-- Modal content -->
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<img src="" class="img-
fluid" alt="Responsive image">
</div>
<div class="col-md-12" style="text-align: center;">
<h1 class="modalh1">abc</h1>
<h3 class="modalh3">xyz</h3>
<p class="modalp">qwertyuicffvgbhnmghj</p>
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
Script:
<script>
// Get the button that opens the modal
var img = document.querySelectorAll("img.rounded-circle");
// All page modals
var modals = document.querySelectorAll('.modal');
// Get the <span> element that closes the modal
var spans = document.getElementsByClassName("close");
// When the user clicks the button, open the modal
for (var i = 0; i < img.length; i++) {
img[i].onclick = function(e) {
e.preventDefault();
modal = document.querySelector(e.target.getAttribute("href"));
modal.style.display = "contents";
}
}
// When the user clicks on <span> (x), close the modal
for (var i = 0; i < spans.length; i++) {
spans[i].onclick = function() {
for (var index in modals) {
if (typeof modals[index].style !== 'undefined') modals[index].style.display = "none";
}
}
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target.classList.contains('modal')) {
for (var index in modals) {
if (typeof modals[index].style !== 'undefined') modals[index].style.display = "none";
}
}
}
</script>
Hope it helps.
I always use flex display so I can click the external content.
I tried to insert it to your code
Change style of .modal
<div
id="myModal1"
class="modal"
style="
display: none;
width: 100vw;
height: 100vh;
justify-content: center;
align-items: center;
position: fixed;
top: 0px;
left: 0px;
">
then in js, instead of window.onclick
for (var i = 0; i < modals.length; i++) {
modals[i].onclick = function (event) {
if (!event.target.closest('.modal-content')) {
for (var index in modals) {
if (typeof modals[index].style !== 'undefined')
modals[index].style.display = 'none';
}
}
};
}
You can change selector to .upp-title or .upp-headshot for a bigger clickable area.
I Hope You Can Use this method to your code! Check this out
document.addEventListener(
"click",
function(event) {
// If user either clicks X button OR clicks outside the modal window, then close modal by calling closeModal()
if (
event.target.matches(".button-close-modal") ||
!event.target.closest(".modal")
) {
closeModal()
}
},
false
)
function closeModal() {
document.querySelector(".modal").style.display = "none"
}
.modal {
padding: 2rem;
border: 1px solid #eee;
width: max-content;
position: fixed;
right: 0;
bottom: 0;
max-width: 100%;
}
.button-close-modal {
display: block;
font-size: 2rem;
font-weight: bold;
margin-left: auto;
}
<main>
<div class="modal">
<button class="button-close-modal">X</button>
<h2>Modal close without Using button(X)</h2>
<p>Sed ut perspiciatis unde voluptatem accusantium doloremque laudantium,</p>
<label for="email">Enter your email:</label>
<input type="email" id="email" name="email">
</div>
</main>

How to show different <div> in one modal?

How can i show (toggle) different divs in one modal? Let me explain:
- when i click on "show me more" i wanna trigger modal (and its working in my case)
- next, i close it (it works)
- i wanna trigger modal again but on different div and offcourse i want this div to be in modal again (now thats where i got stuck at).
Below its snippet of my code...
HTML:
<div id="modal" class="modal">
<div class="modal-content">
<span class="close-button">×</span>
<div id="wrapper" class="modified">
<!-- Main -->
<section>
<div class="inner">
<h1 class="major">DJ ZA POROKE</h1>
<p align="justify">some text</p>
<p align="justify">some text</p>
</div>
</section>
</div>
</div>
</div>
JS:
var modal = document.querySelector(".modal");
var trigger1 = document.querySelector(".trigger1");
var closeButton = document.querySelector(".close-button");
function toggleModal() {
modal.classList.toggle("show-modal");
}
function windowOnClick(event) {
if (event.target === modal) {
toggleModal();
}
}
trigger1.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);
And lets say i trigger it like:
<div class="middle">
<div class="text trigger">Show me more..</div>
Thanks for your help.
Regards.
So to get it right:.
user clicks a button /other element ("show me more") and a
modal is shown with content 1
modal is closed
user clicks again a button /other element ("show me more") and a
modal is shown with content 2.
modal is closed
You have 2 options:
call two different modals identical except for the content -> this can be done with a state var in JS
var stateContent = 0;
and check on the button click event in which state we are
The second more elegant shows/hides the relevant div
HTML addapted
<div id="modal" class="modal">
<div class="modal-content">
<span class="close-button">×</span>
<div id="wrapper" class="modified">
<!-- Main -->
<section>
<div id="content_1" class="inner" style="display: block"> <!-- ID added This part is shown -->
<h1 class="major">DJ ZA POROKE</h1>
<p align="justify">some text</p>
<p align="justify">some text</p>
</div>
<div id="content_2" class="inner" style="display: none"> <!-- ID added This part is hidden -->
<h1 class="major">XY ZZ POROKE</h1>
<p align="justify">some OTHER text</p>
<p align="justify">some OTHER text</p>
</div>
</section>
</div>
</div>
</div>
In javascript you change the display style - for simplification I do it on the close button
closeButton.addEventListener("click", function(e){
switchContent();
toggleModal();
});
New function for doing what we want content switching:
function switchContent(){
var content1 = document.getElementById("content_1");
var content2 = document.getElementById("content_2");
// Check in which state we are
if (content1.style.display === 'none') {
content1.style.display = 'block';
content2.style.display = 'none';
}
else {
content1.style.display = 'none';
content2.style.display = 'block';
}
}
I just opened editor at w3 so i can show directly what i want:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {font-family: Arial, Helvetica, sans-serif;}
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Modal Example</h2>
<!-- Trigger/Open The Modal -->
<button id="myBtn">Open Modal</button>
<button id="myBtn2">Open Modal2</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..1</p>
</div>
</div>
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..2</p>
</div>
</div>
<script>
// Get the modal
var modal = document.getElementById("myModal");
var modal2 = document.getElementById("myModal2");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
var btn2 = document.getElementById("myBtn2");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
btn2.onclick = function() {
modal2.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
span.onclick = function() {
modal2.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
if (event.target == modal2) {
modal.style.display = "none";
}
}
</script>
</body>
</html>
So you see something went wrong, because when i click OPENMODAL2 it freezes. But anyhow, i want 8 different divs to show in 1 modal.

Modal only showing first image (how should i change the codes from id to class?)

I have a journal in which each article shows multiple images. They are self perpetuated and made. I am not sure what are their IDs. I have recently added a code showing modal images, however the code only has one ID and hence only the first image is being shown as a modal image. Rest all do not show.
Please have a look on the JavaScript code and html. Do let me know, how to change it.
Thanks
JS Code
// Get the modal
var modal = document.getElementById('myModal');
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById('myImg');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
img.onclick = function(){
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
HTML Code
<div class="imagewrap">
{** check if link is from galley attachments*}
{if strpos($secCont->getLink(), "/") == false}
{foreach from=$imageUrlArray key=fileName item=urlLink}
{if $fileName == $secCont->getLink()}
<img src="{$urlLink}" id="myImg" alt="{$secCont->getLabel()}" width="300" height="200">
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- The Close Button -->
<span class="close" onclick="document.getElementById('myModal').style.display='none'">×</span>
<!-- Modal Content (The Image) -->
<img class="modal-content" id="img01">
<!-- Modal Caption (Image Text) -->
<div id="caption"></div>
</div>
<a style="font:4;"><a class="imagewrap" href="{$urlLink}"><strong>[Download figure]</strong></a>
{/if}
{/foreach}
{else}
<img src="{$secCont->getLink()}">
<a style="font:4;"><a class="imagewrap" href="{$secCont->getLink()}"><strong>[Download figure]</strong></a>
{/if}
</div>
Well, we don't need ids. We can use document.querySelectorAll to get the different images. Look at the code below.
// Get the modal
// and all the variable we need.
var modal = document.getElementById('myModal');
var modalImg = document.getElementById("img01");
var captionText = document.getElementById("caption");
showImageInModal = function(e) {
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// get all the images using querySelector: we want all the direct descendants of div with class imagewrap.
//Loop them using Array's forEach. Since querySelector returns a nodelist which is array like, we can loop it with forEach. Use call to pass the nodelist as a reference.
var images = document.querySelectorAll("div.imagewrap > img");
Array.prototype.forEach.call(images, function(element){
element.addEventListener("click", showImageInModal, true); //attach the onclick handler to the image using the correct approach with addEventListener.
});
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on <span> (x), close the modal
span.addEventListener("click", function(e) {
modal.style.display = "none";
}, true);
.modal{
position: absolute;
left: 10px;
top: 10px;
border: 1px solid black;
width: 300px;
display: none;
background-color: white;
}
<div class="imagewrap">
<!-- added # to the getLabel so you can see the difference, please remove when copied -->
<img src="{$urlLink}" alt="{$secCont->getLabel(1)}" width="300" height="200">
<img src="{$urlLink}" alt="{$secCont->getLabel(2)}" width="300" height="200">
<img src="{$urlLink}" alt="{$secCont->getLabel(3)}" width="300" height="200">
<img src="{$urlLink}" alt="{$secCont->getLabel(4)}" width="300" height="200">
<img src="{$urlLink}" alt="{$secCont->getLabel(5)}" width="300" height="200">
<img src="{$urlLink}" alt="{$secCont->getLabel(6)}" width="300" height="200">
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- The Close Button -->
<span class="close" >×</span>
<!-- Modal Content (The Image) -->
<img class="modal-content" id="img01">
<!-- Modal Caption (Image Text) -->
<div id="caption"></div>
</div>
</div>

opening multiple modals with one function

I have pictures with "learn more" button underneath. I'm trying to figure out how to write the js with each button showing different modal content.
var modal = document.getElementsByClassName("myModal");
var btn = document.getElementById("myBtn");
var span = document.getElementsByClassName("close")[0];
btn.onclick = function() {
modal.style.display = "block";
}
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
html looks like:
<div class="gallery">
<h3>Bobcats</h3>
<img/>
<button id="myBtn">Learn More</button>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>
</p>
</div></div>
I have 5 sections that need to be shown. Each additional section looks like the one above. I know the buttons need a unique id and I think setting up the class is where I'm running into trouble.
First of all you can't repeat ID's in a page ... they are unique by definition.
Use classes and loop over the class collection to deal with instances, something like:
// collection of galleries
var galleries = document.getElementsByClassName('gallery');
// iterate galleries collection
for (var i = 0; i < galleries.length; i++) {
let gal = galleries[i], // specific gallery instance
modal = gal.querySelector('.modal'), // modal within this gallery instance
learnBtn = gal.querySelector('.learn');//button within this gallery instance
let toggleModal = function(){
modal.classList.toggle('show');
};
learnBtn.onclick = modal.onclick = toggleModal;
}
.modal {
display: none;
}
.modal.show {
display: block;
background: #eaeaea;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0
}
.modal-content {
background: white;
border: 3px solid #ccc;
margin: 20%;
padding:30px;
}
<div class="gallery">
<h3>Gallery 1</h3>
<button class="learn">Learn More</button>
<div class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>Gallery 1 modal
</p>
</div>
</div>
</div>
<div class="gallery">
<h3>Gallery 2</h3>
<button class="learn">Learn More</button>
<div class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>Gallery 2 modal
</p>
</div>
</div>
</div>

same onclick js function for multiple images

I have a gallery of images. I want to show a loading gif when an image is clicked. I am passing the same onclick function to all the images with their id as below:
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
<div id="loading" style="margin-top: -65%; display: none; z-index= 9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
This is my js :
function imageClicked(id) {
// alert(id);
document.getElementById("loading").style.display = ""; // to display
//alert(loading);
return true;
}
var FirstLoading = true;
function Restoresmallimage() {
if (FirstLoading) {
FirstLoading = false;
return;
}
}
// To disable restoring submit button, disable or delete next line.
document.onfocus = Restoresmallimage;
For the first image its working fine.
But issue is when I am clicking on second image, gif is running on first image and not on the second one. How to resolve this issue? I had defined loading id in each div image.
I think the problem is you never move imagepreloader.gif. Here is my solution to have only one imagepreloader.gif for all images:
HTML:
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
CSS:
div {
display: inline-block;
position: relative;
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
JavaScript:
function constructImagePreloader() {
'use strict';
var imagePreloader = document.createElement('img');
imagePreloader.setAttribute('src', 'images/imagepreloader.gif');
imagePreloader.setAttribute('alt', 'loading...');
imagePreloader.setAttribute('id', 'loading');
return imagePreloader;
}
function imageClicked(id) {
document.getElementById(id).appendChild(constructImagePreloader());
return true;
}
Tell me if it suits your needs. We could go further with code optimization but I wanted to stay close from your code for now. For instance: we could remove the image preloader from the clicked image if another image is clicked.
Try this if it will work,
<div id="smallimage1" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image1.jpeg"/>
</div>
<div id="smallimage2" onclick="imageClicked(this.id)">
<img class="model-img" src="img/model/image2.jpeg"/>
</div>
<div id="loading1" style="margin-top: -65%; display: none; z-index:9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
<div id="loading2" style="margin-top: -65%; display: none; z-index: 9999; position: relative;">
<img src="img/imagepreloader.gif" alt="loading...">
</div>
And your script will be like this;
function imageClicked(id) {
// alert(id);
var loadingId = $(id).replace('smallimage','loading');
document.getElementById(loadingId).style.display = "block"; // to display
//alert(loading);
return true;
}

Categories