]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Fixes #21941
authorPierre-Denis Vanduynslager <pierre.denis.vanduynslager@gmail.com>
Wed, 8 Feb 2017 23:51:50 +0000 (18:51 -0500)
committerPierre-Denis Vanduynslager <pierre.denis.vanduynslager@gmail.com>
Wed, 8 Feb 2017 23:51:50 +0000 (18:51 -0500)
js/src/dropdown.js
js/tests/unit/dropdown.js

index 5c204f0544bef5f13b1cc5367ccf64f60fe51f64..1e85c2530bee1e4e5726299cc877e94cdb0a7e05 100644 (file)
@@ -25,6 +25,7 @@ const Dropdown = (($) => {
   const JQUERY_NO_CONFLICT       = $.fn[NAME]
   const ESCAPE_KEYCODE           = 27 // KeyboardEvent.which value for Escape (Esc) key
   const SPACE_KEYCODE            = 32 // KeyboardEvent.which value for space key
+  const TAB_KEYCODE              = 9 // KeyboardEvent.which value for tab key
   const ARROW_UP_KEYCODE         = 38 // KeyboardEvent.which value for up arrow key
   const ARROW_DOWN_KEYCODE       = 40 // KeyboardEvent.which value for down arrow key
   const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)
@@ -37,8 +38,8 @@ 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}`
+    KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,
+    KEYUP_DATA_API   : `keyup${EVENT_KEY}${DATA_API_KEY}`
   }
 
   const ClassName = {
@@ -160,7 +161,8 @@ const Dropdown = (($) => {
     }
 
     static _clearMenus(event) {
-      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+      if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||
+        event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
         return
       }
 
@@ -182,7 +184,7 @@ const Dropdown = (($) => {
         }
 
         if (event && (event.type === 'click' &&
-            /input|textarea/i.test(event.target.tagName) || event.type === 'focusin')
+            /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE)
             && $.contains(parent, event.target)) {
           continue
         }
@@ -213,7 +215,7 @@ const Dropdown = (($) => {
     }
 
     static _dataApiKeydownHandler(event) {
-      if (!REGEXP_KEYDOWN.test(event.which) && /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE ||
+      if (!REGEXP_KEYDOWN.test(event.which) || /button/i.test(event.target.tagName) && event.which === SPACE_KEYCODE ||
          /input|textarea/i.test(event.target.tagName)) {
         return
       }
@@ -275,7 +277,7 @@ const Dropdown = (($) => {
   $(document)
     .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE,  Dropdown._dataApiKeydownHandler)
     .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)
-    .on(`${Event.CLICK_DATA_API} ${Event.FOCUSIN_DATA_API}`, Dropdown._clearMenus)
+    .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_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()
index 5afa2ee03f6d102869cdc6f755884acee3f1b40f..a15eb52450d66ac83634ce682ee2e79e8259db35 100644 (file)
@@ -216,7 +216,7 @@ $(function () {
     $dropdown.trigger('click')
   })
 
-  QUnit.test('should remove "show" class if body is focused', function (assert) {
+  QUnit.test('should remove "show" class if tabbing outside of menu', function (assert) {
     assert.expect(2)
     var done = assert.async()
     var dropdownHTML = '<div class="tabs">'
@@ -238,7 +238,9 @@ $(function () {
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        assert.ok($dropdown.parent('.dropdown').hasClass('show'), '"show" class added on click')
-       $(document.body).trigger('focusin')
+       var e = $.Event('keyup')
+       e.which = 9 // Tab
+       $(document.body).trigger(e)
      }).on('hidden.bs.dropdown', function () {
        assert.ok(!$dropdown.parent('.dropdown').hasClass('show'), '"show" class removed')
        done()
@@ -292,7 +294,7 @@ $(function () {
     $first.trigger('click')
   })
 
-  QUnit.test('should remove "show" class if body is focused, with multiple dropdowns', function (assert) {
+  QUnit.test('should remove "show" class if body if tabbing outside of menu, with multiple dropdowns', function (assert) {
     assert.expect(7)
     var done = assert.async()
     var dropdownHTML = '<div class="nav">'
@@ -320,7 +322,9 @@ $(function () {
     .on('shown.bs.dropdown', function () {
       assert.strictEqual($first.parents('.show').length, 1, '"show" class added on click')
       assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown')
-      $(document.body).trigger('focusin')
+      var e = $.Event('keyup')
+      e.which = 9 // Tab
+      $(document.body).trigger(e)
     }).on('hidden.bs.dropdown', function () {
       assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
       $last.trigger('click')
@@ -330,7 +334,9 @@ $(function () {
     .on('shown.bs.dropdown', function () {
       assert.strictEqual($last.parent('.show').length, 1, '"show" class added on click')
       assert.strictEqual($('#qunit-fixture .show').length, 1, 'only one dropdown is shown')
-      $(document.body).trigger('focusin')
+      var e = $.Event('keyup')
+      e.which = 9 // Tab
+      $(document.body).trigger(e)
     }).on('hidden.bs.dropdown', function () {
       assert.strictEqual($('#qunit-fixture .show').length, 0, '"show" class removed')
       done()