How to close a modal by clicking outside the modal window? - javascript

In a very simple jQuery modal, I close the modal by clicking on CLOSE as
$('#close').click(function(e) {
e.preventDefault();
$('#overlay, #alertModalOuter').fadeOut(400, function() {
$(this).remove();
});
});
How can I close the modal by clicking whether on CLOSE button (which is inside the modal windows) OR clicking anywhere outside the modal window.

Changing your function like so should work:
$('#close, #overlay').click(function(e) {
e.preventDefault();
$('#overlay, #alertModalOuter').fadeOut(400, function() {
$('#close').remove();
});
});

I found it helpful to include:
$('.item-modal').click(function(e) {
e.stopPropagation();
});

Add the same click listener to your overlay.

I know this question pertains to jQuery, but here's how I did this in Vue on my modal component in case anyone finds it helpful. My modal HTML is basically lifted directly from this: https://v2.vuejs.org/v2/examples/modal.html
I set two #click attributes, one on the outermost modal element (modal-mask) that calls my close() method (which emits the close event to the parent component) and one on the actual modal window element (modal-container) that with the .stop event modifier (#click.stop) to stop the click from bubbling up to the parent element (modal-mask). Works like a charm.

Related

Can't close modals after switching if it was already open

I have two modals, one for registration, one for login. Within each modal I have a link to the other modal like this:
Modal Register
<span id="btn-open-login"><a id="btn-open-login-link">Back to Login</a></span>
Modal Login
<span id="btn-open-register"><a id="btn-open-register-link">Register here!</a></span>
To close and open the modal without body scroll I use this peace of js:
js
$('#btn-open-register').on( 'click', '#btn-open-register-link', function () {
$("#modalLogin").modal("hide");
$("#modalLogin").on("hidden.bs.modal",function(){
$("#modalRegister").modal("show");
});
});
$('#btn-open-login').on( 'click', '#btn-open-login-link', function () {
$("#modalRegister").modal("hide");
$("#modalRegister").on("hidden.bs.modal",function(){
$("#modalLogin").modal("show");
});
});
The modal Login opens first as default.
It works fine for the first round. But when the Login modal is opened for a second time, I can't close the modal anymore. It just keeps switching.
What am I missing?
Here a fiddle: https://jsfiddle.net/tk1rbys0/
You can use modal('toggle') instead of "show" and "hide".
Also, you don't need to listen to the hidden.bs.modal. The way you've structured your code, it simply means when you press a modal button, it closes the current modal, when its 'close' event fires, the other modal is shown. You get stuck in a loop, which is your current situation.
Try replacing your code with this:
let modalLogin = $('#modalLogin'),
modalRegister = $('#modalRegister');
$('#btn-open-register').on('click', '#btn-open-register-link', function () {
modalLogin.modal('toggle');
modalRegister.modal('toggle');
});
$('#btn-open-login').on('click', '#btn-open-login-link', function () {
modalRegister.modal('toggle');
modalLogin.modal('toggle');
});
Hope this helps.
Update:
Switch the modals in reversed order, that way you will always have one visible, which will prevent the scrollbar from showing:
$('#btn-open-register').on('click', '#btn-open-register-link', function () {
modalRegister.modal('toggle');
modalLogin.modal('toggle');
});
$('#btn-open-login').on('click', '#btn-open-login-link', function () {
modalLogin.modal('toggle');
modalRegister.modal('toggle');
});
Update 2:
Taking the scrollbar into account, you can update your code to remove the event listener, once the other modal has been shown.
$('#btn-open-register').on( 'click', '#btn-open-register-link', function () {
$("#modalLogin").modal("hide");
$("#modalLogin").on("hidden.bs.modal",function(){
$("#modalRegister").modal("show");
$("#modalLogin").off("hidden.bs.modal"); // allow closing
});
});
$('#btn-open-login').on( 'click', '#btn-open-login-link', function () {
$("#modalRegister").modal("hide");
$("#modalRegister").on("hidden.bs.modal",function(){
$("#modalLogin").modal("show");
$("#modalRegister").off("hidden.bs.modal"); // allow closing
});
});
This should allow you to close an opened modal without showing the other one.

jQuery function prevents add / remove class on click

