I'm using this code to make a Bootstrap 3.4.1 modal non-closable -- to not allow the user to click outside the modal or use Esc to close it, while still allowing the normal .modal("hide")
and data-dismiss="modal"
to work:
$('#myModal').removeData('bs.modal')
.modal({
backdrop: 'static',
keyboard: false
});
This is from this comment on an answer: Disallow Twitter Bootstrap modal window from closing
However, I'm struggling to reverse the above. Just passing in the opposite options won't work; the modal remains non-closable:
$("#myModal").modal({
backdrop: true,
keyboard: true
});
With help from the SO JavaScript chat (thanks @matt), I also tried using the hide.bs.modal
handler, wherein I'd read a data-allow-close
attribute within to determine if I should allow closing via keyboard/mouse:
attachNonClosableModalHideHandler: function() {
const $self = $(this);
$("#myModal").on("hide.bs.modal", $self.handleNonClosableModalHide);
},
handleNonClosableModalHide: function () {
return $(this).data("allow-close");
}
Here's the modal's main DIV tag:
<div id="myModal" class="modal default fade" tabindex="-1"
role="dialog" data-allow-close="true">...</div>
However, the above handler prevents calls to $("#myModal").modal("hide")
from working because I now need to set the allow-close
data attribute before doing so. Also, the data-dismiss="modal"
buttons within the modal won't work for the same reason.
I created this jQuery plugin to call as a wrapper for hiding the modal but it's all becoming cumbersome:
$.fn.hideNonClosableModal = function () {
const $self = $(this);
const hasClass = $self.hasClass("modal");
const hasRole = $self.attr("role") === "dialog";
if (!hasClass || !hasRole) {
return this;
}
$self.data("allow-close", true);
$self.modal("hide");
return this;
};
It shouldn't be this difficult to make a modal closable again. What am I doing wrong? Thanks.
With great help from (and thanks to) this answer, here's a solution for Bootstrap 3.x:
To make the modal non-closable:
$("#myModal").modal("hide");
$("#myModal").data("bs.modal").options.backdrop = 'static';
$("#myModal").off("keydown.dismiss.bs.modal");
$("#myModal").data("bs.modal").options.keyboard = false;
To make it closable:
$("#myModal").modal("hide");
$("#myModal").data("bs.modal").options.backdrop = true;
$("#myModal").data("bs.modal").escape(); // Resets the keyboard.
We need to call $("#myModal").modal("hide");
to initialize the modal and make the options available. We can also check data("bs.modal")
to determine if modal's initialized (see below).
Here it is in a jQuery plugin:
$.fn.toggleModalClosable = function (options) {
// Options can be reduced to a bool argument.
const settings = $.extend({
isClosable: true
}, options);
const $self = $(this);
// If this isn't a modal, return this.
if (!$self.hasClass("modal") || $self.attr("role") !== "dialog"){
return this;
}
// If modal's not initialized, initialize it by hiding it.
// If we've shown or hidden the modal, it's been initialized.
if (!$self.data("bs.modal")) {
$self.modal("hide");
}
if (options.isClosable) {
$self.data("bs.modal").options.backdrop = true;
$self.data("bs.modal").escape();
$(".mymodal-close-button").show();
} else {
$self.data("bs.modal").options.backdrop = "static";
$self.off("keydown.dismiss.bs.modal");
$self.data("bs.modal").options.keyboard = false;
$(".mymodal-close-button").hide();
}
return this;
};