").appendTo("#qunit-fixture");
$div.css("fill-opacity", 0).animate({ "fill-opacity": 1.0 }, 0, function () {
equal( jQuery(this).css("fill-opacity"), 1, "Do not append px to 'fill-opacity'");
$div.remove();
});
});
// Start 1.8 Animation tests
asyncTest( "jQuery.Animation( object, props, opts )", 4, function() {
var testObject = {
"foo": 0,
"bar": 1,
"width": 100
},
testDest = {
"foo": 1,
"bar": 0,
"width": 200
};
var animation = jQuery.Animation( testObject, testDest, { "duration": 1 });
animation.done(function() {
for ( var prop in testDest ) {
equal( testObject[ prop ], testDest[ prop ], "Animated: " + prop );
}
animation.done(function() {
deepEqual( testObject, testDest, "No unexpected properties" );
start();
});
});
});
asyncTest( "Animate Option: step: function( percent, tween )", 1, function() {
var counter = {};
jQuery( "#foo" ).animate({
prop1: 1,
prop2: 2,
prop3: 3
}, {
duration: 1,
step: function( value, tween ) {
var calls = counter[ tween.prop ] = counter[ tween.prop ] || [];
// in case this is called multiple times for either, lets store it in
// 0 or 1 in the array
calls[ value === 0 ? 0 : 1 ] = value;
}
}).queue( function( next ) {
deepEqual( counter, {
prop1: [0, 1],
prop2: [0, 2],
prop3: [0, 3]
}, "Step function was called once at 0% and once at 100% for each property");
next();
start();
});
});
asyncTest( "Animate callbacks have correct context", 2, function() {
var foo = jQuery( "#foo" );
foo.animate({
height: 10
}, 10, function() {
equal( foo[ 0 ], this, "Complete callback after stop(true) `this` is element" );
}).stop( true, true );
foo.animate({
height: 100
}, 10, function() {
equal( foo[ 0 ], this, "Complete callback `this` is element" );
start();
});
});
asyncTest( "User supplied callback called after show when fx off (#8892)", 2, function() {
var foo = jQuery( "#foo" );
jQuery.fx.off = true;
foo.hide();
foo.fadeIn( 500, function() {
ok( jQuery( this ).is( ":visible" ), "Element is visible in callback" );
foo.fadeOut( 500, function() {
ok( jQuery( this ).is( ":hidden" ), "Element is hidden in callback" );
jQuery.fx.off = false;
start();
});
});
});
test( "animate should set display for disconnected nodes", function() {
expect( 18 );
var i = 0,
methods = {
toggle: [ 1 ],
slideToggle: [],
fadeIn: [],
fadeTo: [ "fast", 0.5 ],
slideDown: [ "fast" ],
show: [ 1 ],
animate: [{ width: "show" }]
},
elems = [
// parentNode = document fragment
jQuery("
test
"),
// parentNode = null
jQuery("
"),
jQuery('
'),
jQuery('
')
];
strictEqual( elems[ 0 ].show()[ 0 ].style.display, "block", "set display with show() for element with parentNode = document fragment" );
strictEqual( elems[ 1 ].show()[ 0 ].style.display, "block", "set display with show() for element with parentNode = null" );
strictEqual( elems[ 2 ].show()[ 0 ].style.display, "inline", "show() should not change display if it already set" );
strictEqual( elems[ 3 ].show()[ 0 ].style.display, "block", "show() should change display if it already set to none" );
// cleanup
jQuery.each( elems, function() {
jQuery.removeData( this[ 0 ], "olddisplay", true );
});
stop();
jQuery.each( methods, function( name, opt ) {
jQuery.each([
// parentNode = document fragment
jQuery("
test
"),
// parentNode = null
jQuery("
")
], function() {
var callback = [function () {
strictEqual( this.style.display, "block", "set display to block with " + name );
jQuery.removeData( this, "olddisplay", true );
if ( ++i === 14 ) {
start();
}
}];
jQuery.fn[ name ].apply( this, opt.concat( callback ) );
});
});
});
asyncTest("Animation callback should not show animated element as animated (#7157)", 1, function() {
var foo = jQuery( "#foo" );
foo.animate({
opacity: 0
}, 100, function() {
ok( !foo.is(':animated'), "The element is not animated" );
start();
});
});
asyncTest( "hide called on element within hidden parent should set display to none (#10045)", 3, function() {
var hidden = jQuery(".hidden"),
elems = jQuery("
hide
hide0
hide1
");
hidden.append( elems );
jQuery.when(
elems.eq( 0 ).hide(),
elems.eq( 1 ).hide( 0 ),
elems.eq( 2 ).hide( 1 )
).done(function() {
strictEqual( elems.get( 0 ).style.display, "none", "hide() called on element within hidden parent should set display to none" );
strictEqual( elems.get( 1 ).style.display, "none", "hide( 0 ) called on element within hidden parent should set display to none" );
strictEqual( elems.get( 2 ).style.display, "none", "hide( 1 ) called on element within hidden parent should set display to none" );
elems.remove();
start();
});
});
asyncTest( "hide, fadeOut and slideUp called on element width height and width = 0 should set display to none", 5, function() {
var foo = jQuery("#foo"),
i = 0,
elems = jQuery();
for ( ; i < 5; i++ ) {
elems = elems.add('
');
}
foo.append( elems );
jQuery.when(
elems.eq( 0 ).hide(),
elems.eq( 1 ).hide( jQuery.noop ),
elems.eq( 2 ).hide( 1 ),
elems.eq( 3 ).fadeOut(),
elems.eq( 4 ).slideUp()
).done(function() {
strictEqual( elems.get( 0 ).style.display, "none", "hide() called on element width height and width = 0 should set display to none" );
strictEqual( elems.get( 1 ).style.display, "none",
"hide( jQuery.noop ) called on element width height and width = 0 should set display to none" );
strictEqual( elems.get( 2 ).style.display, "none", "hide( 1 ) called on element width height and width = 0 should set display to none" );
strictEqual( elems.get( 3 ).style.display, "none", "fadeOut() called on element width height and width = 0 should set display to none" );
strictEqual( elems.get( 4 ).style.display, "none", "slideUp() called on element width height and width = 0 should set display to none" );
start();
});
});
asyncTest( "Handle queue:false promises", 10, function() {
var foo = jQuery( "#foo" ).clone().andSelf(),
step = 1;
foo.animate({
top: 1
}, {
duration: 10,
queue: false,
complete: function() {
ok( step++ <= 2, "Step one or two" );
}
}).animate({
bottom: 1
}, {
duration: 10,
complete: function() {
ok( step > 2 && step < 5, "Step three or four" );
step++;
}
});
foo.promise().done( function() {
equal( step++, 5, "steps 1-5: queue:false then queue:fx done" );
foo.animate({
top: 10
}, {
duration: 10,
complete: function() {
ok( step > 5 && step < 8, "Step six or seven" );
step++;
}
}).animate({
bottom: 10
}, {
duration: 10,
queue: false,
complete: function() {
ok( step > 7 && step < 10, "Step eight or nine" );
step++;
}
}).promise().done( function() {
equal( step++, 10, "steps 6-10: queue:fx then queue:false" );
start();
});
});
});
asyncTest( "multiple unqueued and promise", 4, function() {
var foo = jQuery( "#foo" ),
step = 1;
foo.animate({
marginLeft: 300
}, {
duration: 500,
queue: false,
complete: function() {
strictEqual( step++, 2, "Step 2" );
}
}).animate({
top: 100
}, {
duration: 1500,
queue: false,
complete: function() {
strictEqual( step++, 3, "Step 3" );
}
}).animate({}, {
duration: 2000,
queue: false,
complete: function() {
// no properties is a non-op and finishes immediately
strictEqual( step++, 1, "Step 1" );
}
}).promise().done( function() {
strictEqual( step++, 4, "Step 4" );
start();
});
});
asyncTest( "animate does not change start value for non-px animation (#7109)", 1, function() {
var parent = jQuery( "
" ).css({ width: 284, height: 1 }).appendTo( "#qunit-fixture" ),
child = parent.children().css({ fontSize: "98.6in", width: "0.01em", height: 1 }),
actual = parseFloat( child.css( "width" ) ),
computed = [];
child.animate({ width: "0%" }, {
duration: 1,
step: function() {
computed.push( parseFloat( child.css( "width" ) ) );
}
}).queue( function( next ) {
var ratio = computed[ 0 ] / actual;
ok( ratio > 0.9 && ratio < 1.1 , "Starting width was close enough" );
next();
parent.remove();
start();
});
});
asyncTest( "non-px animation handles non-numeric start (#11971)", 2, function() {
var foo = jQuery("#foo"),
initial = foo.css("backgroundPositionX");
if ( initial == null ) {
expect(1);
ok( true, "Style property not understood" );
start();
return;
}
foo.animate({ backgroundPositionX: "42%" }, {
duration: 1,
progress: function( anim, percent ) {
if ( percent ) {
return;
}
if ( parseFloat( initial ) ) {
equal( jQuery.style( this, "backgroundPositionX" ), initial, "Numeric start preserved" );
} else {
equal( jQuery.style( this, "backgroundPositionX" ), "0%", "Non-numeric start zeroed" );
}
},
done: function() {
equal( jQuery.style( this, "backgroundPositionX" ), "42%", "End reached" );
start();
}
});
});
asyncTest("Animation callbacks (#11797)", 15, function() {
var targets = jQuery("#foo").children(),
done = false,
expectedProgress = 0;
targets.eq( 0 ).animate( {}, {
duration: 1,
start: function() {
ok( true, "empty: start" );
},
progress: function( anim, percent ) {
equal( percent, 0, "empty: progress 0" );
},
done: function() {
ok( true, "empty: done" );
},
fail: function() {
ok( false, "empty: fail" );
},
always: function() {
ok( true, "empty: always" );
done = true;
}
});
ok( done, "empty: done immediately" );
done = false;
targets.eq( 1 ).animate({
opacity: 0
}, {
duration: 1,
start: function() {
ok( true, "stopped: start" );
},
progress: function( anim, percent ) {
equal( percent, 0, "stopped: progress 0" );
},
done: function() {
ok( false, "stopped: done" );
},
fail: function() {
ok( true, "stopped: fail" );
},
always: function() {
ok( true, "stopped: always" );
done = true;
}
}).stop();
ok( done, "stopped: stopped immediately" );
targets.eq( 2 ).animate({
opacity: 0
}, {
duration: 1,
start: function() {
ok( true, "async: start" );
},
progress: function( anim, percent ) {
// occasionally the progress handler is called twice in first frame.... *shrug*
if ( percent === 0 && expectedProgress === 1 ) {
return;
}
equal( percent, expectedProgress, "async: progress " + expectedProgress );
// once at 0, once at 1
expectedProgress++;
},
done: function() {
ok( true, "async: done" );
},
fail: function() {
ok( false, "async: fail" );
},
always: function() {
ok( true, "async: always" );
start();
}
});
});
test( "Animate properly sets overflow hidden when animating width/height (#12117)", 4, function() {
jQuery.each( [ "height", "width" ], function( _, prop ) {
jQuery.each( [ 100, 0 ], function( _, value ) {
var div = jQuery("
"),
props = {};
props[ prop ] = value;
div.animate( props, 1 );
equal( div.css( "overflow" ), "hidden",
"overflow: hidden set when animating " + prop + " to " + value );
div.stop();
});
});
});
} // if ( jQuery.fx )