I'm trying to have a div get a new class (which makes it expand) when being clicked, and get it back to the old class (which makes it close) when clicking on a cancel link inside that div.
<div class="new-discussion small">
<a class="cancel">Cancel</a>
</div>
<script>
$('.new-discussion.small').click(function() {
$(this).addClass("expand").removeClass("small");
});
$('a.cancel').click(function() {
$('.new-discussion.expand').addClass("small").removeClass("expand");
});
</script>
Now, adding the expand class works flawlessly, but closing the panel after clicking on the cancel link only works when I remove this code:
$('.new-discussion.small').click(function() {
$(this).addClass("expand").removeClass("small");
});
So I guess this must be preventing the second function to work, but I really can't figure out why.
Any ideas?
Thanks!
Try this
$('a.cancel').click(function() {
$('.new-discussion.expand').addClass("small").removeClass("expand");
return false;
});
Reason may be your click event is getting propagated to parent which is also listening to click event.
Since your a element is inside the .new-discussion element, when you click on the a, it also fires the click event on the parent element because the event is bubbling up.
To fix it, you can stop the propagation of the event by calling e.stopPropagation();. That will prevent any parent handlers to be executed.
$('a.cancel').click(function(e) {
e.stopPropagation();
$('.new-discussion.expand').addClass("small").removeClass("expand");
});
Since the link is inside the <div>, it's using both click methods at once. It might help to do a check to see if the container is already open before proceeding:
<script>
$('.new-discussion.small').click(function() {
if ($(this).hasClass("small")) {
$(this).addClass("expand").removeClass("small");
}
});
$('a.cancel').click(function() {
$(this).parent('.expand').addClass("small").removeClass("expand");
});
</script>

Closing jQuery Modal box

I'm trying to create a basic modal myself and I'm having a little bit trouble here (maybe it's because I'm an expert working with jQuery - don't take it seriously).
I have this HMTL markup:
<div id="modal-boxes">
<div id="modal-updates" class="modal-content">
Content for modal box here.
Close
</div>
</div>
<div id="modal-mask"></div>
So, I made a function that tells the modal box to close and to make disappear the #mask div. And another one to when I click outside of it, it closes anyway. In other words, clicking outside the #modal-updates div is the same that clicking on close button. But the problem is that when I want to click inside the #modal-updates div (should not disappear) it closes anyway. Here is my javascript code:
$(".modal").click(function(e){
e.preventDefault(); // Cancel the default link behavior
$("#modal-mask").fadeTo(400, 0.4);
$("#modal-boxes").fadeIn();
var getName = "#" + $(this).attr("name");
$(getName).fadeTo(400, 1);
});
function closeModal() {
$("#modal-mask, #modal-boxes").fadeOut();
}
$(".close-modal").click(function(e){
e.preventDefault();
closeModal();
});
$(".modal-content").click(function(){
closeModal();
});
Any help?
Regards, Tiago Castro
Try:
$('#modal-updates').click(function(e) {
e.stopPropagation();
});
If done right, this will stop $("#modal-boxes").click() from triggering.
[edit] fixed a typo and added link to jsFiddle with it working
Why not using the modal dialog of jQuery?
About your example :
1) for the link I prefer to do something like:
Close
That way no need to deal with things like preventDefault or click event
2)I guess that instead of binding your click event to ".modal-content" you wanted to bind it to "#modal-mask" ;)

How to prevent the parent div from registering the click when a child class is clicked; event.stopPropagation(); doing funny things

