text: /**
   * This animation class is a mixin.
   *
   * Ext.util.Animate provides an API for the creation of animated transitions of properties and styles.
   * This class is used as a mixin and currently applied to {@link Ext.dom.Element}, {@link Ext.CompositeElement},
   * {@link Ext.draw.sprite.Sprite}, {@link Ext.draw.sprite.Composite}, and {@link Ext.Component}.  Note that Components
   * have a limited subset of what attributes can be animated such as top, left, x, y, height, width, and
   * opacity (color, paddings, and margins can not be animated).
   *
   * ## Animation Basics
   *
   * All animations require three things - `easing`, `duration`, and `to` (the final end value for each property)
   * you wish to animate. Easing and duration are defaulted values specified below.
   * Easing describes how the intermediate values used during a transition will be calculated.
   * {@link Ext.fx.Anim#easing Easing} allows for a transition to change speed over its duration.
   * You may use the defaults for easing and duration, but you must always set a
   * {@link Ext.fx.Anim#to to} property which is the end value for all animations.
   *
   * Popular element 'to' configurations are:
   *
   *  - opacity
   *  - x
   *  - y
   *  - color
   *  - height
   *  - width
   *
   * Popular sprite 'to' configurations are:
   *
   *  - translation
   *  - path
   *  - scale
   *  - stroke
   *  - rotation
   *
   * The default duration for animations is 250 (which is a 1/4 of a second).  Duration is denoted in
   * milliseconds.  Therefore 1 second is 1000, 1 minute would be 60000, and so on. The default easing curve
   * used for all animations is 'ease'.  Popular easing functions are included and can be found in {@link Ext.fx.Anim#easing Easing}.
   *
   * For example, a simple animation to fade out an element with a default easing and duration:
   *
   *     var p1 = Ext.get('myElementId');
   *
   *     p1.animate({
   *         to: {
   *             opacity: 0
   *         }
   *     });
   *
   * To make this animation fade out in a tenth of a second:
   *
   *     var p1 = Ext.get('myElementId');
   *
   *     p1.animate({
   *        duration: 100,
   *         to: {
   *             opacity: 0
   *         }
   *     });
   *
   * ## Animation Queues
   *
   * By default all animations are added to a queue which allows for animation via a chain-style API.
   * For example, the following code will queue 4 animations which occur sequentially (one right after the other):
   *
   *     p1.animate({
   *         to: {
   *             x: 500
   *         }
   *     }).animate({
   *         to: {
   *             y: 150
   *         }
   *     }).animate({
   *         to: {
   *             backgroundColor: '#f00'  //red
   *         }
   *     }).animate({
   *         to: {
   *             opacity: 0
   *         }
   *     });
   *
   * You can change this behavior by calling the {@link Ext.util.Animate#syncFx syncFx} method and all
   * subsequent animations for the specified target will be run concurrently (at the same time).
   *
   *     p1.syncFx();  //this will make all animations run at the same time
   *
   *     p1.animate({
   *         to: {
   *             x: 500
   *         }
   *     }).animate({
   *         to: {
   *             y: 150
   *         }
   *     }).animate({
   *         to: {
   *             backgroundColor: '#f00'  //red
   *         }
   *     }).animate({
   *         to: {
   *             opacity: 0
   *         }
   *     });
   *
   * This works the same as:
   *
   *     p1.animate({
   *         to: {
   *             x: 500,
   *             y: 150,
   *             backgroundColor: '#f00'  //red
   *             opacity: 0
   *         }
   *     });
   *
   * The {@link Ext.util.Animate#stopAnimation stopAnimation} method can be used to stop any
   * currently running animations and clear any queued animations.
   *
   * ## Animation Keyframes
   *
   * You can also set up complex animations with {@link Ext.fx.Anim#keyframes keyframes} which follow the
   * CSS3 Animation configuration pattern. Note rotation, translation, and scaling can only be done for sprites.
   * The previous example can be written with the following syntax:
   *
   *     p1.animate({
   *         duration: 1000,  //one second total
   *         keyframes: {
   *             25: {     //from 0 to 250ms (25%)
   *                 x: 0
   *             },
   *             50: {   //from 250ms to 500ms (50%)
   *                 y: 0
   *             },
   *             75: {  //from 500ms to 750ms (75%)
   *                 backgroundColor: '#f00'  //red
   *             },
   *             100: {  //from 750ms to 1sec
   *                 opacity: 0
   *             }
   *         }
   *     });
   *
   * ## Animation Events
   *
   * Each animation you create has events for {@link Ext.fx.Anim#beforeanimate beforeanimate},
   * {@link Ext.fx.Anim#afteranimate afteranimate}, and {@link Ext.fx.Anim#lastframe lastframe}.
   * Keyframed animations adds an additional {@link Ext.fx.Animator#keyframe keyframe} event which
   * fires for each keyframe in your animation.
   *
   * All animations support the {@link Ext.util.Observable#listeners listeners} configuration to attact functions to these events.
   *
   *     startAnimate: function() {
   *         var p1 = Ext.get('myElementId');
   *         p1.animate({
   *            duration: 100,
   *             to: {
   *                 opacity: 0
   *             },
   *             listeners: {
   *                 beforeanimate:  function() {
   *                     // Execute my custom method before the animation
   *                     this.myBeforeAnimateFn();
   *                 },
   *                 afteranimate: function() {
   *                     // Execute my custom method after the animation
   *                     this.myAfterAnimateFn();
   *                 },
   *                 scope: this
   *         });
   *     },
   *     myBeforeAnimateFn: function() {
   *       // My custom logic
   *     },
   *     myAfterAnimateFn: function() {
   *       // My custom logic
   *     }
   *
   * Due to the fact that animations run asynchronously, you can determine if an animation is currently
   * running on any target by using the {@link Ext.util.Animate#getActiveAnimation getActiveAnimation}
   * method.  This method will return false if there are no active animations or return the currently
   * running {@link Ext.fx.Anim} instance.
   *
   * In this example, we're going to wait for the current animation to finish, then stop any other
   * queued animations before we fade our element's opacity to 0:
   *
   *     var curAnim = p1.getActiveAnimation();
   *     if (curAnim) {
   *         curAnim.on('afteranimate', function() {
   *             p1.stopAnimation();
   *             p1.animate({
   *                 to: {
   *                     opacity: 0
   *                 }
   *             });
   *         });
   *     }
   */
  Ext.define('Ext.util.Animate', {
      mixinId: 'animate',
  
      requires: [
          'Ext.fx.Manager',
          'Ext.fx.Anim'
      ],
  
      isAnimate: true,
  
      /**
       * Performs custom animation on this object.
       *
       * This method is applicable to both the {@link Ext.Component Component} class and the {@link Ext.draw.sprite.Sprite Sprite}
       * class. It performs animated transitions of certain properties of this object over a specified timeline.
       *
       * ### Animating a {@link Ext.Component Component}
       *
       * When animating a Component, the following properties may be specified in `from`, `to`, and `keyframe` objects:
       *
       *   - `x` - The Component's page X position in pixels.
       *
       *   - `y` - The Component's page Y position in pixels
       *
       *   - `left` - The Component's `left` value in pixels.
       *
       *   - `top` - The Component's `top` value in pixels.
       *
       *   - `width` - The Component's `width` value in pixels.
       *
       *   - `height` - The Component's `height` value in pixels.
       *
       * The following property may be set on the animation config root:
       *
       *   - `dynamic` - Specify as true to update the Component's layout (if it is a Container) at every frame of the animation.
       *     *Use sparingly as laying out on every intermediate size change is an expensive operation.*
       *
       * For example, to animate a Window to a new size, ensuring that its internal layout and any shadow is correct:
       *
       *     myWindow = Ext.create('Ext.window.Window', {
       *         title: 'Test Component animation',
       *         width: 500,
       *         height: 300,
       *         layout: {
       *             type: 'hbox',
       *             align: 'stretch'
       *         },
       *         items: [{
       *             title: 'Left: 33%',
       *             margin: '5 0 5 5',
       *             flex: 1
       *         }, {
       *             title: 'Left: 66%',
       *             margin: '5 5 5 5',
       *             flex: 2
       *         }]
       *     });
       *     myWindow.show();
       *     myWindow.header.el.on('click', function() {
       *         myWindow.animate({
       *             to: {
       *                 width: (myWindow.getWidth() == 500) ? 700 : 500,
       *                 height: (myWindow.getHeight() == 300) ? 400 : 300
       *             }
       *         });
       *     });
       *
       * For performance reasons, by default, the internal layout is only updated when the Window reaches its final `"to"`
       * size. If dynamic updating of the Window's child Components is required, then configure the animation with
       * `dynamic: true` and the two child items will maintain their proportions during the animation.
       *
       * @param {Object} config  Configuration for {@link Ext.fx.Anim}.
       * Note that the {@link Ext.fx.Anim#to to} config is required.
       * @return {Object} this
       */
      animate: function(animObj) {
          var me = this;
          if (Ext.fx.Manager.hasFxBlock(me.id)) {
              return me;
          }
          Ext.fx.Manager.queueFx(new Ext.fx.Anim(me.anim(animObj)));
          return this;
      },
  
      /**
       * @private
       * Process the passed fx configuration.
       */
      anim: function(config) {
          if (!Ext.isObject(config)) {
              return (config) ? {} : false;
          }
  
          var me = this;
  
          if (config.stopAnimation) {
              me.stopAnimation();
          }
  
          Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
  
          return Ext.apply({
              target: me,
              paused: true
          }, config);
      },
  
      /**
       * @private
       * Get animation properties
       */
      getAnimationProps: function() {
          var me = this,
              layout = me.layout;
  
          return layout && layout.animate ? layout.animate : {};
      },
  
      /**
       * Stops any running effects and clears this object's internal effects queue if it contains any additional effects
       * that haven't started yet.
       * @deprecated 4.0 Replaced by {@link #stopAnimation}
       * @return {Ext.dom.Element} The Element
       * @method
       */
      stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),
  
      /**
       * Stops any running effects and clears this object's internal effects queue if it contains any additional effects
       * that haven't started yet.
       * @return {Ext.dom.Element} The Element
       */
      stopAnimation: function(/* private */ suppressEvent) {
          Ext.fx.Manager.stopAnimation(this.id, suppressEvent);
          return this;
      },
  
      /**
       * Ensures that all effects queued after syncFx is called on this object are run concurrently. This is the opposite
       * of {@link #sequenceFx}.
       * @return {Object} this
       */
      syncFx: function() {
          Ext.fx.Manager.setFxDefaults(this.id, {
              concurrent: true
          });
          return this;
      },
  
      /**
       * Ensures that all effects queued after sequenceFx is called on this object are run in sequence. This is the
       * opposite of {@link #syncFx}.
       * @return {Object} this
       */
      sequenceFx: function() {
          Ext.fx.Manager.setFxDefaults(this.id, {
              concurrent: false
          });
          return this;
      },
  
      /**
       * @deprecated 4.0 Replaced by {@link #getActiveAnimation}
       * @inheritdoc Ext.util.Animate#getActiveAnimation
       * @method
       */
      hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),
  
      /**
       * Returns the current animation if this object has any effects actively running or queued, else returns false.
       * @return {Ext.fx.Anim/Boolean} Anim if element has active effects, else false
       */
      getActiveAnimation: function() {
          return Ext.fx.Manager.getActiveAnimation(this.id);
      }
  });
  