From 88fd1cf4838b0ea28ea484655dd2aef6a5ec5291 Mon Sep 17 00:00:00 2001 From: Joseph Caburnay Date: Wed, 21 Apr 2021 15:21:15 +0200 Subject: [PATCH] [FIX] extensions: guarantee to call transitionend callback There is a possibility that the transitionend event of an element/component with t-transition directive won't trigger. Though this situation is difficult to assert, it was observe in odoo runbot for the pos ui. When the transitionend event is not fired, the callback that removes the element from the dom won't be called, resulting to a corrupted view. An example of which is the following: ```html
Hello
``` If `show` is set to false by some ui action and by any chance the transitionend event is not fired (perhaps because the transition didn't actually start or because of completely unknown reason), the div element will remain in the view -- and this is not desirable. This commit patches this situation such that if after 50ms that the transitionend event is supposed to be fired but the event isn't fired, we force the callback using a setTimeout. This guarantees the call of the callback that is suppose to remove the element from the view. --- src/qweb/extensions.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/qweb/extensions.ts b/src/qweb/extensions.ts index 33c618c8..7de1acee 100644 --- a/src/qweb/extensions.ts +++ b/src/qweb/extensions.ts @@ -2,6 +2,7 @@ import { STATUS } from "../component/component"; import { VNode } from "../vdom/index"; import { INTERP_REGEXP } from "./compilation_context"; import { QWeb } from "./qweb"; +import { browser } from "../browser"; /** * Owl QWeb Extensions @@ -198,7 +199,14 @@ function whenTransitionEnd(elm: HTMLElement, cb) { const durations: Array = (styles.transitionDuration || "").split(", "); const timeout: number = getTimeout(delays, durations); if (timeout > 0) { - elm.addEventListener("transitionend", cb, { once: true }); + const transitionEndCB = () => { + if (!elm.parentNode) return; + cb(); + browser.clearTimeout(fallbackTimeout); + elm.removeEventListener("transitionend", transitionEndCB); + }; + elm.addEventListener("transitionend", transitionEndCB, { once: true }); + const fallbackTimeout = browser.setTimeout(transitionEndCB, timeout + 1); } else { cb(); }