diff --git a/js/modal.js b/js/modal.js
index a89eb0c09f..20c6712b3d 100644
--- a/js/modal.js
+++ b/js/modal.js
@@ -268,10 +268,13 @@
if ($this.is('a')) e.preventDefault()
- Plugin.call($target, option, this)
- $target.one('hide.bs.modal', function () {
- $this.is(':visible') && $this.trigger('focus')
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
})
+ Plugin.call($target, option, this)
})
}(jQuery);
diff --git a/js/tests/unit/modal.js b/js/tests/unit/modal.js
index d8bef3ea1a..667de547a9 100644
--- a/js/tests/unit/modal.js
+++ b/js/tests/unit/modal.js
@@ -201,4 +201,55 @@ $(function () {
div.remove()
})
+
+ test('should restore focus to toggling element when modal is hidden after having been opened via data-api', function () {
+ stop()
+ $.support.transition = false
+ var toggleBtn = $('').appendTo('#qunit-fixture')
+ var div = $('
')
+ div
+ .on('hidden.bs.modal', function () {
+ window.setTimeout(function () { // give the focus restoration callback a chance to run
+ equal(document.activeElement, toggleBtn[0], 'toggling element is once again focused')
+ div.remove()
+ toggleBtn.remove()
+ start()
+ }, 0)
+ })
+ .on('shown.bs.modal', function () {
+ $('#close').click()
+ })
+ .appendTo('#qunit-fixture')
+ toggleBtn.click()
+ })
+
+ test('should not restore focus to toggling element if the associated show event gets prevented', function () {
+ stop()
+ $.support.transition = false
+ var toggleBtn = $('').appendTo('#qunit-fixture')
+ var otherBtn = $('').appendTo('#qunit-fixture')
+ var div = $('
')
+ div
+ .one('show.bs.modal', function (e) {
+ e.preventDefault()
+ otherBtn.focus()
+ window.setTimeout(function () { // give the focus event from the previous line a chance to run
+ div.bootstrapModal('show')
+ }, 0)
+ })
+ .on('hidden.bs.modal', function () {
+ window.setTimeout(function () { // give the focus restoration callback a chance to run (except it shouldn't run in this case)
+ equal(document.activeElement, otherBtn[0], 'show was prevented, so focus should not have been restored to toggling element')
+ div.remove()
+ toggleBtn.remove()
+ otherBtn.remove()
+ start()
+ }, 0)
+ })
+ .on('shown.bs.modal', function () {
+ $('#close').click()
+ })
+ .appendTo('#qunit-fixture')
+ toggleBtn.click()
+ })
})