From 78f85f2725ef3d9194ab17f6bf7b2d236b07821e Mon Sep 17 00:00:00 2001 From: Bruno Boi Date: Thu, 17 Feb 2022 09:46:36 +0000 Subject: [PATCH] [FIX] web: repair some keynav in dropdowns ENCOUNTERED ISSUE: Unable to close a dropdown with ESC when the focus has been given to a select element inside the dropdown. TO REPRODUCE: i.e. in the searchpanel, go to "FilterMenu > Add Custom Filter" and open the field select element. Press ESC once: the field select element closes just fine. Press ESC a 2nd time: we expect the dropdown to close but nothing occur. REASON EXPLANATION: Since 84715436d our Dropdown component uses the 'dropdown-menu' bootstrap class. But under some conditions bootstrap stops the keydown events propagation when the event.target matches the query selector '.dropdown-menu'. IMPLEMENTED FIX: This commit refines this selector directly inside the bootstrap library. This is admittedly a bad practice but: - this modification is trivial and sensible - the modified selector is only used locally in the bootstrap's 'dropdown.js' file - the added test should prevent the lost of this customization in the future task-2764821 Part-of: odoo/odoo#84969 --- .../web/static/lib/bootstrap/js/dropdown.js | 2 +- .../web/static/tests/core/dropdown_tests.js | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/addons/web/static/lib/bootstrap/js/dropdown.js b/addons/web/static/lib/bootstrap/js/dropdown.js index 2d011d75513..d1ccec1f550 100644 --- a/addons/web/static/lib/bootstrap/js/dropdown.js +++ b/addons/web/static/lib/bootstrap/js/dropdown.js @@ -111,7 +111,7 @@ var Selector = { DATA_TOGGLE: '[data-toggle="dropdown"]', FORM_CHILD: '.dropdown form', - MENU: '.dropdown-menu', + MENU: '.dropdown-menu:not(.o-dropdown--menu)', // Odoo fix task-2764821 NAVBAR_NAV: '.navbar-nav', VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' }; diff --git a/addons/web/static/tests/core/dropdown_tests.js b/addons/web/static/tests/core/dropdown_tests.js index a2c2eb2975a..45406ba9ae1 100644 --- a/addons/web/static/tests/core/dropdown_tests.js +++ b/addons/web/static/tests/core/dropdown_tests.js @@ -665,6 +665,37 @@ QUnit.module("Components", ({ beforeEach }) => { assert.verifySteps(["1", "2"], "items should have been selected in this order"); }); + QUnit.test("dropdowns keynav is not impacted by bootstrap", async (assert) => { + class Parent extends Component {} + Parent.components = { Dropdown }; + Parent.template = xml` + + + + `; + env = await makeTestEnv(); + await mount(Parent, target, { env }); + assert.containsOnce(target, ".dropdown-menu", "menu is opened at start"); + const menu = target.querySelector(".dropdown-menu"); + + // This class presence makes bootstrap ignore the below event + assert.hasClass(menu, "o-dropdown--menu"); + + const select = menu.querySelector("select"); + const ev = new KeyboardEvent("keydown", { + bubbles: true, + // Define the ESC key with standard API (for hotkey_service) + key: "Escape", + code: "Escape", + // Define the ESC key with deprecated API (for bootstrap) + keyCode: 27, + which: 27, + }); + select.dispatchEvent(ev); + await nextTick(); + assert.containsNone(target, ".dropdown-menu", "menu is now closed"); + }); + QUnit.test("props toggler='parent'", async (assert) => { class Parent extends Component {} Parent.template = xml`