Feature detection for transtionend/animationend event?
Asked Answered
A

4

6

I'm looking for a cleaner way to feature detect the actual name of the transitionend. I've seen a lot of examples just brute force adding handlers to all the variations. Also, I don't want to have to rely on jQuery (or similar framework).

I'm basically starting with this list and hoping to just bind the best fit (i.e., first in list to match).

var transitionendName,
    events = [
        'transitionend',
        'webkitTransitionEnd',
        'MozTransitionEnd',
        'oTransitionEnd'
    ];

// ^^^^^ your code here

myElem.addEventListener(transitionendName, myHandler, false);

Anyone feel they have a clean solution to this? The same solution presumably will work for animationend events.

Edit: msTransitionEnd and '-ms-' prefixed properties were removed in one of the final IE10 release candidates.

Airglow answered 10/10, 2012 at 0:4 Comment(0)
A
0

Using @jfriend00 's answer/example it becomes easier to create a lighter weight detection.

// cssPrefix is any method which detects the property name
var transition = cssPrefix('transition');

var transitionend = {
    'transition': 'transitionend',
    'webkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd'
}[transition];

See it in action: http://jsfiddle.net/mckamey/qWPTg/

Airglow answered 10/10, 2012 at 2:1 Comment(6)
This does not actually do a feature test on the transistionend event which is what I thought the OP was asking for. This looks for a style property and then assumes that a particular transition end event name goes with that style name.Clad
This feature detects the style property (which can be efficiently performed) and uses the corresponding transitionend event name.Airglow
Plus all of these assume they know all the vendor prefixes, so there is some a priori knowledge needed.Airglow
I just saw a similar idea in the wild: github.com/dmotz/oriDomi/blob/master/oriDomi.js#L80Airglow
Folks need to be careful with those switch statements because IE 10 is NOT using the MS prefixes for CSS3. They are using the standard names without prefix.Clad
Then that switch branch will just lie dormant. It doesn't hurt and it technically would cover the IE10 preview releases which did use those prefixes.Airglow
C
4

You can register all the event end names and then trigger a very short CSS transition and see which one fires. Also, IE10, uses transitionend, so there is no browser that uses msTransitionEnd.

Here's an example of how to do that: http://jsfiddle.net/jfriend00/5Zv9m/

var transitionendName,
    events = [
        'transitionend',
        'webkitTransitionEnd',
        'MozTransitionEnd',
        'oTransitionEnd'
    ];

function findTransitionEnd(callback) {
    // add an off-screen element
    var elem = document.createElement("div");
    elem.id = "featureTester";
    document.body.appendChild(elem);

    // clean up temporary element when done
    function cleanup() {
        document.body.removeChild(elem);
        elem = null;
    }

    // set fallback timer in case transition doesn't trigger
    var timer = setTimeout(function() {
        if (!transitionendName) {
            cleanup();
            callback("");
        }
    }, 200);

    // register all transition end names
    for (var i = 0; i < events.length; i++) {
        (function(tname) {
            elem.addEventListener(tname, function() {
                if (!transitionendName) {
                    transitionendName = tname;
                    clearTimeout(timer);
                    cleanup();
                    callback(tname);
                }

            });
        })(events[i]);
    }


    // trigger transition
    setTimeout(function() {
        elem.className = "featureTestTransition";
    }, 1);
}
Clad answered 10/10, 2012 at 0:39 Comment(4)
I might as well just continue doing brute force for the first time through and then just make a note of which one returned for future iterations. Explicitly triggering just to feature detect feels dirty.Airglow
@McKAMEY - I'm not sure why this feels dirty to you. Feature detection is all about setting up a situation and programatically checking how the browser responds. That's all this is doing here.Clad
Yes but it is heavy and time sensitive. This type of thing really adds up after a while. When a bunch of these kinds of tests need to check features it delays the page load.Airglow
@McKAMEY - this is asynchronous so I doubt it slows down page load in any way. If you want to do feature detection on the end event name, you have to run a transition and see which event name works. If you want to just see which style properties exist and then assume you know which end event name goes with that style property, you can certainly do that, but I didn't think that's what you were asking.Clad
A
4

