Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling of transitionend events dispatched by nested elements #33845

Merged
merged 2 commits into from Jun 3, 2021

Conversation

alpadev
Copy link
Contributor

@alpadev alpadev commented May 6, 2021

@GeoSot GeoSot added this to Inbox in v5.0.1 via automation May 11, 2021
@GeoSot GeoSot force-pushed the fix-transitionend-event-handling branch from 0199be3 to 5d73f20 Compare May 11, 2021 21:47
@mdo
Copy link
Member

mdo commented May 13, 2021

Is this ready for review and shipping with v5.0.1?

@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from 92e64d5 to 349e414 Compare May 13, 2021 12:01
@alpadev alpadev marked this pull request as ready for review May 13, 2021 12:03
@alpadev alpadev requested a review from a team as a code owner May 13, 2021 12:03
@GeoSot GeoSot moved this from Inbox to Review in v5.0.1 May 13, 2021
js/src/modal.js Outdated Show resolved Hide resolved
@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from 349e414 to aead9dd Compare May 13, 2021 12:49
rohit2sharma95
rohit2sharma95 previously approved these changes May 13, 2021
v5.0.1 automation moved this from Review to Approved May 13, 2021
GeoSot
GeoSot previously approved these changes May 13, 2021
@alpadev alpadev force-pushed the fix-transitionend-event-handling branch 2 times, most recently from 68cb2cb to 4c3c946 Compare May 13, 2021 16:05
@XhmikosR
Copy link
Member

@alpadev would it be OK to move this to 5.0.2? I plan to make the release soon, and I'm unsure if we should land this in such a hurry :)

@XhmikosR XhmikosR added this to Inbox in v5.0.2 via automation May 13, 2021
@XhmikosR XhmikosR removed this from Approved in v5.0.1 May 13, 2021
@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from 4c3c946 to 2064073 Compare May 13, 2021 16:11
@alpadev
Copy link
Contributor Author

alpadev commented May 13, 2021

@alpadev would it be OK to move this to 5.0.2? I plan to make the release soon, and I'm unsure if we should land this in such a hurry :)

Proceed as you wish, I don't mind. Been quite busy and missed the information in slack that we would do a release today. Otherwise I would have tried to focus more on this PR.

@alpadev alpadev force-pushed the fix-transitionend-event-handling branch 2 times, most recently from 9c4bb8a to 106bbca Compare May 13, 2021 16:27
@alpadev alpadev requested a review from GeoSot May 13, 2021 16:34
@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from a0c2f97 to 707ef8e Compare May 13, 2021 17:09
@GeoSot
Copy link
Member

GeoSot commented May 14, 2021

Now that we have time, guys do you consider changing theemulateTransitionEnd arguments is a breaking change or not?
Theoretically yes, but as our utils are not officially documented and exported, I suppose are remaining internal.

I am asking this, cause as Alpa said, the footprint of this change will be less compared with the extra function approach

CC/ @XhmikosR

@XhmikosR
Copy link
Member

Technically, it could be a BC, but since we are not exposing directly the utils, I'd say we can make the change, if it helps us. At some point, we should expose our utils, but that's for another time.

v5.0.2 automation moved this from Approved to Review May 20, 2021
return
}

const durationPadding = 5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the comment was not present here before, 5 seems the magic number here thus it is better to put a nice comment 🙂

Copy link
Contributor Author

@alpadev alpadev May 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what to comment here.. I tried to find out why it's 5 but I have no idea.. Considering that one frame of a 60fps animation is about 16ms - 5ms seems basically nothing.

AFAICT the idea behind this emulation code was to dispatch a transitionend event if no other transitionend event had been triggered. Likely as a fallback for legacy browsers that don't support them.

I guess the intention was to add some additional duration so the timeout will finish after the native transition event in case the browser dispatch it. That's hard to enforce tho since we're not starting any transition here (or tracking its state) but only adding some listener and a timeout that would trigger after the calculated duration no matter what.

