Close 2-Div Modal With Pure JS - javascript

I have a simple modal which has two divs. I want to have it "close" when either a) hitting esc e.g. keypress key code 27, or b) clicking outside.
I've searched so many posts but so many are js framework specific and/or don't work in the specific situation.
I want to be able to close it on esc or any click outside of the #emod div.
Here is what I have:
<div id="emod-bg"></div><div id="emod"></div>
CSS
#emod-bg
{
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #d0d0d0;
opacity: .50;
-webkit-opacity: .5;
-moz-opacity: .5;
filter: alpha(opacity=50);
z-index: 1000;
}
#emod
{
background-color: white;
display: none;
height: 480px;
left: 50%;
margin: -250px 0 0 -160px;
padding: 10px;
position: absolute;
top: 50%;
width: 320px;
z-index: 1000;
}
...and it is activated as follows:
document.getElementById('emod').style.display = "block";
document.getElementById('emod-bg').style.display = "block";

To close the modal when hitting the escape key, just add a keyup event to the document, and then check the keyCode property of the event object.
If you want to close the modal when clicking on the backdrop, just attach a click event and compare event.target to #emod-bg:
Example Here
var modal = document.getElementById('emod-bg');
modal.style.display = "block";
document.addEventListener('keyup', function (e) {
if (e.keyCode === 27) {
modal.style.display = 'none';
}
});
modal.addEventListener('click', function (e) {
if (e.target === e.currentTarget) {
modal.style.display = 'none';
}
});

Related

HTML - Close pop up when clicking outside the div?

Got this script, but wondering what kind of function I need to add to make it close when clicking outside the box? Do I need to add another div and try to trigger that to make it close or?
Sorry I'm clueless considering writing javascript, I just understand how the events are created by the .onclick events but that's about it.
var closePopup = document.getElementById("popupclose");
var overlay = document.getElementById("overlay");
var popup = document.getElementById("popup");
var button = document.getElementById("button");
// Close Popup Event
closePopup.onclick = function () {
overlay.style.display = 'none';
popup.style.display = 'none';
};
// Show Overlay and Popup
button.onclick = function () {
overlay.style.display = 'block';
popup.style.display = 'block';
}
#overlay {
display: none;
position: absolute;
top: 0;
bottom: 0;
background: #99999945;
width: 100%;
height: 100%;
opacity: 0.8;
z-index: 100;
}
#popup {
display: none;
position: absolute;
top: 25%;
background: #fff;
width: 80%;
margin-left: 10%;
z-index: 200;
border-radius: 4px;
}
#popupclose {
float: right;
padding: 2px;
cursor: pointer;
}
.popupcontent {
padding: 10px;
}
#button {
cursor: pointer;
}
<button id="button" class="button btn--primary">Open div</button>
<div id="overlay"></div>
<div id="popup">
<div class="popupcontrols">
<span id="popupclose">Close X</span>
</div>
<div class="popupcontent">
Content inside popup
</div>
</div>
You could add a click-handler for the overlay element since that should cover all of the "outside" areas.
overlay.onclick = function () {
overlay.style.display = 'none';
popup.style.display = 'none';
};

Something wrong when using addEventListener to add a callback with arguments

I use addEventListener to add a callback with arguments, but something is wrong
I implement a modal dialog component with overlay:
When click on button, the modal will display.
When click on overlay, the modal will disappear.
html:
<button class="common-btn">Click me to show a common modal</button>
<div class="modal common">
<div class="modal-overlay"></div>
<div class="modal-content">
<div>This is a common modal</div>
</div>
</div>
css:
.modal {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 900;
}
.modal .modal-overlay {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #fff;
z-index: 910;
}
.modal .modal-content {
padding: 20px;
border: 1px solid #000;
border-radius: 5px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
z-index: 920;
}
js:
const commonBtn = document.querySelector('.common-btn');
const commonModal = document.querySelector('.modal.common');
function toggleModal(modalEle) {
console.log('func is called');
const preModalDisplay = modalEle.style.display;
if (preModalDisplay === 'block') {
modalEle.style.display = 'none';
modalEle
.querySelector('.modal-overlay')
.removeEventListener('click', () => {
toggleModal(modalEle);
});
} else {
modalEle.style.display = 'block';
modalEle.querySelector('.modal-overlay').addEventListener('click', () => {
toggleModal(modalEle);
});
}
}
commonBtn.addEventListener('click', () => {
toggleModal(commonModal);
});
The expected results should be:
click on btn: display
click on overlay: disappear
click on btn: display
click on overlay: disappear
click on btn: display
click on overlay: disappear
...
But the actual results is:
click on btn: display
click on overlay: disappear
click on btn: display
click on overlay: still display, and the callback func is called twice
There is something wrong with callback, could anybody tell me what is the problem? Thanks.

JavaScript hide on click outside triggers twice from the same click

I have this code:
Full Code:
https://codepen.io/anon/pen/wmLBxW
JavaScript code:
function HideOnClickOutside(aContentElement, aFullScreenElement) {
const outsideClickListener = event => {
event.preventDefault();
let isClickInside = aContentElement.contains(event.target);
if (!isClickInside) {
aFullScreenElement.classList.toggle("hidden", true);
removeClickListener();
}
};
const removeClickListener = () => {
document.removeEventListener("click", outsideClickListener);
};
document.addEventListener("click", outsideClickListener);
}
CSS
#fullscreen {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow: auto;
background: black;
opacity: 0.5;
}
.hidden {
display: none;
}
#journal-show-entry {
display: flex;
justify-content: center;
width: 40%;
height: 60%;
border: 1px solid #9b6400;
background-color: #ffffff;
}
HTML
Link
<div id="fullscreen" class="hidden">
<div id="journal-show-entry">
</div>
</div>
Which I found in this thread:
How do I detect a click outside an element?
However just like in my CodePen, it triggers the outsideClickListener on the same click that adds the EventListener making the div hide itself again on the same click and therefore never shows.
Why is this happening?
What is happening is that the event is propagating onto the next layer (the hidden div)
Adding this will fix your problem:
function ShowFullScreenDiv(event) {
event.stopPropagation(); // <-- add this
divFullScreen.classList.toggle("hidden", false);
HideOnClickOutside(divEntry, divFullScreen);
}
And ofcourse add the event to the html:
Link

