[FIX] web: tooltip service should not cleanup when mouse is inside
Steps to reproduce
==================
- Use a laptop with touch or apply the following patch
```diff
diff --git a/addons/web/static/src/core/browser/feature_detection.js b/addons/web/static/src/core/browser/feature_detection.js
index 21c6294b1b0e..64c4bc9b899c 100644
--- a/addons/web/static/src/core/browser/feature_detection.js
+++ b/addons/web/static/src/core/browser/feature_detection.js
@@ -62,6 +62,7 @@ export function isDisplayStandalone() {
}
export function hasTouch() {
+ return true;
return browser.ontouchstart !== undefined || browser.matchMedia("(pointer:coarse)").matches;
}
```
- Enable debug mode
- Go to contacts
- Hover the mouse over a question mark next to a field
=> Nothing happens
Cause of the issue
==================
The function `shouldCleanup` returns true when the device has touch and
the popover has been triggerd with the mouse
opw-3694156
closes odoo/odoo#152629
X-original-commit: 27242a0f1070b6b16c16e479e22dc0ccad0d9659
Signed-off-by: Pierre Paridans (app) <app@odoo.com>
This commit is contained in:
@@ -51,6 +51,7 @@ export const tooltipService = {
|
||||
let closeTooltip;
|
||||
let target = null;
|
||||
let touchPressed;
|
||||
let mouseEntered;
|
||||
const elementsWithTooltips = new Map();
|
||||
|
||||
/**
|
||||
@@ -74,7 +75,7 @@ export const tooltipService = {
|
||||
if (!document.body.contains(target)) {
|
||||
return true; // target is no longer in the DOM
|
||||
}
|
||||
if (hasTouch()) {
|
||||
if (hasTouch() && !mouseEntered) {
|
||||
return !touchPressed;
|
||||
}
|
||||
return false;
|
||||
@@ -153,11 +154,13 @@ export const tooltipService = {
|
||||
* @param {MouseEvent} ev a "mouseenter" event
|
||||
*/
|
||||
function onMouseenter(ev) {
|
||||
mouseEntered = true;
|
||||
openElementsTooltip(ev.target);
|
||||
}
|
||||
|
||||
function onMouseleave(ev) {
|
||||
if (target === ev.target) {
|
||||
mouseEntered = false;
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,4 +443,47 @@ QUnit.module("Tooltip service", (hooks) => {
|
||||
// tooltip did not crash and is not shown
|
||||
assert.containsNone(target, ".o_popover");
|
||||
});
|
||||
|
||||
QUnit.test("tooltip using the mouse with a touch enabled device", async (assert) => {
|
||||
// patch matchMedia to alter hasTouch value
|
||||
patchWithCleanup(browser, {
|
||||
matchMedia: (media) => {
|
||||
if (media === "(pointer:coarse)") {
|
||||
return { matches: true };
|
||||
}
|
||||
return this._super();
|
||||
},
|
||||
});
|
||||
|
||||
class MyComponent extends Component {}
|
||||
MyComponent.template = xml`<button class="mybtn" data-tooltip="hello">Action</button>`;
|
||||
let simulateTimeout;
|
||||
let simulateInterval;
|
||||
const mockSetTimeout = (fn) => {
|
||||
simulateTimeout = fn;
|
||||
};
|
||||
const mockSetInterval = (fn) => {
|
||||
simulateInterval = fn;
|
||||
};
|
||||
await makeParent(MyComponent, { mockSetInterval, mockSetTimeout });
|
||||
|
||||
assert.containsNone(target, ".o_popover");
|
||||
target.querySelector(".mybtn").dispatchEvent(new Event("mouseenter"));
|
||||
await nextTick();
|
||||
assert.containsNone(target, ".o_popover");
|
||||
|
||||
simulateTimeout();
|
||||
await nextTick();
|
||||
assert.containsOnce(target, ".o_popover");
|
||||
assert.strictEqual(target.querySelector(".o_popover").innerText, "hello");
|
||||
|
||||
simulateInterval();
|
||||
await nextTick();
|
||||
assert.containsOnce(target, ".o_popover");
|
||||
assert.strictEqual(target.querySelector(".o_popover").innerText, "hello");
|
||||
|
||||
target.querySelector(".mybtn").dispatchEvent(new Event("mouseleave"));
|
||||
await nextTick();
|
||||
assert.containsNone(target, ".o_popover");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user