0

I want to do a color fade, and run a function once when it is complete. I can do this with the bind, which runs a callback on transitionend. This works, but is run for each transition tied to an element.

CSS

Multiple transitions: Output: (2) called

 box-shadow: 2px 2px 5px red !important;
 transition: all 2s ease-out ;      

Single transition: Output: called

 transition: background-color 2s ease-out !important;
 background: red !important; 

jQuery:

    $("#currentBlock").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(event){ 
                log("called");
                $(this).unbind(event);
            });

I would like to apply a transition to the box-shadow, but it is calling the transitionend twice, instead of once. How do I limit the amount of time the callback is called, or cancel it if it is called again.

user3871
  • 12,432
  • 33
  • 128
  • 268
  • possible duplicate of [transitionend event fire twice](http://stackoverflow.com/questions/18689031/transitionend-event-fire-twice) – nice ass Nov 14 '14 at 21:55

2 Answers2

2

Multiple fired transitionend-events can have two reasons:

  • As Christopher White said in his answer: Some browsers supports more than one transitionend event, so all are fired, because you bind them all. ---> Let jQuery do the check for unprefixed or prefixed versions and bind only the result jQuery returns.
  • For each transitioned property one transitionend-event is fired. So transitioning box-shadow and background results in two events. ---> Find inside the event-object the name of the property that caused the event. Then you can decide with if-statements what to do.

$('body').css('transition'); // this initializes the check for vendor-prefixed transitions
console.log($.cssProps.transition); // in jQuery.cssProps you find the result
$("#currentBlock").bind($.cssProps.transition + 'end', function(evt) {
    // jQuery wraps the original event in an own object so we retrieve it from there
    var prop = evt.originalEvent.propertyName; // in the original you find the property
    console.log(prop);
    // now you can for a specific transitionend decide what shall happen
    if (prop == 'box-shadow') { // note the properties are dashed here
        console.log('boxShadow has finished.');
    }
    // if you want to unbind the handler argument is the event-name, not the event-object
    $(this).unbind($.cssProps.transition + 'end');
});

BTW: If you have a newer version of jQuery use .on() / .off() instead of .bind() / unbind().

Martin Ernst
  • 3,199
  • 1
  • 12
  • 12
1

You are binding to manufacturer specific events as well as the standard event. Some browsers support more than one of these. Each supported event is getting bound and called when the transition ends. You should test to see which events are supported before binding and just bind to one of them.