Question

Have anybody out there found a simple way of detecting whether the browser supports the transitionend event or not in vanillaJs, especially in a way that actually works in all major browsers? :(

I have found this unanswered thread in here: Test for transitionend event support in Firefox, and quite a lot of almost working hacks.

Right now I am bulk adding eventlisteners to all the vendor prefixes, and it kind of works out (even though I think it is a hideous approach that hurts my eyes every time I look at it). But IE8 and IE9 does not support it at all, so I need to detect those two, and treat them separately.

I would prefer to do this without browser sniffing, and definitely without huge libraries/frameworks like jQuery

I have made a jsfiddler snippet that illustrates my problem. There is a button that spawns a dialog. When the dialog is removed by clicking close, it is transitioned in top and opacity, and after ended transition it is supposed to display=none. But if the transitionend is never fired (like in IE8 and IE9), the dialog is never removed, making it cover the show dialog button, destroying the UX. If I could detect when transitionend is not working, I could just set the display=none when closing for those browsers.

http://jsfiddle.net/QJwzF/22/

window.listenersSet = false;
window.dialogShouldBeVisible = false;

window.showMyDialog = function () {
    var myDialog = document.getElementById('dialog'),
        myClose = document.getElementById('close');
    if (!listenersSet) {
        if (!window.addEventListener) { // IE8 has no addEventListener
            myclose.attachEvent('onclick', function () {
                hideMyDialog();
            });
        } else {
            myClose.addEventListener('click', function () {
                hideMyDialog()
            });

            ['webkitTransitionEnd','oTransitionEnd', 'otransitionend', 'transitionend'].forEach(function (eventName) {
                myDialog.addEventListener(eventName, function (e) {
                    if (e.target === myDialog && e.propertyName === 'top') { // only do trigger if it is the top transition of the modalDialog that has ended
                        if (!dialogShouldBeVisible) {
                            myDialog.style.display = 'none';
                            e.stopPropagation();
                        }
                    }
                });
            });
        }
        listenersSet = true;
    }

    myDialog.style.display = 'block';
    myDialog.style.top = '15px';
    myDialog.style.opacity = '1';
    dialogShouldBeVisible = true;
}

window.hideMyDialog = function () {
    var myDialog = document.getElementById('dialog'),
        myClose = document.getElementById('close');
    myDialog.style.top = '-5%';
    myDialog.style.opacity = '0.1';
    dialogShouldBeVisible = false;
}

It is working in Opera, Firefox, Chrome and IE10, but not in IE8 and IE9 (afaik)

If I did a bad job explaining my problem, please let me know, and I will try do a better job! :)

Was it helpful?

Solution 2

I would definitely use this small script available on Github. It's listed among Modernizr "Cross-browser polyfills" page so it can be trusted but Modernizr itself is not required.

The examples in the Github page of the script are written using jQuery (and I can't understand why) but jQuery is also not required as it's written in vanilla js.

Like so you'll have a useful whichTransitionEnd method available. I can't test it right now being on my laptop without IE8/IE9 available but I guess that this method will return false (or anything falsy) in those browsers.

var transition = transitionEnd(box).whichTransitionEnd(); 
// return for example "webkitTransitionEnd"

It will then be quite easy to target those browsers where transitions (and thus transitionend events) are not supported. Hope this will be a nudge in the right direction.

EDIT

After tweaking with the above code the OP came up with a much shorter version of the original script. It saves a good deal of bytes and only detects support for this event, and, in case it's supported returns the name of the event itself.

You can find it here as a gist and read more about it in the comments to this answer.

OTHER TIPS

Copied from bootstrap transition, it not only returns true if browser supports transition but also returns proper name of event

  function transitionEnd() {
    var el = document.createElement('div')//what the hack is bootstrap

    var transEndEventNames = {
      WebkitTransition : 'webkitTransitionEnd',
      MozTransition    : 'transitionend',
      OTransition      : 'oTransitionEnd otransitionend',
      transition       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return transEndEventNames[name];
      }
    }

    return false // explicit for ie8 (  ._.)
  }

Hope this helps.

EIDT: I modified a little bit default bootstrap function so it doesn't return object but string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top