aboutsummaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorPierre-Denis Vanduynslager <[email protected]>2017-01-02 17:44:27 -0500
committerMark Otto <[email protected]>2017-01-02 14:44:27 -0800
commitbbb0d2b573c28793358be66a1c05f2d68ded4db6 (patch)
tree24e4c0d7000c596f7f5790d929776d0a9ec8cc59 /js
parent9fc54f89f4d7a15c4118835b7eeae810cc8c5c0a (diff)
downloadbootstrap-bbb0d2b573c28793358be66a1c05f2d68ded4db6.tar.xz
bootstrap-bbb0d2b573c28793358be66a1c05f2d68ded4db6.zip
Dropdown: close menu when focusing outside element (#21375)
* Close dropdown menu when focusing an outside element * Update unit test to new markup
Diffstat (limited to 'js')
-rw-r--r--js/src/dropdown.js9
-rw-r--r--js/tests/unit/dropdown.js60
2 files changed, 65 insertions, 4 deletions
diff --git a/js/src/dropdown.js b/js/src/dropdown.js
index 97bba1c76..29c4efe04 100644
--- a/js/src/dropdown.js
+++ b/js/src/dropdown.js
@@ -35,6 +35,7 @@ const Dropdown = (($) => {
SHOWN : `shown${EVENT_KEY}`,
CLICK : `click${EVENT_KEY}`,
CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,
+ FOCUSIN_DATA_API : `focusin${EVENT_KEY}${DATA_API_KEY}`,
KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`
}
@@ -180,9 +181,9 @@ const Dropdown = (($) => {
continue
}
- if (event && event.type === 'click' &&
- /input|textarea/i.test(event.target.tagName) &&
- $.contains(parent, event.target)) {
+ if (event && (event.type === 'click' &&
+ /input|textarea/i.test(event.target.tagName) || event.type === 'focusin')
+ && $.contains(parent, event.target)) {
continue
}
@@ -275,7 +276,7 @@ const Dropdown = (($) => {
.on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler)
.on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler)
- .on(Event.CLICK_DATA_API, Dropdown._clearMenus)
+ .on(`${Event.CLICK_DATA_API} ${Event.FOCUSIN_DATA_API}`, Dropdown._clearMenus)
.on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle)
.on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {
e.stopPropagation()
diff --git a/js/tests/unit/dropdown.js b/js/tests/unit/dropdown.js
index 53455c2a6..9a34fc0c9 100644
--- a/js/tests/unit/dropdown.js
+++ b/js/tests/unit/dropdown.js
@@ -192,6 +192,30 @@ $(function () {
assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
})
+ QUnit.test('should remove "show" class if body is focused', function (assert) {
+ assert.expect(2)
+ var dropdownHTML = '<div class="tabs">'
+ + '<div class="dropdown">'
+ + '<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>'
+ + '<div class="dropdown-menu">'
+ + '<a class="dropdown-item" href="#">Secondary link</a>'
+ + '<a class="dropdown-item" href="#">Something else here</a>'
+ + '<div class="dropdown-divider"/>'
+ + '<a class="dropdown-item" href="#">Another link</a>'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ var $dropdown = $(dropdownHTML)
+ .appendTo('#qunit-fixture')
+ .find('[data-toggle="dropdown"]')
+ .bootstrapDropdown()
+ .trigger('click')
+
+ assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
+ $(document.body).trigger('focusin')
+ assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
+ })
+
QUnit.test('should remove "show" class if body is clicked, with multiple dropdowns', function (assert) {
assert.expect(7)
var dropdownHTML = '<ul class="nav">'
@@ -229,6 +253,42 @@ $(function () {
assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
})
+ QUnit.test('should remove "show" class if body is focused, with multiple dropdowns', function (assert) {
+ assert.expect(7)
+ var dropdownHTML = '<div class="nav">'
+ + '<div class="dropdown" id="testmenu">'
+ + '<a class="dropdown-toggle" data-toggle="dropdown" href="#testmenu">Test menu <span class="caret"/></a>'
+ + '<div class="dropdown-menu">'
+ + '<a class="dropdown-item" href="#sub1">Submenu 1</a>'
+ + '</div>'
+ + '</div>'
+ + '</div>'
+ + '<div class="btn-group">'
+ + '<button class="btn">Actions</button>'
+ + '<button class="btn dropdown-toggle" data-toggle="dropdown"><span class="caret"/></button>'
+ + '<div class="dropdown-menu">'
+ + '<a class="dropdown-item" href="#">Action 1</a>'
+ + '</div>'
+ + '</div>'
+ var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
+ var $first = $dropdowns.first()
+ var $last = $dropdowns.last()
+
+ assert.strictEqual($dropdowns.length, 2, 'two dropdowns')
+
+ $first.trigger('click')
+ assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
+ assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show')
+ $(document.body).trigger('focusin')
+ assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
+
+ $last.trigger('click')
+ assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
+ assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is show')
+ $(document.body).trigger('focusin')
+ assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
+ })
+
QUnit.test('should fire show and hide event', function (assert) {
assert.expect(2)
var dropdownHTML = '<ul class="tabs">'