JQuery busy indicator doesn't disable keyboard events

I have integrated a Jquery busy indicator in my app from this link: http://www.aspsnippets.com/demos/1331/
It doesn't let the user click on input elements while loading. But if I press tab I can easily navigate to those input elements and enter whatever I want and press enter on button to send a service call. This defeats the whole purpose of busy indicator. Any idea how I can fix it?
This is the css:
.busy-modal
{
position: fixed;
z-index: 999;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-color: Black;
filter: alpha(opacity=60);
opacity: 0.6;
-moz-opacity: 0.8;
}
.busy-center
{
z-index: 1000;
margin: 300px auto;
padding: 10px;
width: 130px;
background-color: White;
border-radius: 10px;
filter: alpha(opacity=100);
opacity: 1;
-moz-opacity: 1;
}
.busy-center img
{
height: 128px;
width: 106px;
}
I fixed it by manually disabling keyboard input on busy indicator. Here's how I did it:
In my angularJS controller I declared a variable that will decide whether to disable keyboard input or not
$scope.disableKeys = false;
then I added following code that disables keyboard input
window.addEventListener('keydown', function (event) {
if ($scope.disableKeys == true) {
event.preventDefault();
return false;
}
});
this is my busyIndicator function:
function busyIndicator(type)
{
if(type == 1)
{
$scope.disableKeys = true;
$(".busy-modal").show();
}
else if (type == 0)
{
$scope.disableKeys = false;
$(".busy-modal").hide();
}
}
Finally, calling this function:
//to show busy indicator
busyIndicator(1);
//to hide busy indicator
busyIndicator(0);
and that's it.

multiple pop up div's in the same page

In one of my projects, I have requirement of multiple pop up div's on the same page. That means when user clicks on a link, some content should open in a pop up. There will be many such links with their own pop ups. With little knowledge of javascript, I have tried to write a javascript for it but it works only for one pop up. When I click on second, third... links, only first pop up opens rather than opening second, third... pop ups. Here is my code. Please tell the modifications to it.
<!DOCTYPE html>
<html >
<head>
<script>
window.document.onkeydown = function (e)
{
if (!e)
{
e = event;
}
if (e.keyCode == 27)
{
lightbox_close();
}
}
function lightbox_open()
{
window.scrollTo(0,0);
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
function lightbox_close()
{
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none';
}
</script>
<style>
#fade
{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: #000;
z-index:1001;
-moz-opacity: 0.7;
opacity:.70;
filter: alpha(opacity=70);
}
#light
{
display: none;
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
padding: 10px;
border: 2px solid #FFF;
background: #CCC;
z-index:1002;
overflow:visible;
}
</style>
</head>
<body>
Open 1
<div id="light">div 1</div>
<div id="fade" onClick="lightbox_close();"></div>
Open 2
<div id="light">div 2</div>
<div id="fade" onClick="lightbox_close();"></div>
Open 3
<div id="light">div 3</div>
<div id="fade" onClick="lightbox_close();"></div>
</body>
</html>
Here's a way to achieve what you want. I'm sure it can be improved, but it's up to you then.
First, IDs should be unique across the page. If you want to group elements, give them a shared class instead.
With the changes, your HTML would look like this:
Open 1
<div class="light">div 1</div>
<div class="fade" onClick="lightbox_close()"></div>
Open 2
<div class="light">div 2</div>
<div class="fade" onClick="lightbox_close()"></div>
Open 3
<div class="light">div 3</div>
<div class="fade" onClick="lightbox_close()"></div>
Your CSS:
html, body {
width: 100%;
height: 100%;
}
.fade {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index:1001;
-moz-opacity: 0.7;
opacity:.70;
filter: alpha(opacity=70);
}
.light {
display: none;
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
padding: 10px;
border: 2px solid #FFF;
background: #CCC;
z-index:1002;
overflow:visible;
}
And your Javascript:
window.document.onkeydown = function (e) {
if (!e) {
e = event;
}
if (e.keyCode == 27) {
lightbox_close();
}
}
// Note that the function is receiving the clicked element reference.
function lightbox_open(el) {
window.scrollTo(0,0);
// All the anchors that have a class lightbox.
var anchors = document.querySelectorAll('a.lightbox');
// All the elements with class light.
var light = document.querySelectorAll('.light');
// All the elements with class fade.
var fade = document.querySelectorAll('.fade');
// Iterate over the anchors elements.
for (var i = 0; i < anchors.length; i++) {
// If the anchor matches the clicked one.
if (anchors[i] == el) {
// Look for the light and fade with the same index
// and display them.
light[i].style.display = 'block';
fade[i].style.display = 'block';
}
}
}
function lightbox_close() {
// All the elements with class light or fade.
var els = document.querySelectorAll('.light, .fade');
// Loop through the list.
for (var i = 0; i < els.length; i++) {
// Hide them.
els[i].style.display = 'none';
}
}
Demo

Categories