Skip to content

Commit e3156ea

Browse files
ddstreetgnarf
authored andcommitted
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
1 parent 4cc61b4 commit e3156ea

File tree

3 files changed

+103
-75
lines changed

3 files changed

+103
-75
lines changed

tests/unit/effects/effects.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@
7575
height: 50px;
7676
}
7777

78+
.ticket7106 {
79+
width: 50px;
80+
height: 50px;
81+
}
82+
.ticket7106.animate {
83+
width: 100px;
84+
}
85+
7886
</style>
7987
</head>
8088
<body>
@@ -94,6 +102,8 @@ <h2>Slide with relative width</h2>
94102
</div>
95103
<div class="testScale">
96104
</div>
105+
<div class="ticket7106">
106+
</div>
97107

98108
</div>
99109
</body>

tests/unit/effects/effects_core.js

Lines changed: 77 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -31,59 +31,19 @@ test( "Immediate Return Conditions", function() {
3131
equal( ++count, 3, "Both Functions worked properly" );
3232
});
3333

34-
$.each( $.effects.effect, function( effect ) {
35-
if ( effect === "transfer" ) {
36-
return;
37-
}
38-
module( "effect."+effect );
39-
asyncTest( "show/hide", function() {
40-
var hidden = $( "div.hidden" );
41-
expect( 8 );
42-
43-
var count = 0,
44-
test = 0;
45-
46-
function queueTest( fn ) {
47-
count++;
48-
var point = count;
49-
return function( next ) {
50-
test++;
51-
equal( point, test, "Queue function fired in order" );
52-
if ( fn ) {
53-
fn();
54-
} else {
55-
setTimeout( next, minDuration );
56-
}
57-
};
58-
}
59-
60-
hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() {
61-
equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" );
62-
})).queue( queueTest() ).hide( effect, minDuration, queueTest(function() {
63-
equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" );
64-
})).queue( queueTest(function(next) {
65-
deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains");
66-
start();
67-
}));
68-
});
69-
70-
asyncTest( "relative width & height - properties are preserved", function() {
71-
var test = $("div.relWidth.relHeight"),
72-
width = test.width(), height = test.height(),
73-
cssWidth = test[0].style.width, cssHeight = test[0].style.height;
34+
test( "createWrapper and removeWrapper retain focused elements (#7595)", function() {
35+
expect( 2 );
36+
var test = $( "div.hidden" ).show(),
37+
input = $( "<input>" ).appendTo( test ).focus();
7438

75-
expect( 4 );
76-
test.toggle( effect, minDuration, function() {
77-
equal( test[0].style.width, cssWidth, "Inline CSS Width has been reset after animation ended" );
78-
equal( test[0].style.height, cssHeight, "Inline CSS Height has been rest after animation ended" );
79-
start();
80-
});
81-
equal( test.width(), width, "Width is the same px after animation started" );
82-
equal( test.height(), height, "Height is the same px after animation started" );
83-
});
39+
$.effects.createWrapper( test );
40+
equal( document.activeElement, input[ 0 ], "Active element is still input after createWrapper" );
41+
$.effects.removeWrapper( test );
42+
equal( document.activeElement, input[ 0 ], "Active element is still input after removeWrapper" );
8443
});
8544

86-
module("animateClass");
45+
46+
module( "effects.core: animateClass" );
8747