Also getTransitionDurationFromElement only respects the duration of one (the first) CSS transition. If there are multiple transitions defined and one that takes longer (which isn't the first one) setTimeout might finish too early. (This shouldn't be the case with our defaults from what I can tell.)

In general since the timeout triggers a (custom) transitionend event and we don't match or verify them, this could lead to inconsistencies. For example the browser takes longer for the transition, setTimeout will trigger an event, then the browser triggers another event for the same transition.

On a sidenote, native transitionend events in the test environment seem to be somewhat unreliable. No idea if this is some optimization the browser is doing because it's headless or the elements are rendered offscreen (because of the fixture) or what exactly is causing this. setTimeout on the other hand works pretty reliable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/CC @Johann-S for the opinion ❤️

const durationPadding = 5
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding

let called = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag variable (called) can not be omitted? @alpadev 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although, there is no test covering the use of the called flag 🙂

Copy link
Contributor Author

@alpadev alpadev May 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about omitting this. I mean in theory we could, since the event handler unregisters itself, thus the callback is only executed once. But there would be another transitionend event dispatched by the setTimeout which could be a problem.

called is partly covered by
https://github.com/twbs/bootstrap/blob/fd016ac7ba9900f2275163d86c0d554d6a0d9b5a/js/tests/unit/util/index.spec.js#L665 because setTimeout wouldn't trigger an event if called is true.

I added another test that I hope will satisfy your objection. (I can't really verify the state of called since it's scoped to the function.)
https://github.com/twbs/bootstrap/blob/0c1d8fd9849be89f6f933b6b0017dc8f435c31c3/js/tests/unit/util/index.spec.js#L703

@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from fd016ac to 0c1d8fd Compare May 26, 2021 02:33
@alpadev alpadev moved this from Approved to Review in v5.0.2 May 28, 2021
@GeoSot
Copy link
Member

GeoSot commented Jun 2, 2021

@alpadev @rohit2sharma95
this pr is being hold for much time. Do you want to proceed with this as it fixes many things and open an issue, for the questions that accrue from past implementation?

…elements

fix: emulateTransitionEnd should properly handle events from nested elements

fix: BaseComponent._queueCallback should not execute callback if event from nested elements

refactor: use _queueCallback for static modal animation

refactor: reuse _queueCallback from BaseComponent for backdrop animations

feature: add executeAfterTransition utility function

test: add spec for excuteAfterTransition function

refactor: use executeAfterTransition in base-component and backdrop

test: add test if static modal backdrop is clicked multiple times

fix: callbacks are queued multiple times when static modal backdrop is clicked more than once

test: added another test and updated timing/wording on executeAfterTransition tests

test: ensure the functionality of triggerTransitionEnd

refactor: merge emulateTransitionEnd with executeAfterTransition

test: remove emulateTransitionEnd tests

test: add another test for executeAfterTransition

This is to assure that setTimeout wouldn't trigger another transitionend event if one had already happened
@alpadev alpadev force-pushed the fix-transitionend-event-handling branch from 2cf6c6f to 4f12061 Compare June 2, 2021 09:46
@rohit2sharma95
Copy link
Collaborator

True @GeoSot, everything else LGTM 👍

v5.0.2 automation moved this from Review to Approved Jun 2, 2021
@GeoSot GeoSot merged commit 4a5029e into twbs:main Jun 3, 2021
v5.0.2 automation moved this from Approved to Done Jun 3, 2021
@alpadev alpadev deleted the fix-transitionend-event-handling branch June 3, 2021 22:02
marvin-hinkley-vortx pushed a commit to Vortx-Inc/bootstrap that referenced this pull request Aug 18, 2021
…bs#33845)

Fix handling of transitionend events dispatched by nested elements
Properly handle events from nested elements

Change `emulateTransitionEnd` to `executeAfterTransition` &&
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment