一个总是触发的"过渡事件"事件,只有一次

nic*_*ass 18 javascript jquery javascript-events css-transitions

我需要一个特殊transitionend的事件,在所有转换完成后触发一次,或者如果CSS中没有定义转换则立即触发.

这就是我到目前为止所得到的:

(function($){

  $.event.special.transitionsComplete = {

    setup: function(data, namespaces, eventHandle){    
      var queue = [],
          style = window.getComputedStyle(this, null),
          computedProps = style.getPropertyValue('transition-property').split(', '),
          computedDurations = style.getPropertyValue('transition-duration').split(', '),
          $node = $(this);          

      // only count properties with duration higher than 0s
      for(var i = 0; i < computedDurations.length; i++)
        if(computedDurations[i] !== '0s')
          queue.push(computedProps[i]);           

      // there are transitions
      if(queue.length > 0){
        $node.on('webkitTransitionEnd.x transitionend.x', function(e){          
          queue.splice(queue.indexOf(e.originalEvent.propertyName));          
          if(queue.length < 1)
            $node.trigger('transitionsComplete');
        });

      // no transitions, fire (almost) immediately
      }else{
        setTimeout(function(){
          $node.trigger('transitionsComplete');
        }, 5);

      }

    },

    teardown: function(namespaces){
      $(this).off('.x');
    }

  };
})(jQuery);
Run Code Online (Sandbox Code Playgroud)

我在这里做了一个实例.

唯一的问题是它只有在元素本身具有过渡属性时才有效,忽略了来自子元素的过渡.如果切换transitionsCompletetransitionend父事件和子事件处理程序,则在子转换完成后运行.是否有某种方式,或者更好的方法来确定一个元素是否发生过它或它的孩子的转变?如果可能的话,我想避免手动通过孩子并检查他们的过渡属性.(无论如何这都不可靠,因为即使有些孩子有过渡,也不意味着他们会在那时活跃)

Eri*_*icG 3

所以在这里,我确实检查了孩子们:http://jsfiddle.net/cegejk59/2/

(function($){

  $.event.special.transitionsComplete = {

    setup: function( data, namespaces, eventHandle ) {

        var allTransitions          = [];
            w                       = window,
            TRANSITION_PROPERTY_KEY = 'transition-property',
            TRANSITION_DURATION_KEY = 'transition-duration',
            $node                   = $( this );

        function collectTransitionsRecursively( node ) {

            var style                   = w.getComputedStyle( node ),
                nodeComputedProperties  = style.getPropertyValue( TRANSITION_PROPERTY_KEY ).split( ', ' ),
                nodeComputedDurations   = style.getPropertyValue( TRANSITION_DURATION_KEY ).split( ', ' );

            for( var i = 0; i < nodeComputedDurations.length; i++ )
                if( nodeComputedDurations[ i ] !== '0s' )
                    allTransitions.push( nodeComputedProperties[ i ] );

            for( var childIndex = 0; childIndex < node.children.length; childIndex++ )
                collectTransitionsRecursively( node.children[ childIndex ] );
        }

        function triggerTransitionsComplete( $onNode ) {

            console.log( "No transitions (left)." );

            $onNode.trigger('transitionsComplete');
        }

        function onNoTransitionsFound() {

            setTimeout( function() {

                triggerTransitionsComplete( $node );
            });
        }

        collectTransitionsRecursively( this );

        if( allTransitions.length == 0 )
            return onNoTransitionsFound();
        else
            console.log( 'remaining', allTransitions );    

        $node.on('webkitTransitionEnd.x transitionend.x', function( e ){ 

            allTransitions.splice(allTransitions.indexOf(e.originalEvent.propertyName));

            if( allTransitions.length == 0 )
                triggerTransitionsComplete( $node );
            else
                console.log('remaining', allTransitions);
        });
    },

    teardown: function( namespaces ) {

      $( this ).off( '.x' );
    }
  };
})(jQuery);


var div = $('div'), p = $('p'), start = new Date().getTime();
console.log('-- start --');
div.addClass('visible');

div.one('transitionsComplete', function(e){
    console.log('complete-div', (new Date().getTime() - start) / 1000);
});

//p.one('transitionsComplete', function(e){
//    console.log('complete-p', (new Date().getTime() - start) / 1000);
//});
Run Code Online (Sandbox Code Playgroud)