Sorry for the late reply. I did this a couple months back so my memory about it is a little bit fuzzy. I knew from past experiences that it might be difficult for you if I just gave you a sample solution so I’ve tried to explain what I did as best as I could. If you have any questions, I’ll be happy to try my best to help.
So I had some project objects that I was displaying and I wanted each of them to have a “more info” button which users can click on to get more information about the respective project.
This is a summary of what the solution does:
- A hidden div is placed below each project card code and inside the
for loop
looping through the project objects. This div will contain all the project info that will be displayed on the popup.
- Another div that will be hidden by default is placed somewhere below the code dealing with loading the project cards onto the template. This div will contain the design of the popup and includes all the elements you’ll need for displaying the project information.
- Then, using javascript, we’ll continuously check if any of the “more info” button is clicked. If one of them is, get all the elements in the hidden div for that specific project. Then set the content of each - initially blank - popup elements to the element in the hidden div containing the info we need.Then, display the popup by displaying the popup div.
- Finally, using javascript again, check continuously if the user clicks on the popup close button. If they do, close the popup.
Okay, First off, below is the html code. some will have comments that explain the code.
Html Template (take note of the .popup-info
class):
<div class="project-box">
{% for project in projects %}
<div class="project-item"> <! -- this just displays each project as a card -->
<img src="{{ project.image.url }}" alt="project images">
<h1>{{ project.title}}</h1>
<p>
{{project.description}}
</p>
<a href="{{project.url}}" target="_blank" class="card-link"> <h2>{{ project.linktext }}</h2></a>
<a href="#" class="card-link popupbtn"> <h2> More Info </h2></a>
<div class="popup-info"> <!-- this div will be hidden by default and I use it to store all the info I'll need to display on the popup for each project -->
<p>{{project.image.url}}</p>
<h1>{{project.title}}</h1>
<p>{{project.description}}</p>
<p>{{project.linktext}}</p>
<p>{{project.url}}</p>
</div>
</div>
{% endfor %}
</div>
<div class="popup-wrapper"> <!-- holds the design of the popup. will be hidden initially -->
<div class="popup">
<header>
<span class="popup-title"></span> <!-- title of the project -->
<div class="popup-close">x</div>
</header>
<div class="popup-content">
<div class="popup-imgbox">
<img src="" alt="" class="popup-image"> <!-- an image of the project-->
</div>
<p class="popup-descrip"></p> <!-- project description-->
<a href="#" target="__blank__" class="popup-link"></a> <!-- an external link unique to the project -->
</div>
</div>
</div>
Now this is the javascript code. First is the just the whole code. Then I break down each section and explain it.
Javascript:
// get elements for popup
const wrapper = document.querySelector(".popup-wrapper");
const popupbtns = document.querySelectorAll('.popupbtn');
const popup = document.querySelector('.popup');
const popupclose = document.querySelector('.popup-close');
const popupContent = document.querySelector(".popup-content");
// popup
// get project item popup info
popupbtns.forEach(btn => btn.addEventListener('click', () => {
const popupinfo = btn.parentNode.childNodes[11];
popupContent.querySelector(".popup-image").src = popupinfo.children[0].textContent //project image
popup.querySelector(".popup-title").textContent = popupinfo.children[1].textContent; // project title
popupContent.querySelector(".popup-descrip").textContent = popupinfo.children[2].textContent; // project description
popupContent.querySelector(".popup-link").textContent = popupinfo.children[3].textContent; //project link text
popupContent.querySelector(".popup-link").href = popupinfo.children[4].textContent;
wrapper.style.display = "block";
popup.style.display = "block";
}));
//this block of code will continuously check if the user clicks the "X" button
on the popup which will mean they want to close the popup and so it will close it if they do.
popupclose.addEventListener('click', () => {
popup.style.display = 'none';
wrapper.style.display = "none";
});
// this block of code continuously checks if the user clicks anywhere outside the popup box.
If they do, it will close the popup. This is optional. You don't have to include this feature.
popup.addEventListener('click', (e) => {
if(e.target.className === 'popup-wrapper'){
popup.style.display = 'none';
wrapper.style.display = "none";
}
});
So as I alluded to earlier, the JavaScript is what will allow us to dynamically change the content shown on the popup depending on which project object I click "more info " on as well as make the popup open and close.
Basically, what I did was that I first got all the elements that I’ll need to make the popup work.
// get elements for popup
const wrapper = document.querySelector(".popup-wrapper"); // this gets the div representing the screen when the popup is showing
const popupbtns = document.querySelectorAll('.popupbtn'); // this gets the "more info" button on each of my project card
const popup = document.querySelector('.popup'); // this gets the popup containing the info itself (the box)
const popupclose = document.querySelector('.popup-close'); // this gets the "X" button that will allow the user to close the popup
const popupContent = document.querySelector(".popup-content"); // this gets the div holding all the popup content
// get project item popup info
popupbtns.forEach(btn => btn.addEventListener('click', () => {
const popupinfo = btn.parentNode.childNodes[11];
popupContent.querySelector(".popup-image").src = popupinfo.children[0].textContent //project image
popup.querySelector(".popup-title").textContent = popupinfo.children[1].textContent; // project title
popupContent.querySelector(".popup-descrip").textContent = popupinfo.children[2].textContent; // project description
popupContent.querySelector(".popup-link").textContent = popupinfo.children[3].textContent; //project link text
popupContent.querySelector(".popup-link").href = popupinfo.children[4].textContent;
wrapper.style.display = "block";
popup.style.display = "block";
}));
Then what I did with this part of the code (the one above ) is :
- I used
forEach
to add an eventlistener
to each of the “more info” buttons stored in the popupbtns
variable
- This means that now there is an infinite loop continuously checking whether any of the “more info” buttons is clicked. If a user clicks on of them, this line of code
const popupinfo = btn.parentNode.childNodes[11];
will then get the popupinfo
for the project that the user clicked “more info” on
- Then I matched the elements in the
popupinfo
class with the elements in the popup. For example:
popup.querySelector(".popup-title").textContent = popupinfo.children[1].textContent; // project title
This line of code sets the content of this <span class="popup-title"></span>
to whatever is inside <h1>{{project.title}}</h1>
.
3. After I set the content of the popup,
wrapper.style.display = "block";
popup.style.display = "block";
These two lines of code display the popup.
So that was the solution. I hope it helps.