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

Timing issue with transitionend event, preventing Modal overlay from being closed. #192

Closed
jcbrand opened this issue Feb 23, 2018 · 17 comments
Assignees
Labels
bug critical issue

Comments

@jcbrand
Copy link

jcbrand commented Feb 23, 2018

Hi there

Thanks for a great lib.

I'm running into a timing issue when I close modals. Sometimes (every 3rd or 4th attempt), the event listener which is registered for transitionend doesn't get called, which means that the Modal overlay doesn't get removed, making the page unusable.

In my CSS I increased the transition time for .fade from 0.15s to 0.2s and that seems to solve the problem (also confirming that it's a timing issue).

I'd suggest you add some kind of timeout so that if the transitionend event never fires, that the Modal overlay still gets removed.

I'm using version 2.0.21 and Chromium 63.0.3239.132 (Developer Build)

@jcbrand jcbrand changed the title Timing issue with transitionend event, preventing Modal overlay Timing issue with transitionend event, preventing Modal overlay from being closed. Feb 23, 2018
jcbrand added a commit to conversejs/converse.js that referenced this issue Feb 23, 2018
jcbrand added a commit to conversejs/converse.js that referenced this issue Feb 23, 2018
@Vuurvlieg
Copy link

Same problem for me. Thanks for your commit, it should be marged into the official project.

@thednp
Copy link
Owner

thednp commented Feb 25, 2018

I remember this has been discussed before, I will think of a way to work around this issue.

@sect2k
Copy link

sect2k commented Mar 28, 2018

This seems to have been discussed in #184 before.

Looking at the code the issue seems to be the timeout. Pardon my ignorance, but why is it there in the first place? Since dialog is only shown/hidden when the transition completes, it seems redundant.

@thednp
Copy link
Owner

thednp commented Mar 29, 2018

I cannot reproduce the issue even with the latest Bootstrap 4.0.0 CSS, can you guys create a pen or something?

@sect2k
Copy link

sect2k commented Mar 29, 2018

@thednp it's hard to reproduce, but it should be easy to simulate by decreasing transition time in CSS, for overlay and modal itself.

But the underlying issues is apparent even by just observing the code, if transition finishes before event handler for `transtiononend' is added, then it will never be run.

Why it works in most cases are transitions that happen on the dialog itself and not the overlay, on which gets the handler attached.

To handle this properly, you should drop setTimeout all together and just rely on the transitiononend event. The catch here is that it will fire of for any transition on the element and child elements, so you need to check in the handler itself if target element is indeed the overlay and it also helps to only fire it on the transition that takes the longest time.

let animationEndHandler = function(e) {
    if (e.target.matches(this.formSelector) && e.propertyName == 'opacity') {
        e.target.removeEventListener(e.type, animationEndHandler)
        //show|hide code here
    }
}

Example of event handler, this is from a project I've been working on recently, where I had to deal with handling code with transtiononend.

@sect2k
Copy link

sect2k commented Mar 29, 2018

https://codepen.io/anon/pen/jzZZqo

This should illustrate the issue, I've adjusted the timings on transitions, so they finish before event handler gets attached, and as you can see, the overlay never disappears.

@thednp
Copy link
Owner

thednp commented Mar 29, 2018

@sect2k it's true the setTimeout is not the cleanest/best solution, but there is something to be done, a short delay of at least one millisecond after display:block/none is set in order for the animation to work and eventually trigger transitionend.

There was a setImmediate tool for that but only for select browsers, so I can only use self executable anonymous function for that, now testing and seems to be working properly, at least with Chrome. It even works with 0.05 second animation duration no problem.

@sect2k
Copy link

sect2k commented Mar 29, 2018

If 1 millisecond is all that is needed, maybe lower the timeout from 150ms to something lower, which should eliminate this issue and is indeed the simplest solution to this problem.

Another possibility could be requestAnimationFrame.

if (hasClass(modal,'fade')) {
    requestAnimationFrame(function() {
        removeClass(modal,showClass);
        modal[setAttribute](ariaHidden, true);
    })

    emulateTransitionEnd(modal, triggerHide)    
} else {
    removeClass(modal,showClass);
    modal[setAttribute](ariaHidden, true);
    triggerHide():
}

@thednp
Copy link
Owner

thednp commented Mar 29, 2018

That solution is too sexy for this issue, however we're not interested in max performance or max accuracy, we're focused on browser consistency.

I'm gonna close this issue right here, please be sure to check back later for my commits comin in about 30 min or so.

@thednp thednp closed this as completed Mar 29, 2018
@thednp thednp self-assigned this Mar 29, 2018
@thednp thednp added the bug critical issue label Mar 29, 2018
thednp added a commit that referenced this issue Mar 29, 2018
* Fixing Modal `transitionend` issue #192
* Fixing Tooltip/Popover position #182
* Code cleanup
* V4 page updates
thednp added a commit that referenced this issue Mar 29, 2018
* Fixing Modal `transitionend` issue #192
* Fixing Tooltip/Popover position #182
* Code cleanup
* V4 page updates
@thednp
Copy link
Owner

thednp commented Mar 30, 2018

@sect2k @Vuurvlieg @jcbrand all good with the latest master version? Are we ready for a new release tag?

@sect2k
Copy link

sect2k commented Mar 30, 2018

@thednp my codepen above no longer exhibits the issue, so I'd say it's all good.

@jcbrand
Copy link
Author

jcbrand commented Mar 30, 2018

@thednp I'm not able to test this soon (I'm taking a 2 week break starting Monday). I trust you guys got down to the bottom of this, looks like it. Thanks!

@Vuurvlieg
Copy link

Vuurvlieg commented Mar 30, 2018

Thanks @thednp for the updates!

After testing the latest "bootstrap-native-v4.js" from the "dist" folder of the latest master, so far the modal transition issue doesn't showed up. However, the bug from #169 is there again: When initializing an Carousel with interval set to false or 0, it stills autoplay the slides. Check https://codepen.io/anon/pen/OvvErr

@thednp
Copy link
Owner

thednp commented Apr 2, 2018

@Vuurvlieg I cannot replicate the issue with Carousel, with data-interval="false" or interval = false JavaScript initialization. Perhaps you are using some outdated version.

@Vuurvlieg
Copy link

@thednp Well, if you check the codepen in my previous post you will see that Im using the latest version. Also data-interval="false" is working while interval = false via JS is not.

@thednp
Copy link
Owner

thednp commented Apr 4, 2018

@Vuurvlieg you are right, I tested and seem to be an issue with manual JavaScript initialization, so we'll get this fixed with the next update.

Thanks for sticking to it.

thednp added a commit that referenced this issue Apr 4, 2018
* fixing minor bug with **Carousel** #192 (comment)
* bump version
thednp added a commit that referenced this issue Apr 4, 2018
* fixing minor bug with **Carousel** #192 (comment)
* bump version
@Vuurvlieg
Copy link

Sure, no problem, and thanks for creating and maintaining this amazing project!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug critical issue
Projects
None yet
Development

No branches or pull requests

4 participants