text: /**
   * @class Ext.fx.Queue
   * Animation Queue mixin to handle chaining and queueing by target.
   * @private
   */
  
  Ext.define('Ext.fx.Queue', {
  
      requires: ['Ext.util.HashMap'],
  
      constructor: function() {
          this.targets = new Ext.util.HashMap();
          this.fxQueue = {};
      },
  
      /**
       * @private
       */
      getFxDefaults: function(targetId) {
          var target = this.targets.get(targetId);
          if (target) {
              return target.fxDefaults;
          }
          return {};
      },
  
      /**
       * @private
       */
      setFxDefaults: function(targetId, obj) {
          var target = this.targets.get(targetId);
          if (target) {
              target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj);
          }
      },
  
      /**
       * @private
       */
      stopAnimation: function(targetId) {
          var me = this,
              queue = me.getFxQueue(targetId),
              ln = queue.length,
              item;
          
          while (ln) {
              item = queue[ln - 1];
              
              if (item) {
                  item.end();
              }
              
              ln--;
          }
      },
  
      /**
       * @private
       * Returns current animation object if the element has any effects actively running or queued, else returns false.
       */
      getActiveAnimation: function(targetId) {
          var queue = this.getFxQueue(targetId);
          return (queue && !!queue.length) ? queue[0] : false;
      },
  
      /**
       * @private
       */
      hasFxBlock: function(targetId) {
          var queue = this.getFxQueue(targetId);
          return queue && queue[0] && queue[0].block;
      },
  
      /**
       * @private
       * Get fx queue for passed target, create if needed.
       */
      getFxQueue: function(targetId) {
          if (!targetId) {
              return false;
          }
          var me = this,
              queue = me.fxQueue[targetId],
              target = me.targets.get(targetId);
  
          if (!target) {
              return false;
          }
  
          if (!queue) {
              me.fxQueue[targetId] = [];
              // GarbageCollector will need to clean up Elements since they aren't currently observable
              if (target.type !== 'element') {
                  target.target.on('destroy', function() {
                      me.fxQueue[targetId] = [];
                  });
              }
          }
          return me.fxQueue[targetId];
      },
  
      /**
       * @private
       */
      queueFx: function(anim) {
          var me = this,
              target = anim.target,
              queue, ln;
  
          if (!target) {
              return;
          }
  
          queue = me.getFxQueue(target.getId());
          ln = queue.length;
  
          if (ln) {
              if (anim.concurrent) {
                  anim.paused = false;
              }
              else {
                  queue[ln - 1].on('afteranimate', function() {
                      anim.paused = false;
                  });
              }
          }
          else {
              anim.paused = false;
          }
          anim.on('afteranimate', function() {
              Ext.Array.remove(queue, anim);
              if (queue.length === 0) {
                  me.targets.remove(anim.target);
              }
              if (anim.remove) {
                  if (target.type === 'element') {
                      var el = Ext.get(target.id);
                      if (el) {
                          el.destroy();
                      }
                  }
              }
          }, me, {
              single: true
          });
          queue.push(anim);
      }
  });