From ed53db792a6d1ecb712142d1a38a2e75b85cbf7f Mon Sep 17 00:00:00 2001 From: Hardik Prajapati Date: Wed, 5 Aug 2020 13:10:26 +0000 Subject: [PATCH] [FIX] web: prevent dropdown closing on mouseup Before this commit, selecting the whole content of the custom filter input and releasing the cursor outside of the dropdown closed the dropdown. With this commit, the dropdown is kept open in this situation. task - 2276544 closes odoo/odoo#57807 X-original-commit: 450e0ec45005c3d6c2e8475e134113a7d8515e9f Signed-off-by: Aaron Bohy (aab) Co-authored-by: Mohammed Shekha --- .../static/src/js/components/dropdown_menu.js | 6 ++- .../src/js/components/dropdown_menu_item.js | 6 ++- .../tests/components/dropdown_menu_tests.js | 43 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/components/dropdown_menu.js b/addons/web/static/src/js/components/dropdown_menu.js index c536f3caba7..64c30b6500e 100644 --- a/addons/web/static/src/js/components/dropdown_menu.js +++ b/addons/web/static/src/js/components/dropdown_menu.js @@ -121,7 +121,11 @@ odoo.define('web.DropdownMenu', function (require) { * @param {MouseEvent} ev */ _onWindowClick(ev) { - if (this.state.open && !this.el.contains(ev.target)) { + if ( + this.state.open && + !this.el.contains(ev.target) && + !this.el.contains(document.activeElement) + ) { this.state.open = false; } } diff --git a/addons/web/static/src/js/components/dropdown_menu_item.js b/addons/web/static/src/js/components/dropdown_menu_item.js index bc028e17719..bcc54ab4ffb 100644 --- a/addons/web/static/src/js/components/dropdown_menu_item.js +++ b/addons/web/static/src/js/components/dropdown_menu_item.js @@ -86,7 +86,11 @@ odoo.define('web.DropdownMenuItem', function (require) { * @param {MouseEvent} ev */ _onWindowClick(ev) { - if (this.state.open && !this.el.contains(ev.target)) { + if ( + this.state.open && + !this.el.contains(ev.target) && + !this.el.contains(document.activeElement) + ) { this.state.open = false; } } diff --git a/addons/web/static/tests/components/dropdown_menu_tests.js b/addons/web/static/tests/components/dropdown_menu_tests.js index a0f00b68ef1..da0d458d680 100644 --- a/addons/web/static/tests/components/dropdown_menu_tests.js +++ b/addons/web/static/tests/components/dropdown_menu_tests.js @@ -339,5 +339,48 @@ odoo.define('web.dropdown_menu_tests', function (require) { parent.destroy(); }); + + QUnit.test("dropdown doesn't get close on mousedown inside and mouseup outside dropdown", async function (assert) { + // In this test, we simulate a case where the user clicks inside a dropdown menu item + // (e.g. in the input of the 'Save current search' item in the Favorites menu), keeps + // the click pressed, moves the cursor outside the dropdown and releases the click + // (i.e. mousedown and focus inside the item, mouseup and click outside the dropdown). + // In this case, we want to keep the dropdown menu open. + assert.expect(5); + + const items = this.items; + class Parent extends owl.Component { + constructor() { + super(...arguments); + this.items = items; + } + } + Parent.components = { DropdownMenu }; + Parent.template = owl.tags.xml` +
+ +
`; + const parent = new Parent(); + await parent.mount(testUtils.prepareTarget(), { position: "first-child" }); + + const menu = parent.el.querySelector(".o_dropdown"); + assert.doesNotHaveClass(menu, "show", "dropdown should not be open"); + + await testUtils.dom.click(menu.querySelector("button")); + assert.hasClass(menu, "show", "dropdown should be open"); + + const firstItemEl = menu.querySelector(".o_menu_item > a"); + // open options menu + await testUtils.dom.click(firstItemEl); + assert.hasClass(firstItemEl.querySelector("i"), "o_icon_right fa fa-caret-down"); + + // force the focus inside the dropdown item and click outside + firstItemEl.parentElement.querySelector(".o_menu_item_options .o_item_option a").focus(); + await testUtils.dom.triggerEvents(parent.el, "click"); + assert.hasClass(menu, "show", "dropdown should still be open"); + assert.hasClass(firstItemEl.querySelector("i"), "o_icon_right fa fa-caret-down"); + + parent.destroy(); + }); }); });