Another variation which qualifies for pure feature detection (rather than a purely pragmatic solution) but is more efficient:

var transitionendNames = [
    'transitionend',
    'webkitTransitionEnd',
    'MozTransitionEnd',
    'oTransitionEnd'
];

/**
 * Helper function to bind to the correct transitionend event
 * @param {function} callback The function to call when the event fires
 */
var transitionend = function(elem, callback) {
    var handler = function(e) {
        //console.log('transitionend == '+e.type);

        // test in case multiple were registered before change
        if (transitionendNames) {
            // store the actual name
            var transitionendName = e.type;

            // every other time, bind only to actual event
            transitionend = function(elem, callback) {
                elem.addEventListener(transitionendName, callback, false);
            };

            // flag for any others
            transitionendNames = null;
        }
        return callback.call(elem, e);
    };

    // until an event has been triggered bind them all
    for (var i=0, len=transitionendNames.length; i<len; i++) {
        elem.addEventListener(transitionendNames[i], handler, false);
    }
};
Airglow answered 10/10, 2012 at 16:14 Comment(8)
Wouldn't it be more efficient to just reassign the transitionend function to a new function that just uses a global you set as soon as you know which transition name it is rather than still using the array?Clad
Ahhh, much better with the local variable transitionendName, than overloading the one global variable and using typeof.Clad
I'll give you an upvote even though I have a competing answer. I've concluded that this whole question just has no interested readers and the OP isn't paying much attention either.Clad
Nope, didn't realize you were the OP. It's not very common for the OP to provide multiple answers to their own question - in fact I've never seen it done before. I assumed you were just another answerer. It does appear that you and I are the only ones spending any time on this question.Clad
Well, thanks for the help discussing possibile solutions anyway.Airglow
I answer my own questions all the time. Stack even encourages it.Hypothesis
@Clad - I also answer my questions all the time, why wouldn't I? If I know how to do something, then I ask the question in here and answer myself, so there will be an online documentation where others could learn.Edibles
Remember to remove the unused event listeners, to avoid memory leak.Salpingitis
C
3

I know this is old, but I'd just like to add: the style attribute isn't always a good way of detecting the animationend/transitionend prefix. For example, some android browsers use no prefix for transitions but webkitAnimationEnd for the JS event.

Crying answered 19/8, 2014 at 13:46 Comment(1)
I would go as far as to say that the style attribute is NEVER a good way of detecting whether or not the events are prefixed. As of today, the accepted answer is broken at least on iPad/Safari.Ssw
A
0

Using @jfriend00 's answer/example it becomes easier to create a lighter weight detection.

// cssPrefix is any method which detects the property name
var transition = cssPrefix('transition');

var transitionend = {
    'transition': 'transitionend',
    'webkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd'
}[transition];

See it in action: http://jsfiddle.net/mckamey/qWPTg/

Airglow answered 10/10, 2012 at 2:1 Comment(6)
This does not actually do a feature test on the transistionend event which is what I thought the OP was asking for. This looks for a style property and then assumes that a particular transition end event name goes with that style name.Clad
This feature detects the style property (which can be efficiently performed) and uses the corresponding transitionend event name.Airglow
Plus all of these assume they know all the vendor prefixes, so there is some a priori knowledge needed.Airglow
I just saw a similar idea in the wild: github.com/dmotz/oriDomi/blob/master/oriDomi.js#L80Airglow
Folks need to be careful with those switch statements because IE 10 is NOT using the MS prefixes for CSS3. They are using the standard names without prefix.Clad
Then that switch branch will just lie dormant. It doesn't hurt and it technically would cover the IE10 preview releases which did use those prefixes.Airglow

© 2022 - 2024 — McMap. All rights reserved.