I'm currently rebuilding my portfolio and have cards for each of the projects that I've worked on, the idea being that when the user clicks on a card it opens a modal box containing more information about the project and a link to it.
Unfortunately, I can't figure out how to have multiple modal boxes on the same page, without writing a new block of code for every single box. I'm guessing I'll need some sort of for loop but I've been experimenting all day and can't find anything that works.
This is the JavaScript I have so far:
var modal = document.getElementsByClassName("modal")[1];
var card = document.getElementsByClassName("card")[1];
// When the user clicks on the card, open the modal box
card.onclick = function() {
modal.style.display = "block";
}
// When the user clicks anywhere outside of the modal box, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
Many thanks!
Add a class in your modal something like .modal;
window.onclick = function(event) {
if (event.target.classList.contains('modal')) {
event.target.style.display = 'none';
}
}
Related
The Issue
I'm looking to implement a flexible javascript solution to opening and closing multiple modal windows on the same page.
I have found way to open multiple modal windows in such a manner, but I can't for the life of me figure out how to close them by the click of a button or by clicking outside of the modal window itself.
Here is my javascript code:
var openModal = document.getElementsByClassName("open-modal");
for (var i = 0; i < openModal.length; i++) {
var thisOpenModal = openModal[i];
thisOpenModal.addEventListener("click", function() {
var modal = document.getElementById(this.dataset.modal);
modal.style.display = "block";
}, false);
}
(I didn't write this code myself, it's an edited copy of "pgk's" answer over on this page: Opening multiple modal boxes on one page)
I trigger the modal windows by adding the 'open-modal' class to my "buttons" and I use 'data-modal' in relation to the id's of the modal windows:
<div class="featurette-wrap featurette--anchor open-modal" data-modal="modal-microsoft-account">
Opprett konto
</div>
The button above triggers the modal window with the id of modal-microsoft-account:
<div class="modal" id="modal-microsoft-account">
Microsoft-konto
</div>
So my question is:How can I implement a way to close a modal window once it's opened?
I've tried doing this, but I can't get it to work (from W3schools):
// When the user clicks on <span> (x), close the modal
closeModal.onclick = function() {
modal.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";
}
}
It's better to use event listeners to track actions on elements as I've done below;
also, making use of the setAttribute function when setting styles with Javascript ensures that every other style assigned to that element is overridden and the style you are setting always applies (except in cases where another style is set to be important)
var openModal = document.getElementsByClassName("open-modal");
for (var i = 0; i < openModal.length; i++) {
var thisOpenModal = openModal[i];
var targetModal = thisOpenModal.getAttribute('data-modal')
//get the id of the modal to open based on thisOpenModal
var thisTargetModal = document.getElementById(targetModal)
//get element
thisOpenModal.addEventListener("click", function(event) {
thisTargetModal.setAttribute('style', "display:block;")
//code to open modal on click of div with id=""
}, false);
// When the user clicks on <span> (x), close the modal
var closeModal = document.querySelector('#' + thisTargetModal.id, "span");
//code to listen to click event and change block style attribute to none on click
closeModal.addEventListener("click", function() {
thisTargetModal.setAttribute('style', "display:none;")
}, false)
// When the user clicks anywhere on the modal div, close it
window.addEventListener("click", function(event) {
//code to listen to click event on window and change block style attribute to none
if (event.target == targetModal) {
thisTargetModal.setAttribute('style', "display:none;")
}
})
}
<div class="featurette-wrap featurette--anchor open-modal" data-modal="modal-microsoft-account">
Opprett konto
</div>
<div class="modal" id="modal-microsoft-account" style="display:none;">
<p>Microsoft-konto </p>
<p>
<span id="close-modal">
x
</span>
</p>
</div>
So I actually ended up finding a solution that did exactly what I was looking for over at W3Schools forum: http://w3schools.invisionzone.com/topic/55976-multiple-modal-boxes-on-webpage/
This did the trick 🙌:
// Get the modal
var modal = document.getElementsByClassName("modal");
// Get the button that opens the modal
var openModal = document.getElementsByClassName("open-modal");
// Get the <span> element that closes the modal
var closeModal = document.getElementsByClassName("modal__close");
// When the user clicks the button, open the modal
function setDataIndex() {
for (i = 0; i < openModal.length; i++) {
openModal[i].setAttribute('data-index', i);
modal[i].setAttribute('data-index', i);
closeModal[i].setAttribute('data-index', i);
}
}
for (i = 0; i < openModal.length; i++) {
openModal[i].onclick = function() {
var ElementIndex = this.getAttribute('data-index');
modal[ElementIndex].style.display = "block";
};
// When the user clicks on <span> (x), close the modal
closeModal[i].onclick = function() {
var ElementIndex = this.getAttribute('data-index');
modal[ElementIndex].style.display = "none";
};
}
window.onload = function() {
setDataIndex();
};
window.onclick = function(event) {
if (event.target === modal[event.target.getAttribute('data-index')]) {
modal[event.target.getAttribute('data-index')].style.display = "none";
}
};
I have a modal box of html inside a php foreach loop. I am using javascript to display and hide the modal box by using onclick event. The Problem is bot my onclick event to display and hide functions are working, but when I click on the window outside the modal box it's not hiding the modal box.
I think It might be because I an printing several modal box in the php loop and the javascript does not know which one to close.
I just want to close all the modal box but don't know how to get it done
Thanks in advance
My javascript:
<script>
// Get the modal
var currentIndex;
var modal = document.getElementsByClassName('myModal');
// Get the button that opens the modal
var btn = document.getElementsByClassName("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close");
// When the user clicks the button, open the modal
function display(index) {
modal[index].style.display = "block";
currentIndex = index;
}
function notdisplay(index){
modal[index].style.display = "none";
}
// When the user clicks on <span> (x), close the modal
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal[currentIndex]) {
modal.style.display = "none";
}
}
</script>
My modal box inside the php loop:
<div class="col-md-7 offset-md-2 myBtn" onclick="display('.$index.')" style="margin-left:20px;">
<span onclick="notdisplay('.$index.')" class="close">×</span>
You can give access to the index by declare a global variable (let's say var currentIndex) of the script. Then inside display(index) method change the global variable to index.
var currentIndex;
function display(index) {
modal[index].style.display = "block";
currentIndex = index;
}
then inside window.onclick function you can access the currentIndex
window.onclick = function(event) {
if (event.target == modal[currentIndex]) {
modal.style.display = "none";
}
}
I'm using JS modal (no jquery), since I have some issues with that approach...
Everything works good except that on mobile user can't close it.
var modal = document.getElementById('myModal');
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
It is probably related to that touch that I'm missing...
I tried with jquery like this:
$(document).ready(function(){
$(modal).on('click touchstart', function() {
modal.style.display = "none";
});
});
The problem here is that if user clicks inside the modal, it will also disappear...
What I need is that when user clicks only outside, modal should disappear...
Any ideas how can I solve this issue?
Thanks.
instead of registering click on the target, register on the document and then check to see that the mouse wasn't inside of the target
$(document).on ('mouseup touchstart', function (e)
{
var container = $("#myModal");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});
You can listen for the 'mousedown' event on the document, then check if the modal is in the event path. If it's not, then hide the modal. If it is, then do nothing.
var myModal = document.getElementById('myModal');
document.addEventListener('mousedown', function(e)
{
if (e.path.indexOf(myModal) == -1)
myModal.hidden = true;
});
Have you tried to use contains ?
I just tested it on iOS safari and chrome, it works correctly
please check out the demo,
when you click the yellow part, it still exists
however, when you click the pink part, the whole modal will hide
JS Bin
code in JS Bin
var pa = document.querySelector('#modal-overlay');
var ch = document.querySelector('#modal-container');
pa.addEventListener('click', function(e) {
if (!ch.contains(e.target)) {
pa.style.display = 'none';
}
});
I'm totally new to Web programming.
I've just learned HTML and CSS, but have no any knowledge about Java Script.
Situation what i have is like this.
There are two buttons and two divs.
If one button is clicked, the div related in that button appears.(visibility:visible)
And click same button one more, div is disappear.
So now when I click buttons at once, two divs are overlapped.
Now I want to build an effect like this.
If one button already clicked(one div is appeared already), and click another
button then first div is disappeared and another div appear at the same time.(replace position)
<script>
function show1() {
document.getElementById("div1").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.button1'))
var dropdowns = document.getElementsByClassName("div1_pop");
}
function show2() {
document.getElementById("div2").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.button2'))
var dropdowns = document.getElementsByClassName("div2_pop");
}
</script>
I'm totally toddler when it comes to Java Script. So I just copy&paste that
script section. Can I get an appear/disappear effect fixing that script?
One possible solution is to show one dive and hide the second div.
function show1() {
document.getElementById("div1").style.display = "block";
document.getElementById("div2").style.display = "none";
}
window.onclick = function(event) {
if (!event.target.matches('.button1'))
var dropdowns = document.getElementsByClassName("div1_pop");
}
function show2() {
document.getElementById("div1").style.display = "none";
document.getElementById("div2").style.display = "block";
}
window.onclick = function(event) {
if (!event.target.matches('.button2'))
var dropdowns = document.getElementsByClassName("div2_pop");
}
</script>
Edit
I have updated all the code in this question.
Question
I have been trying to get more than one modal box to work a single page.
I can get one to work but I can't replicate it so that two will open (I want there to be three modal boxes to in the end?
This is the button that is being called to open the first modal;
<button id="myHistoryBtn" class="myAboutBtn">more</button>
This is the second one;
<button id="myAboutBtn" class="myAboutBtn">more</button>
This is the modal structure that I am using
<div id="myHistoryModal" class="modal">
<!-- Modal content -->
<div class="modal-container">
<div class="modal-content">
<span class="modalclose">×</span>
<h1>sstory</h1>
</div>
</div>
</div>
This is the second one
<div id="myAboutModal" class="modal2">
<!-- Modal content -->
<div class="modal-container">
<div class="modal-content">
<span class="Aboutclose" id="close">×</span>
<h1>AAAAAstory</h1>
</div>
</div>
</div>
Then this is the JavaScript that is making everything work.
// Get the modal
var modal = document.getElementById('myHistoryModal');
// Get the button that opens the modal
var btn = document.getElementById("myHistoryBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("modalclose")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
main.style.display = "none";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
main.style.display = "flex";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
main.style.display = "flex";
}
}
Here is the JavaScript to get the other modal box to work.
// Get the modal
var about = document.getElementById('myAboutModal');
// Get the button that opens the modal
var Abtn = document.getElementById("myAboutBtn");
// Get the <span> element that closes the modal
var Aspan = document.getElementById("close")[0];
// When the user clicks the button, open the modal
Abtn.onclick = function(event) {
about.style.display = "block";
main.style.display = "none";
}
// When the user clicks on <span> (x), close the modal
Aspan.onclick = function() {
about.style.display = "none";
main.style.display = "flex";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function() {
if (event.target == about) {
about.style.display = "none";
main.style.display = "flex";
}
}
I think I am going insane as it all starting to muddle now. Once I try to have more than one modal box it.
I gave it one more go and I sort have got it to work (sort of)
One of the modal box appears when I click the button but won't disappear on close (just stays there)
When I click the other modal box button it hides content but doesn't show the modal box?
Heres a link of what I am working on. I have taken out the code that makes the other modal boxes to work to show you what meant to happen when you click on the more button.
http://www.periodictablesearch.zackreid.com/pages/Carbon.html
This is just confusing me now. I have renamed everything on the second set of JavaScript that makes the second button to work but still nothing.
Edit
So I have now got them to appear and but one is still broken a bit.
http://www.periodictablesearch.zackreid.com/pages/Carbon.html
Then second modal box appears but it won't hide/ close done when using the button our clicking outside the modal box.
Edit
I have now gotten the second modal to close when clicking of the window. Just need to make the button work? Is anyone interested? Should I update my code?
You may need to change the name of second box to
var myAboutModal = document.getElementById('myAboutModal');
var myAboutBtn = document.getElementById("myAboutsBtn");
and register the onclick to myAboutBtn like:
myAboutBtn.onclick = function() {
myAboutModal.style.display = "block";
main.style.display = "none";
}
Otherwise it will end up mess with the first btn and modal variable
And same with the span variable. By the way, the span may need to use the id instead of the classname, because getElementsByClassName("close")[0]; is always the first span in the document, may never give you the second span you want for the second modal
For the close btn, you can add event listener to all close button without the need to add them one by one
var closeBtns = document.getElementsByClassName("modalclose");
for(var i=0; i< closeBtns.length; i++) {
closeBtns[i].onclick = function() {
modal.style.display = "none";
about.style.display = "none";
}
}
To close modal when click outside of it, you need to check if the target is not any of the modal, not the trigger modal buttons, not the modal-container, not the modal-content and not any content inside of modal-content
window.onclick = function(event) {
if (event.target != modal && event.target != about && event.target != btn && event.target != Abtn && event.target.className != "modal-container" && event.target.className != "modal-content" && event.target.parentNode.className != "modal-content") {
modal.style.display = "none";
about.style.display = "none";
}
}
I am not sure what you want to do with the main.style.display = "flex". In most cases, there is no need to set any style regarding the main, assuming the main is the html <body>
A working jsfiddle is here https://jsfiddle.net/yg88rvgq/1/