transitionEnd
event is fired on the transition which ends first and not last, which is not the desired behavior. Any workarounds?
document.querySelector('a').addEventListener('transitionend', function(){
var time = (new Date().getMinutes()) + ':' + (new Date().getSeconds());
console.log('transitionEnd - ', time);
});
a{
display:block;
opacity:.5;
width:100px;
height:50px;
background:lightblue;
}
a:hover{
width:200px;
height:100px;
background:red;
transition: 4s width, /* <-- "transitionEnd" should fire after this */
2s height,
.5s background;
}
<a>Hover me</a>
Now that I check on Chrome (I do not use that browser), I see that the event gets called 3 times, one per transition. Anyway, I need it to fire for the last one, and in Firefox. (I can't know how many transitions were on the element anyway, to know which was the last)
transitionEnd
returns a property called propertyName
in the event object.
Source
Therefore you can test for the property you want and use simple logic to filter the callbacks:
document.querySelector('a').addEventListener('transitionend', function(event){
if(event.propertyName !== 'width') return;
console.log('transitionEnd - width!');
});
A bit of a hacky solution might be to try to find out which css property has the longest total duration. You can do so by using window.getComputedStyle
on your <a>
element and adding up all duration
and delay
properties.
You could do this in the regular event handler that is fired three times (it's pretty quick), or make a function that pre-computes the property name you're looking for.
Main problems with this approach:
ms
and s
in one statement, you might need to do some more computing.transition
style on hover, or when adding new classes just before/after a transition.var getValues = function(str) {
return str
.replace(/[A-Z]/gi, "")
.split(", ")
.map(parseFloat);
};
var getMaxTransitionProp = function(el) {
var style = window.getComputedStyle(el);
var props = style.transitionProperty.split(", ");
var delays = getValues(style.transitionDelay);
var durations = getValues(style.transitionDuration);
var totals = durations.map(function(v, i) {
return v + delays[i];
});
var maxIndex = totals.reduce(function(res, cur, i) {
if (res.val > cur) {
res.val = cur;
res.i = i;
}
return res;
}, {
val: -Infinity,
i: 0
}).i;
return props[maxIndex];
}
var lastEventListenerFor = function(el, cb) {
var lastProp = getMaxTransitionProp(el);
return function(e) {
if (e.propertyName == lastProp) {
cb(e);
}
};
}
var a = document.querySelector("a");
var cb = function(e) {
console.log("End");
};
a.addEventListener("transitionend", lastEventListenerFor(a, cb));
a {
display: block;
opacity: .5;
width: 100px;
height: 50px;
background: lightblue;
transition: 3s width,
/* <-- "transitionEnd" should fire after this */
2s height, .5s background;
}
a:hover {
width: 200px;
height: 100px;
background: red;
}
<a>Hover me</a>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With