diff --git a/addons/web/static/src/core/tooltip/tooltip_service.js b/addons/web/static/src/core/tooltip/tooltip_service.js index 684421f8e68..a398562510f 100644 --- a/addons/web/static/src/core/tooltip/tooltip_service.js +++ b/addons/web/static/src/core/tooltip/tooltip_service.js @@ -23,6 +23,10 @@ const { whenReady } = owl; * The opening delay can be modified with the "data-tooltip-delay" attribute (default: 400): * * + * The default behaviour on touch devices to open the tooltip can be modified from "hold-to-show" + * to "tap-to-show" "with the data-tooltip-touch-tap-to-show" attribute: + * + * * For advanced tooltips containing dynamic and/or html content, the * "data-tooltip-template" and "data-tooltip-info" attributes can be used. * For example, let's suppose the following qweb template: @@ -188,12 +192,20 @@ export const tooltipService = { if (hasTouch()) { document.body.addEventListener("touchstart", onTouchStart); - document.body.addEventListener("touchend", () => { - touchPressed = false; + document.body.addEventListener("touchend", (ev) => { + if (ev.target.matches("[data-tooltip], [data-tooltip-template]")) { + if (!ev.target.dataset.tooltipTouchTapToShow) { + touchPressed = false; + } + } }); - document.body.addEventListener("touchcancel", () => { - touchPressed = false; + document.body.addEventListener("touchcancel", (ev) => { + if (ev.target.matches("[data-tooltip], [data-tooltip-template]")) { + if (!ev.target.dataset.tooltipTouchTapToShow) { + touchPressed = false; + } + } }); return; diff --git a/addons/web/static/src/views/form/form_label.js b/addons/web/static/src/views/form/form_label.js index ea79db9e04d..d9e826d333e 100644 --- a/addons/web/static/src/views/form/form_label.js +++ b/addons/web/static/src/views/form/form_label.js @@ -55,6 +55,6 @@ export class FormLabel extends Component { } FormLabel.template = xml` `; diff --git a/addons/web/static/tests/core/tooltip/tooltip_service_tests.js b/addons/web/static/tests/core/tooltip/tooltip_service_tests.js index 5c1c5a9f4b2..b2b1f7a0788 100644 --- a/addons/web/static/tests/core/tooltip/tooltip_service_tests.js +++ b/addons/web/static/tests/core/tooltip/tooltip_service_tests.js @@ -381,7 +381,7 @@ QUnit.module("Tooltip service", (hooks) => { await nextTick(); }); - QUnit.test("touch rendering", async (assert) => { + QUnit.test("touch rendering - hold-to-show", async (assert) => { class MyComponent extends Component {} MyComponent.template = xml``; let simulateTimeout; @@ -414,4 +414,41 @@ QUnit.module("Tooltip service", (hooks) => { await nextTick(); assert.containsNone(target, ".o_popover_container .o_popover"); }); + + QUnit.test("touch rendering - tap-to-show", async (assert) => { + class MyComponent extends Component {} + MyComponent.template = xml``; + let simulateTimeout; + const mockSetTimeout = (fn) => { + simulateTimeout = fn; + }; + let simulateInterval; + const mockSetInterval = (fn) => { + simulateInterval = fn; + }; + const mockOnTouchStart = () => {}; + await makeParent(MyComponent, { mockSetTimeout, mockSetInterval, mockOnTouchStart }); + + assert.containsNone(target, ".o_popover_container .o_popover"); + await triggerEvent(target, "button[data-tooltip]", "touchstart"); + await nextTick(); + assert.containsNone(target, ".o_popover_container .o_popover"); + + simulateTimeout(); + await nextTick(); + assert.containsOnce(target, ".o_popover_container .o_popover"); + assert.strictEqual( + target.querySelector(".o_popover_container .o_popover").innerText, + "hello" + ); + + await triggerEvent(target, "button[data-tooltip]", "touchend"); + assert.containsOnce(target, ".o_popover_container .o_popover"); + simulateInterval(); + await nextTick(); + assert.containsOnce(target, ".o_popover_container .o_popover"); + + await triggerEvent(target, "button[data-tooltip]", "touchstart"); + assert.containsNone(target, ".o_popover_container .o_popover"); + }); });