Last active
March 22, 2017 20:33
-
-
Save leereamsnyder/9942868 to your computer and use it in GitHub Desktop.
Quick jQuery plugin to fire the correct browser-prefixed 'transitionend' event with a callback
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************************** | |
Little utility function for handling single transitionEnd events. | |
Particularly handy for when you need to remove something from | |
the DOM after transforming it with an animation | |
WHY NOT $el.one('transitionend', callback) ???? | |
============================================= | |
+ "transitionend" is the standardized name, but in some browsers | |
it may be prefixed or camel-cased. This normalizes that. | |
+ Browsers that don't do transitions will never fire a transitionend event | |
on their own. This makes sure the callback fires. | |
+ Sometimes a browser will just *not* fire the transitionend event to drive you nuts | |
This makes sure it happens. (This is why you need the duration) | |
USAGE | |
================== | |
$el.onTransitionEnd( duration, callback ); | |
(OR $el.transitionend( duration, callback ) ) | |
After any transition on the element finishes, callback will call once. | |
Uses .one(), so callback won't be called again. | |
Currently limited to a single element | |
I'm looking into supporting collections | |
OPTIONS | |
================== | |
duration [required] INT | |
- How long in milliseconds before firing the callback | |
- To avoid duplication with your CSS, you might try to get it like this: | |
$el.css('transition-duration') | |
.split(',') // in case of multiple transitions | |
.shift() // get the first | |
.replace('s','') // replace "s" (".5s" -> ".5") | |
.trim()*1000 // trim and convert to ms (".5" -> 500) | |
- I add 50ms to this before triggering the 'backup' event | |
in case the browser misses it. It happens! | |
- For browsers that don't do transitions, I trigger the event | |
a few ticks (10ms) later. | |
callback [optional ... but why not?] FUNCTION | |
- the function to execute after the transition finishes | |
- attached with $.one(), so it won't fire after another transition | |
- the callback is called with the jQuery event object, and "this" is the element (as expected) | |
EXAMPLE | |
==================== | |
$el = $(this); | |
$el.onTransitionEnd( 250, function( event ){ | |
$(this).css('display','none'); | |
}); | |
$el.addClass('fadeOut'); // (or whatever would trigger a transition) | |
SHOUTOUTS | |
==================== | |
http://www.modernizr.com/ | |
http://blog.alexmaccaw.com/css-transitions | |
https://github.com/twbs/bootstrap/blob/master/js/transition.js | |
*************************/ | |
(function(window, $, undefined){ | |
'use strict'; | |
// Checking for CSS transition support | |
var transitionSupport = false, | |
transitionEnd = 'fakeTransitionEnd', // this is the fake event name we'll use if there's no transition support | |
el = document.createElement('div'), | |
transEndEventNames = { | |
'WebkitTransition' : 'webkitTransitionEnd', | |
'MozTransition' : 'transitionend', | |
'OTransition' : 'oTransitionEnd otransitionend', // Opera used both at one point! | |
'transition' : 'transitionend' | |
// Microsoft never supported prefixed transitions. IE10 is not prefixed | |
}; | |
// Loop through the event names and see if one works. | |
// If so, update transitionSupport to TRUE and update the transitionEnd event name | |
for (var name in transEndEventNames) { | |
if (el.style[name] !== undefined) { | |
transitionSupport = true; | |
transitionEnd = transEndEventNames[name]; | |
} | |
} | |
$.fn.onTransitionEnd = function( duration, callback ) { | |
var called = false, $el = $(this); | |
$el.one( transitionEnd, function(evt) { | |
called = true; | |
if (callback && $.isFunction(callback) ) { | |
// I'm reasonably sure because we're in an event callback, | |
// "this" for the callback will be the element (as expected in jQuery world) | |
// Shouldn't hurt to be explicit though (famous last words) | |
callback.call(this, evt); | |
} | |
}); | |
var timeout = function() { | |
// If we haven't done the callback already, do so now | |
if ( ! called ) { | |
$el.trigger( transitionEnd ); | |
} | |
}; | |
// add a little time to the duration | |
// if there's no transition support, fire it ASAP | |
duration = transitionSupport ? duration + 50 : 10; | |
setTimeout(timeout, duration); | |
return this; | |
}; | |
// sugar if you think more like $el.click() | |
$.fn.transitionend = $.fn.onTransitionEnd; | |
})(window, jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment