From e3156ea28617e6cc30a3389ee8d3f30514b9d894 Mon Sep 17 00:00:00 2001 From: ddstreet Date: Tue, 25 Oct 2011 17:40:37 -0500 Subject: [PATCH] Effects Core: Do not overwrite css or class changes that aren't animated during class animation. Fixed #7106 - animateClass: css and class changes during animation are lost --- tests/unit/effects/effects.html | 10 +++ tests/unit/effects/effects_core.js | 136 ++++++++++++++++------------- ui/jquery.effects.core.js | 32 +++---- 3 files changed, 103 insertions(+), 75 deletions(-) diff --git a/tests/unit/effects/effects.html b/tests/unit/effects/effects.html index f2c447ef7cd..f5dac54c7cf 100644 --- a/tests/unit/effects/effects.html +++ b/tests/unit/effects/effects.html @@ -75,6 +75,14 @@ height: 50px; } + .ticket7106 { + width: 50px; + height: 50px; + } + .ticket7106.animate { + width: 100px; + } + @@ -94,6 +102,8 @@

Slide with relative width

+
+
diff --git a/tests/unit/effects/effects_core.js b/tests/unit/effects/effects_core.js index 1e5da211336..e1d52bd8072 100644 --- a/tests/unit/effects/effects_core.js +++ b/tests/unit/effects/effects_core.js @@ -31,59 +31,19 @@ test( "Immediate Return Conditions", function() { equal( ++count, 3, "Both Functions worked properly" ); }); -$.each( $.effects.effect, function( effect ) { - if ( effect === "transfer" ) { - return; - } - module( "effect."+effect ); - asyncTest( "show/hide", function() { - var hidden = $( "div.hidden" ); - expect( 8 ); - - var count = 0, - test = 0; - - function queueTest( fn ) { - count++; - var point = count; - return function( next ) { - test++; - equal( point, test, "Queue function fired in order" ); - if ( fn ) { - fn(); - } else { - setTimeout( next, minDuration ); - } - }; - } - - hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() { - equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" ); - })).queue( queueTest() ).hide( effect, minDuration, queueTest(function() { - equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" ); - })).queue( queueTest(function(next) { - deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains"); - start(); - })); - }); - - asyncTest( "relative width & height - properties are preserved", function() { - var test = $("div.relWidth.relHeight"), - width = test.width(), height = test.height(), - cssWidth = test[0].style.width, cssHeight = test[0].style.height; +test( "createWrapper and removeWrapper retain focused elements (#7595)", function() { + expect( 2 ); + var test = $( "div.hidden" ).show(), + input = $( "" ).appendTo( test ).focus(); - expect( 4 ); - test.toggle( effect, minDuration, function() { - equal( test[0].style.width, cssWidth, "Inline CSS Width has been reset after animation ended" ); - equal( test[0].style.height, cssHeight, "Inline CSS Height has been rest after animation ended" ); - start(); - }); - equal( test.width(), width, "Width is the same px after animation started" ); - equal( test.height(), height, "Height is the same px after animation started" ); - }); + $.effects.createWrapper( test ); + equal( document.activeElement, input[ 0 ], "Active element is still input after createWrapper" ); + $.effects.removeWrapper( test ); + equal( document.activeElement, input[ 0 ], "Active element is still input after removeWrapper" ); }); -module("animateClass"); + +module( "effects.core: animateClass" ); asyncTest( "animateClass works with borderStyle", function() { var test = $("div.animateClass"), @@ -150,15 +110,73 @@ asyncTest( "animateClass clears style properties when stopped", function() { start(); }); -test( "createWrapper and removeWrapper retain focused elements (#7595)", function() { - expect( 2 ); - var test = $( "div.hidden" ).show(), - input = $( "" ).appendTo( test ).focus(); +asyncTest( "animateClass: css and class changes during animation are not lost (#7106)", function() { + var test = $( "div.ticket7106" ); - $.effects.createWrapper( test ); - equal( document.activeElement, input[ 0 ], "Active element is still input after createWrapper" ); - $.effects.removeWrapper( test ); - equal( document.activeElement, input[ 0 ], "Active element is still input after removeWrapper" ); -}) + // add a class and change a style property after starting an animated class + test.addClass( "animate", minDuration, animationComplete ) + .addClass( "testClass" ) + .height( 100 ); + + // ensure the class stays and that the css property stays + function animationComplete() { + ok( test.hasClass( "testClass" ), "class change during animateClass was not lost" ); + equal( test.height(), 100, "css change during animateClass was not lost" ); + start(); + } +}); + + +$.each( $.effects.effect, function( effect ) { + if ( effect === "transfer" ) { + return; + } + module( "effect."+effect ); + asyncTest( "show/hide", function() { + var hidden = $( "div.hidden" ); + expect( 8 ); + + var count = 0, + test = 0; + + function queueTest( fn ) { + count++; + var point = count; + return function( next ) { + test++; + equal( point, test, "Queue function fired in order" ); + if ( fn ) { + fn(); + } else { + setTimeout( next, minDuration ); + } + }; + } + + hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() { + equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" ); + })).queue( queueTest() ).hide( effect, minDuration, queueTest(function() { + equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" ); + })).queue( queueTest(function(next) { + deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains"); + start(); + })); + }); + + asyncTest( "relative width & height - properties are preserved", function() { + var test = $("div.relWidth.relHeight"), + width = test.width(), height = test.height(), + cssWidth = test[0].style.width, cssHeight = test[0].style.height; + + expect( 4 ); + test.toggle( effect, minDuration, function() { + equal( test[0].style.width, cssWidth, "Inline CSS Width has been reset after animation ended" ); + equal( test[0].style.height, cssHeight, "Inline CSS Height has been rest after animation ended" ); + start(); + }); + equal( test.width(), width, "Width is the same px after animation started" ); + equal( test.height(), height, "Height is the same px after animation started" ); + }); +}); })(jQuery); diff --git a/ui/jquery.effects.core.js b/ui/jquery.effects.core.js index 3dc0a4e6710..a47880e7ff8 100644 --- a/ui/jquery.effects.core.js +++ b/ui/jquery.effects.core.js @@ -224,7 +224,7 @@ $.effects.animateClass = function( value, duration, easing, callback ) { return this.queue( function() { var animated = $( this ), baseClass = animated.attr( "class" ) || "", - finalClass, + applyClassChange, allAnimations = o.children ? animated.find( "*" ).andSelf() : animated; // map the animated objects to store the original styles. @@ -232,18 +232,19 @@ $.effects.animateClass = function( value, duration, easing, callback ) { var el = $( this ); return { el: el, - originalStyleAttr: el.attr( "style" ) || " ", start: getElementStyles.call( this ) }; }); // apply class change - $.each( classAnimationActions, function(i, action) { - if ( value[ action ] ) { - animated[ action + "Class" ]( value[ action ] ); - } - }); - finalClass = animated.attr( "class" ); + applyClassChange = function() { + $.each( classAnimationActions, function(i, action) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + }); + }; + applyClassChange(); // map all animated objects again - calculate new styles and diff allAnimations = allAnimations.map(function() { @@ -275,16 +276,15 @@ $.effects.animateClass = function( value, duration, easing, callback ) { $.when.apply( $, allAnimations.get() ).done(function() { // set the final class - animated.attr( "class", finalClass ); + applyClassChange(); - // for each animated element + // for each animated element, + // clear all css properties that were animated $.each( arguments, function() { - if ( typeof this.el.attr( "style" ) === "object" ) { - this.el.attr( "style" ).cssText = ""; - this.el.attr( "style" ).cssText = this.originalStyleAttr; - } else { - this.el.attr( "style", this.originalStyleAttr ); - } + var el = this.el; + $.each( this.diff, function(key) { + el.css( key, '' ); + }); }); // this is guarnteed to be there if you use jQuery.speed()