+ startingFilter: function(o) {
+ return o.paused === false && o.running === false && o.iterations > 0;
+ },
+
+<span id='Ext-fx-Manager-method-runningFilter'> /**
+</span> * @private
+ * Filter function to determine which animations are still running
+ */
+ runningFilter: function(o) {
+ return o.paused === false && o.running === true && o.isAnimator !== true;
+ },
+
+<span id='Ext-fx-Manager-method-runner'> /**
+</span> * @private
+ * Runner function being called each frame
+ */
+ runner: function() {
+ var me = this,
+ items = me.items;
+
+ me.targetData = {};
+ me.targetArr = {};
+
+ // Single timestamp for all animations this interval
+ me.timestamp = new Date();
+
+ // Start any items not current running
+ items.filterBy(me.startingFilter).each(me.startAnim, me);
+
+ // Build the new attributes to be applied for all targets in this frame
+ items.filterBy(me.runningFilter).each(me.runAnim, me);
+
+ // Apply all the pending changes to their targets
+ me.applyPendingAttrs();
+ },
+
+<span id='Ext-fx-Manager-method-startAnim'> /**
+</span> * @private
+ * Start the individual animation (initialization)
+ */
+ startAnim: function(anim) {
+ anim.start(this.timestamp);
+ },
+
+<span id='Ext-fx-Manager-method-runAnim'> /**
+</span> * @private
+ * Run the individual animation for this frame
+ */
+ runAnim: function(anim) {
+ if (!anim) {
+ return;
+ }
+ var me = this,
+ targetId = anim.target.getId(),
+ useCSS3 = me.useCSS3 && anim.target.type == 'element',
+ elapsedTime = me.timestamp - anim.startTime,
+ target, o;
+
+ this.collectTargetData(anim, elapsedTime, useCSS3);
+
+ // For CSS3 animation, we need to immediately set the first frame's attributes without any transition
+ // to get a good initial state, then add the transition properties and set the final attributes.
+ if (useCSS3) {
+ // Flush the collected attributes, without transition
+ anim.target.setAttr(me.targetData[targetId], true);
+
+ // Add the end frame data
+ me.targetData[targetId] = [];
+ me.collectTargetData(anim, anim.duration, useCSS3);
+
+ // Pause the animation so runAnim doesn't keep getting called
+ anim.paused = true;
+
+ target = anim.target.target;
+ // We only want to attach an event on the last element in a composite
+ if (anim.target.isComposite) {
+ target = anim.target.target.last();
+ }
+
+ // Listen for the transitionend event
+ o = {};
+ o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
+ o.scope = anim;
+ o.single = true;
+ target.on(o);
+ }
+ // For JS animation, trigger the lastFrame handler if this is the final frame
+ else if (elapsedTime >= anim.duration) {
+ me.applyPendingAttrs(true);
+ delete me.targetData[targetId];
+ delete me.targetArr[targetId];
+ anim.lastFrame();
+ }
+ },
+
+<span id='Ext-fx-Manager-method-collectTargetData'> /**
+</span> * Collect target attributes for the given Anim object at the given timestamp
+ * @param {Ext.fx.Anim} anim The Anim instance
+ * @param {Number} timestamp Time after the anim's start time
+ */
+ collectTargetData: function(anim, elapsedTime, useCSS3) {
+ var targetId = anim.target.getId(),
+ targetData = this.targetData[targetId],
+ data;
+
+ if (!targetData) {
+ targetData = this.targetData[targetId] = [];
+ this.targetArr[targetId] = anim.target;
+ }
+
+ data = {
+ duration: anim.duration,
+ easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
+ attrs: {}
+ };
+ Ext.apply(data.attrs, anim.runAnim(elapsedTime));
+ targetData.push(data);