Detecting CSS transition completion
by Vince Aggrippino
April 26, 2013
HTML
<p>Based on code from <a href="http://blog.alexmaccaw.com/css-transitions">http://blog.alexmaccaw.com/css-transitions</a> and <a href="http://stackoverflow.com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers">http://stackoverflow.com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers</a>
</p>
<div class="element"></div>
<div class="status"></div>
SCSS
body {
margin: 20px;
}
.element {
width: 100px;
height: 100px;
background: black;
}
div.status {
border: 1px solid black;
width: 10em;
padding: 3px;
margin: 10px auto;
text-align: center;
background: black;
color: white;
}
div.status:before {
content: "Not Started";
display: block;
}
div.status.started {
background: red;
}
div.status.started:before {
content: "Started";
}
div.status.complete {
background: green;
}
div.status.complete:before {
content: "Complete";
}
JavaScript
var defaults = {
duration: 400,
easing: ''
};
var whichTransitionEvent = function(){
var t;
var el = document.createElement('fakeelement');
var transitions = {
'transition':'transitionend',
'OTransition':'oTransitionEnd',
'MozTransition':'transitionend',
'WebkitTransition':'webkitTransitionEnd'
};
for(t in transitions){
if( el.style[t] !== undefined ){
return transitions[t];
}
}
};
var transition_event = whichTransitionEvent();
$.fn.emulateTransitionEnd = function (duration) {
var called = false,
$el = this;
$(this).one(transition_event, function () {
called = true;
});
var callback = function () {
if (!called) {
$($el).trigger(transition_event);
}
};
// Sometimes the event doesn't fire?
setTimeout(callback, duration);
};
$.fn.transition = function (properties, options) {
options = $.extend({}, defaults, options);
properties.transition = 'all ' + options.duration + 'ms ' + options.easing;
$(this).one(transition_event, options.complete || $.noop);
$("div.status").toggleClass("started");
$(this).css(properties);
$(this).emulateTransitionEnd(options.duration);
};
setTimeout(function () {
var callback = function () {
$("div.status").toggleClass("complete");
};
$('.element').transition({
'margin-left': 100,
'background': 'green'
}, {
complete: callback,
duration: 2000
});
}, 2000);