We've got the classic problem with a div's child getting clicked and the parent's click event gets triggered as well. I've got a button set within a container that expands and unexpands upon clicking.
The button, when clicked, should:
Unexpand the container
Hide the container's description
The two click functions are given below:
var $NotificationContainer = $("#NotificationContainer");
$NotificationContainer.append('<div class="Notification" title="'+title+'"></div>');
var $thisNotification = $NotificationContainer.children('.Notification[title='+uniqueTitle+']');
$thisNotification.append('<div class="NotificationDescription">'+uniqueDescription+'</div>');
$(".NotificationDescription").hide();
// Button used to close an expanded notification
$thisNotification.append("<div class='NotificationCloseButton'></div>");
$('.NotificationCloseButton').hide();
$thisNotification.click(function()
{
$(this).animate({height:250}, 1000);
$(this).find('.NotificationDescription').slideToggle('fast');
$(this).find('.NotificationCloseButton').slideToggle('fast');
});
$(".NotificationCloseButton").click(function()
{
$thisNotification.animate({height:50}, 1000);
$(this).find('.NotificationDescription').slideToggle('fast');
$(this).find('.NotificationCloseButton').slideToggle('fast');
});
What I find with this code is that when clicking the close button:
SlideToggles the description to be hidden
SlideToggles the close button to be hidden
The container unexpands, but then re-expands (contents still hidden)
The $thisNotification click is being called (I think).
Now, when I try to use event.stopPropagation(); or a simple return false; in the closeButton's click, I get very interesting results.
Clicking the close button with either of the above additions now:
Unexpands the container
The description and button remain present, and do not slideToggle at all.
Code snippets of the exact way I implemented stopPropogation and return false:
$(".NotificationCloseButton").click(function(event)
{
event.stopPropagation();
$thisNotification.animate({height:50}, 1000);
$(this).find('.NotificationDescription').slideToggle('fast');
$(this).find('.NotificationCloseButton').slideToggle('fast');
});
and
$(".NotificationCloseButton").click(function()
{
$thisNotification.animate({height:50}, 1000);
$(this).find('.NotificationDescription').slideToggle('fast');
$(this).find('.NotificationCloseButton').slideToggle('fast');
return false;
});
You have click bindings for a the parent object:
$thisNotification
and for a child object:
$(".NotificationCloseButton")
When you click the close button, the 'click' event is being fired for both handlers, all animations are queued, and you get the undesirable closes-then-opens action.
You have a few options to resolve this. #1 is to unbind the parent click handler and rebind it after the close button is clicked.
$thisNotification.click(function()
{
notificationClickHandler(); //animations are separated from bindings
$thisNotification.unbind('click');
});
Alternately, jQuery has a .clearQueue() method that removes all queued animations. This might have side-effects when users are quick with the mouse, or if your page is heavy on jQuery animations, so you'll have to experiment with the appropriate level of scope for your application.
$(".NotificationCloseButton").click(function()
{
$thisNotification.animate({height:50}, 1000);
$(this).find('.NotificationDescription').slideToggle('fast');
$(this).find('.NotificationCloseButton').slideToggle('fast');
$.clearQueue();
});

jQuery - Toggle a panel closed on click of outside element, only if panel is visible

I'm working on this site: http://dev.rjlacount.com/treinaAronson/index.php
My final to-do is to set the contact panel (which you can see if you click the top left "contact" button) to close if it's currently open and the user either clicks outside of the panel (in the "#content" area) or hits the esc key.
I figured the clicking in the #content area trigger would be the easier of the two, so I started with that. I've read a couple threads on triggering functions only if elements are visible, but what I've come up with so far isn't working at all:
$("#panel").is(":visible") {
$("#content").click(function(){
$("#panel").slideToggle("3000");
});
};
This breaks the functionality of the contact button, and I've tried several variations of this to no avail. Am I making any glaring errors here? Any advice would be greatly appreciated.
Thanks!
Bind Click and Keydown functions to the document and make sure the click function doesn't bubble up to the document when your panel or flip buttons are clicked. Like so:
$(document).bind({
keydown:function(e) {
if (e.keyCode == 27 ) {
$("#panel").slideUp("3000");
}
}, click: function(e) {
$("#panel").slideUp("3000");
}
});
$('#flip, #panel').bind('click', function(e){return false});
Why don't you add a class to the body of the page when the panel is opened and remove it when it's closed? That makes this much simpler:
$('.class #content').click(function(){
// Close the contact panel
});
Now, when the body has a class of 'class', any click on the #content div will automatically close contact.
Make sense? Great looking site, by the way.
$('#flip').bind('click', function(){
$(this).toggleClass('contactOpen');
$("#panel").slideToggle("3000");
});
$('#content').bind('click', function(){
if($('#flip').hasClass('contactOpen')){
$(this).toggleClass('contactOpen');
$("#panel").slideToggle("3000");
}
});

Categories

Resources