When it happens
Event shown.bs.modal is not fired when modal has also class "fade". Whereas show.bs.modal always works.
See https://github.com/twbs/bootstrap/issues/11793
HTML:
<div class="modal fade" id="first" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">Hello world from first modal</div>
</div>
</div>
<div class="modal" id="second" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">Hello world from second modal</div>
</div>
</div>
jQuery:
$('.modal').on('shown.bs.modal', function() {
//fired only in second modal
console.info('shown.bs.modal');
});
$('.modal').on('show.bs.modal', function() {
//fired always
console.info('show.bs.modal');
});
Solution
For bootstrap v3.3.6 replace line 1010 with:
that.$element // wait for modal to slide in
What is the problem
Look at lines 1006-1015:
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$dialog // wait for modal to slide in
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
Without transition (no fade class) the event e is triggered right away (on that.$element).
With transition, I'm not sure why exactly, but somehow the bsTransationEnd event from function emulateTransitionEnd is not handled by that.$dialog.one(). But with that.$element, everything seem to work.