8848
asyncTest( "animateClass works with borderStyle", function() {
8949
var test = $("div.animateClass"),
@@ -150,15 +110,73 @@ asyncTest( "animateClass clears style properties when stopped", function() {
150110
start();
151111
});
152112

153-
test( "createWrapper and removeWrapper retain focused elements (#7595)", function() {
154-
expect( 2 );
155-
var test = $( "div.hidden" ).show(),
156-
input = $( "<input>" ).appendTo( test ).focus();
113+
asyncTest( "animateClass: css and class changes during animation are not lost (#7106)", function() {
114+
var test = $( "div.ticket7106" );
157115

158-
$.effects.createWrapper( test );
159-
equal( document.activeElement, input[ 0 ], "Active element is still input after createWrapper" );
160-
$.effects.removeWrapper( test );
161-
equal( document.activeElement, input[ 0 ], "Active element is still input after removeWrapper" );
162-
})
116+
// add a class and change a style property after starting an animated class
117+
test.addClass( "animate", minDuration, animationComplete )
118+
.addClass( "testClass" )
119+
.height( 100 );
120+
121+
// ensure the class stays and that the css property stays
122+
function animationComplete() {
123+
ok( test.hasClass( "testClass" ), "class change during animateClass was not lost" );
124+
equal( test.height(), 100, "css change during animateClass was not lost" );
125+
start();
126+
}
127+
});
128+
129+
130+
$.each( $.effects.effect, function( effect ) {
131+
if ( effect === "transfer" ) {
132+
return;
133+
}
134+
module( "effect."+effect );
135+
asyncTest( "show/hide", function() {
136+
var hidden = $( "div.hidden" );
137+
expect( 8 );
138+
139+
var count = 0,
140+
test = 0;
141+
142+
function queueTest( fn ) {
143+
count++;
144+
var point = count;
145+
return function( next ) {
146+
test++;
147+
equal( point, test, "Queue function fired in order" );
148+
if ( fn ) {
149+
fn();
150+
} else {
151+
setTimeout( next, minDuration );
152+
}
153+
};
154+
}
155+
156+
hidden.queue( queueTest() ).show( effect, minDuration, queueTest(function() {
157+
equal( hidden.css("display"), "block", "Hidden is shown after .show(\"" +effect+ "\", time)" );
158+
})).queue( queueTest() ).hide( effect, minDuration, queueTest(function() {
159+
equal( hidden.css("display"), "none", "Back to hidden after .hide(\"" +effect+ "\", time)" );
160+
})).queue( queueTest(function(next) {
161+
deepEqual( hidden.queue(), ["inprogress"], "Only the inprogress sentinel remains");
162+
start();
163+
}));
164+
});
165+
166+
asyncTest( "relative width & height - properties are preserved", function() {
167+
var test = $("div.relWidth.relHeight"),
168+
width = test.width(), height = test.height(),
169+
cssWidth = test[0].style.width, cssHeight = test[0].style.height;
170+
171+
expect( 4 );
172+
test.toggle( effect, minDuration, function() {
173+
equal( test[0].style.width, cssWidth, "Inline CSS Width has been reset after animation ended" );
174+
equal( test[0].style.height, cssHeight, "Inline CSS Height has been rest after animation ended" );
175+
start();
176+
});
177+
equal( test.width(), width, "Width is the same px after animation started" );
178+
equal( test.height(), height, "Height is the same px after animation started" );
179+
});
180+
});
163181

164182
})(jQuery);

ui/jquery.effects.core.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -224,26 +224,27 @@ $.effects.animateClass = function( value, duration, easing, callback ) {
224224
return this.queue( function() {
225225
var animated = $( this ),
226226
baseClass = animated.attr( "class" ) || "",
227-
finalClass,
227+
applyClassChange,
228228
allAnimations = o.children ? animated.find( "*" ).andSelf() : animated;
229229

230230
// map the animated objects to store the original styles.
231231
allAnimations = allAnimations.map(function() {
232232
var el = $( this );
233233
return {
234234
el: el,
235-
originalStyleAttr: el.attr( "style" ) || " ",
236235
start: getElementStyles.call( this )
237236
};
238237
});
239238

240239
// apply class change
241-
$.each( classAnimationActions, function(i, action) {
242-
if ( value[ action ] ) {
243-
animated[ action + "Class" ]( value[ action ] );
244-
}
245-
});
246-
finalClass = animated.attr( "class" );
240+
applyClassChange = function() {
241+
$.each( classAnimationActions, function(i, action) {
242+
if ( value[ action ] ) {
243+
animated[ action + "Class" ]( value[ action ] );
244+
}
245+
});
246+
};
247+
applyClassChange();
247248

248249
// map all animated objects again - calculate new styles and diff
249250
allAnimations = allAnimations.map(function() {
@@ -275,16 +276,15 @@ $.effects.animateClass = function( value, duration, easing, callback ) {
275276
$.when.apply( $, allAnimations.get() ).done(function() {
276277

277278
// set the final class
278-
animated.attr( "class", finalClass );
279+
applyClassChange();
279280

280-
// for each animated element
281+
// for each animated element,
282+
// clear all css properties that were animated
281283
$.each( arguments, function() {
282-
if ( typeof this.el.attr( "style" ) === "object" ) {
283-
this.el.attr( "style" ).cssText = "";
284-
this.el.attr( "style" ).cssText = this.originalStyleAttr;
285-
} else {
286-
this.el.attr( "style", this.originalStyleAttr );
287-
}
284+
var el = this.el;
285+
$.each( this.diff, function(key) {
286+
el.css( key, '' );
287+
});
288288
});
289289

290290
// this is guarnteed to be there if you use jQuery.speed()

0 commit comments

Comments
 (0)