I am showing a Bootstrap modal window for loading when performing AJAX calls. I broadcast a \"progress.init\" event when the loading modal should show and a \"progress.finis
The problem is that bootstrap removes the backdrop asynchronously. So when you call hide and show quickly after each other, the backdrop isn't removed.
The solution (as you've mentioned) is to wait for the modal to have been hidden completely, using the 'hidden.bs.modal' event. Use jQuery one to only perform the callback once. I've forked your jsfiddle to show how this would work.
// wait for the backdrop to be removed nicely.
loadingModal.one('hidden.bs.modal', function()
{
loadingModal.modal("show");
//Again simulate 3 seconds
setTimeout(function () {
loadingModal.modal("hide");
}, 3000);
});
// hide for the first time, after binding to the hidden event.
loadingModal.modal("hide");
Looking through the code in Bootstrap:
This is what makes hiding the modal asynchronous:
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
This checks whether transitions are supported and the fade class is included on the modal. When both are true, it waits for the fade effect to complete, before hiding the modal. This waiting happens again before removing the backdrop.
This is why removing the fade class will make hiding the modal synchronous (no more waiting for CSS fade effect to complete) and why the solution by reznic works.
This check determines whether to add or remove the backdrop. isShown = true is performed synchronously. When you call hide and show quickly after each other, isShown becomes true and the check adds a backdrop, instead of removing the previous one, creating the problem you're having.