Multiple modal windows on a single page (flexible JS solution) - javascript

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";
}
};

Related

Trigger the same action with two IDs

I have a modal which I would like to call with two buttons with different IDs. The reason is that one button is displayed on desktop and the other on mobile view (responsive). display: none does do the trick of using two times the same ID.
The modal:
<!-- The Modal -->
<div id="myModal" class="modal">
<span class="closecross">×</span>
<!-- Modal content -->
<div class="modal-content">
<p>Content</p>
</div>
</div>
The modal as JS:
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("closecross")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.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";
}
};
My two buttons:
<div class="insertClass" id="myBtnMobile">Modal</div>
And
<div class="insertClass" id="myBtn">Modal</div>
I tried to use getElementsByClassName('.myBtnMobile','.myBtn') but it does not work with my JS.
The code I am using is from https://www.w3schools.com/howto/howto_css_modals.asp just to provide some potential playground.
Thanks in advance!
Working fiddle
You could use queryselectorAll() :
var divs = document.querySelectorAll('#myBtnMobile,#myBtn');
divs.forEach(function(div) {
div.addEventListener("click", clickEvent);
});
function clickEvent() {
console.log('Div ' + this.id + ' Clicked');
}
<div id="myBtnMobile">Modal</div>
<div id="myBtn">Modal</div>
You can just use this:
<div class="insertClass" id="myBtnMobile" onclick="yourfunction()">Modal</div>
<div class="insertClass" id="myBtn" onclick="yourfunction()">Modal</div>
or
document.getElementById("myBtnMobile").addEventListener("click", yourfunction);
document.getElementById("myBtn").addEventListener("click", yourfunction);
Or use
<button class="...">
not
<button id="...">.
One more possible solution:
var buttons = document.getElementsByClassName('insertClass');
for (var i = 0; i < buttons.length; i++)
{
buttons[i].onclick = function() {
document.getElementById('myModal').style.display = 'block';
}
}
https://jsfiddle.net/43gkcm92/24/
you may this way to trigger two ID with same action
$('#myBtnMobile,#myBtn').click(function () {
// your logic
});
You need to access the class and not the ids:
document.getElementsByClassName("insertClass");

Window.onclick not working in modal box

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";
}
}

How do I create a second close button on my modal (in addition to the top left x)

I'd like to add another "Cancel" button on the bottom of the modal in addition to the span option to close the modal. Not sure where to go from here please advise on some options. Thanks
<!-- The Offer Modal-->
<!-- Trigger/Open The Modal -->
<button id="makeOfferBtn">Make an Offer</button>
<!-- The Offer Modal content -->
<div id="myOfferModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
</div>
</div>
<script>
// Get the modal
var modal = document.getElementById('myOfferModal');
// Get the button that opens the modal
var btn = document.getElementById("makeOfferBtn");
// 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";
}
// When the user clicks on <span> (x), close the modal
span.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";
}
}
</script>
This is a quick and dirty example that will work with any number of buttons that has the .close class defined:
// Selecting all nodes that are `.close`
var closeBtns = document.querySelectorAll('.close');
// Iterating over on all of them and
// attaching handlers for the 'click' event.
for (var i = 0, max = closeBtns.length; i < max; i++) {
var close = closeBtns[i];
close.addEventListener('click', function() {
modal.style.display = 'none';
});
}
However, I would recommend to restructure your code a bit in order to not to use so many global variables.

Pop Up modal only works on first item

I am working on a shopify store, there is a 'remove from cart' option on the cart page, when they click on it a popup shows up to confirm if they want to remove it from the cart.
The issue I am having is that the popup will only work on the first item, the others will just take you back to the top of the page.
Here's the code I am using.
The remove text
<td style="text-align: center">
X
</td>
The Popup
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<p class="modal-index-title">Hey!</p>
<p class="modal-title">Are you sure you want to remove this?</p>
<div class="modal-confirm">
<span class="close">No!</span>
<p>Yes</p>
</div>
</div>
</div>
The script
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("cart_popup");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.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";
}
}
IDs are supposed to be unique for a DOM element so your JS code will just grab the first instance of the cart_popup element and apply the onClick there.
If you want to make it apply across all your remove cart buttons, add a CSSclass to it and then apply the btn.onclick function to buttons having that class.
EDIT:
Example:
var classname = document.getElementsByClassName("classname");
var showModal = function() {
modal.style.display = "block";
};
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', showModal, false);
}
You might have several elements with the same id attribute. Only the first triggers your btn.onclick function.

More than one modal box on page?

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/

Categories