Renamed the 'fx' module to 'effects'. Should've been done a long time ago.
[jquery.git] / test / unit / effects.js
1 module("effects");
2
3 test("show()", function() {
4         expect(16);
5         var pass = true, div = jQuery("#main div");
6         div.show().each(function(){
7                 if ( this.style.display == "none" ) pass = false;
8         });
9         ok( pass, "Show" );
10
11         pass = true;
12         div.hide().show(null).each(function() {
13                 if ( this.style.display == "none" ) pass = false;
14         });
15         ok( pass, "Show will null speed");
16
17         jQuery("#main").append('<div id="show-tests"><div><p><a href="#"></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div>');
18
19         var old = jQuery("#show-tests table").show().css("display") !== "table";
20
21         var test = {
22                 "div"      : "block",
23                 "p"        : "block",
24                 "a"        : "inline",
25                 "code"     : "inline",
26                 "pre"      : "block",
27                 "span"     : "inline",
28                 "table"    : old ? "block" : "table",
29                 "thead"    : old ? "block" : "table-header-group",
30                 "tbody"    : old ? "block" : "table-row-group",
31                 "tr"       : old ? "block" : "table-row",
32                 "th"       : old ? "block" : "table-cell",
33                 "td"       : old ? "block" : "table-cell",
34                 "ul"       : "block",
35                 "li"       : old ? "block" : "list-item"
36         };
37
38         jQuery.each(test, function(selector, expected) {
39                 var elem = jQuery(selector, "#show-tests").show();
40                 equals( elem.css("display"), expected, "Show using correct display type for " + selector );
41         });
42 });
43
44 test("show(Number) - other displays", function() {
45         expect(15);
46         reset();
47         stop();
48
49         jQuery("#main").append('<div id="show-tests"><div><p><a href="#"></a></p><code></code><pre></pre><span></span></div><table><thead><tr><th></th></tr></thead><tbody><tr><td></td></tr></tbody></table><ul><li></li></ul></div>');
50
51         var old = jQuery("#show-tests table").show().css("display") !== "table",
52                 num = 0;
53
54         var test = {
55                 "div"      : "block",
56                 "p"        : "block",
57                 "a"        : "inline",
58                 "code"     : "inline",
59                 "pre"      : "block",
60                 "span"     : "inline",
61                 "table"    : old ? "block" : "table",
62                 "thead"    : old ? "block" : "table-header-group",
63                 "tbody"    : old ? "block" : "table-row-group",
64                 "tr"       : old ? "block" : "table-row",
65                 "th"       : old ? "block" : "table-cell",
66                 "td"       : old ? "block" : "table-cell",
67                 "ul"       : "block",
68                 "li"       : old ? "block" : "list-item"
69         };
70
71         jQuery.each(test, function(selector, expected) {
72                 var elem = jQuery(selector, "#show-tests").show(1, function() {
73                         equals( elem.css("display"), expected, "Show using correct display type for " + selector );
74                         if ( ++num === 15 ) {
75                                 start();
76                         }
77                 });
78         });
79 });
80
81 test("animate(Hash, Object, Function)", function() {
82         expect(1);
83         stop();
84         var hash = {opacity: 'show'};
85         var hashCopy = jQuery.extend({}, hash);
86         jQuery('#foo').animate(hash, 0, function() {
87                 equals( hash.opacity, hashCopy.opacity, 'Check if animate changed the hash parameter' );
88                 start();
89         });
90 });
91
92 test("animate negative height", function() {
93         expect(1);
94         stop();
95         jQuery("#foo").animate({ height: -100 }, 100, function() {
96                 equals( this.offsetHeight, 0, "Verify height." );
97                 start();
98         });
99 });
100
101 /* // This test ends up being flaky depending upon the CPU load
102 test("animate option (queue === false)", function () {
103         expect(1);
104         stop();
105
106         var order = [];
107
108         var $foo = jQuery("#foo");
109         $foo.animate({width:'100px'}, 3000, function () {
110                 // should finish after unqueued animation so second
111                 order.push(2);
112                 same( order, [ 1, 2 ], "Animations finished in the correct order" );
113                 start();
114         });
115         $foo.animate({fontSize:'2em'}, {queue:false, duration:10, complete:function () {
116                 // short duration and out of queue so should finish first
117                 order.push(1);
118         }});
119 });
120 */
121
122 test("animate with no properties", function() {
123         expect(1);
124         
125         var divs = jQuery("div"), count = 0;
126
127         divs.animate({}, function(){
128                 count++;
129         });
130
131         equals( divs.length, count, "Make sure that callback is called for each element in the set." );
132 });
133
134 test("animate duration 0", function() {
135         expect(11);
136         
137         stop();
138         
139         var $elems = jQuery([{ a:0 },{ a:0 }]), counter = 0;
140         
141         equals( jQuery.timers.length, 0, "Make sure no animation was running from another test" );
142                 
143         $elems.eq(0).animate( {a:1}, 0, function(){
144                 ok( true, "Animate a simple property." );
145                 counter++;
146         });
147         
148         // Failed until [6115]
149         equals( jQuery.timers.length, 0, "Make sure synchronic animations are not left on jQuery.timers" );
150         
151         equals( counter, 1, "One synchronic animations" );
152         
153         $elems.animate( { a:2 }, 0, function(){
154                 ok( true, "Animate a second simple property." );
155                 counter++;
156         });
157         
158         equals( counter, 3, "Multiple synchronic animations" );
159         
160         $elems.eq(0).animate( {a:3}, 0, function(){
161                 ok( true, "Animate a third simple property." );
162                 counter++;
163         });
164         $elems.eq(1).animate( {a:3}, 200, function(){
165                 counter++;
166                 // Failed until [6115]
167                 equals( counter, 5, "One synchronic and one asynchronic" );
168                 start();
169         });
170         
171         var $elem = jQuery("<div />");
172         $elem.show(0, function(){ 
173                 ok(true, "Show callback with no duration");
174         });
175         $elem.hide(0, function(){ 
176                 ok(true, "Hide callback with no duration");
177         });
178 });
179
180 test("animate hyphenated properties", function(){
181         expect(1);
182         stop();
183
184         jQuery("#nothiddendiv")
185                 .css("font-size", 10)
186                 .animate({"font-size": 20}, 200, function(){
187                         equals( this.style.fontSize, "20px", "The font-size property was animated." );
188                         start();
189                 });
190 });
191
192 test("animate non-element", function(){
193         expect(1);
194         stop();
195
196         var obj = { test: 0 };
197
198         jQuery(obj).animate({test: 200}, 200, function(){
199                 equals( obj.test, 200, "The custom property should be modified." );
200                 start();
201         });
202 });
203
204 test("stop()", function() {
205         expect(3);
206         stop();
207
208         var $foo = jQuery("#nothiddendiv");
209         var w = 0;
210         $foo.hide().width(200).width();
211
212         $foo.animate({ width:'show' }, 1000);
213         setTimeout(function(){
214                 var nw = $foo.width();
215                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
216                 $foo.stop();
217
218                 nw = $foo.width();
219                 ok( nw != w, "Stop didn't reset the animation " + nw + "px " + w + "px");
220                 setTimeout(function(){
221                         equals( nw, $foo.width(), "The animation didn't continue" );
222                         start();
223                 }, 100);
224         }, 100);
225 });
226
227 test("stop() - several in queue", function() {
228         expect(3);
229         stop();
230
231         var $foo = jQuery("#nothiddendivchild");
232         var w = 0;
233         $foo.hide().width(200).width();
234
235         $foo.animate({ width:'show' }, 1000);
236         $foo.animate({ width:'hide' }, 1000);
237         $foo.animate({ width:'show' }, 1000);
238         setTimeout(function(){
239                 equals( $foo.queue().length, 3, "All 3 still in the queue" );
240                 var nw = $foo.width();
241                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
242                 $foo.stop();
243
244                 nw = $foo.width();
245                 ok( nw != w, "Stop didn't reset the animation " + nw + "px " + w + "px");
246                 // Disabled, being flaky
247                 //equals( $foo.queue().length, 1, "The next animation continued" );
248                 $foo.stop(true);
249                 start();
250         }, 100);
251 });
252
253 test("stop(clearQueue)", function() {
254         expect(4);
255         stop();
256
257         var $foo = jQuery("#nothiddendiv");
258         var w = 0;
259         $foo.hide().width(200).width();
260
261         $foo.animate({ width:'show' }, 1000);
262         $foo.animate({ width:'hide' }, 1000);
263         $foo.animate({ width:'show' }, 1000);
264         setTimeout(function(){
265                 var nw = $foo.width();
266                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
267                 $foo.stop(true);
268
269                 nw = $foo.width();
270                 ok( nw != w, "Stop didn't reset the animation " + nw + "px " + w + "px");
271
272                 equals( $foo.queue().length, 0, "The animation queue was cleared" );
273                 setTimeout(function(){
274                         equals( nw, $foo.width(), "The animation didn't continue" );
275                         start();
276                 }, 100);
277         }, 100);
278 });
279
280 test("stop(clearQueue, gotoEnd)", function() {
281         expect(1);
282         stop();
283
284         var $foo = jQuery("#nothiddendivchild");
285         var w = 0;
286         $foo.hide().width(200).width();
287
288         $foo.animate({ width:'show' }, 1000);
289         $foo.animate({ width:'hide' }, 1000);
290         $foo.animate({ width:'show' }, 1000);
291         $foo.animate({ width:'hide' }, 1000);
292         setTimeout(function(){
293                 var nw = $foo.width();
294                 ok( nw != w, "An animation occurred " + nw + "px " + w + "px");
295                 $foo.stop(false, true);
296
297                 nw = $foo.width();
298                 // Disabled, being flaky
299                 //equals( nw, 1, "Stop() reset the animation" );
300
301                 setTimeout(function(){
302                         // Disabled, being flaky
303                         //equals( $foo.queue().length, 2, "The next animation continued" );
304                         $foo.stop(true);
305                         start();
306                 }, 100);
307         }, 100);
308 });
309
310 test("toggle()", function() {
311         expect(6);
312         var x = jQuery("#nothiddendiv");
313         ok( x.is(":visible"), "is visible" );
314         x.toggle();
315         ok( x.is(":hidden"), "is hidden" );
316         x.toggle();
317         ok( x.is(":visible"), "is visible again" );
318         
319         x.toggle(true);
320         ok( x.is(":visible"), "is visible" );
321         x.toggle(false);
322         ok( x.is(":hidden"), "is hidden" );
323         x.toggle(true);
324         ok( x.is(":visible"), "is visible again" );
325 });
326
327 jQuery.checkOverflowDisplay = function(){
328         var o = jQuery.css( this, "overflow" );
329
330         equals(o, "visible", "Overflow should be visible: " + o);
331         equals(jQuery.css( this, "display" ), "inline", "Display shouldn't be tampered with.");
332
333         start();
334 }
335
336 test("JS Overflow and Display", function() {
337         expect(2);
338         stop();
339         jQuery.makeTest( "JS Overflow and Display" )
340                 .addClass("widewidth")
341                 .css({ overflow: "visible", display: "inline" })
342                 .addClass("widewidth")
343                 .text("Some sample text.")
344                 .before("text before")
345                 .after("text after")
346                 .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay);
347 });
348                 
349 test("CSS Overflow and Display", function() {
350         expect(2);
351         stop();
352         jQuery.makeTest( "CSS Overflow and Display" )
353                 .addClass("overflow inline")
354                 .addClass("widewidth")
355                 .text("Some sample text.")
356                 .before("text before")
357                 .after("text after")
358                 .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay);
359 });
360
361 jQuery.each( {
362         "CSS Auto": function(elem,prop){
363                 jQuery(elem).addClass("auto" + prop)
364                         .text("This is a long string of text.");
365                 return "";
366         },
367         "JS Auto": function(elem,prop){
368                 jQuery(elem).css(prop,"auto")
369                         .text("This is a long string of text.");
370                 return "";
371         },
372         "CSS 100": function(elem,prop){
373                 jQuery(elem).addClass("large" + prop);
374                 return "";
375         },
376         "JS 100": function(elem,prop){
377                 jQuery(elem).css(prop,prop == "opacity" ? 1 : "100px");
378                 return prop == "opacity" ? 1 : 100;
379         },
380         "CSS 50": function(elem,prop){
381                 jQuery(elem).addClass("med" + prop);
382                 return "";
383         },
384         "JS 50": function(elem,prop){
385                 jQuery(elem).css(prop,prop == "opacity" ? 0.50 : "50px");
386                 return prop == "opacity" ? 0.5 : 50;
387         },
388         "CSS 0": function(elem,prop){
389                 jQuery(elem).addClass("no" + prop);
390                 return "";
391         },
392         "JS 0": function(elem,prop){
393                 jQuery(elem).css(prop,prop == "opacity" ? 0 : "0px");
394                 return 0;
395         }
396 }, function(fn, f){
397         jQuery.each( {
398                 "show": function(elem,prop){
399                         jQuery(elem).hide().addClass("wide"+prop);
400                         return "show";
401                 },
402                 "hide": function(elem,prop){
403                         jQuery(elem).addClass("wide"+prop);
404                         return "hide";
405                 },
406                 "100": function(elem,prop){
407                         jQuery(elem).addClass("wide"+prop);
408                         return prop == "opacity" ? 1 : 100;
409                 },
410                 "50": function(elem,prop){
411                         return prop == "opacity" ? 0.50 : 50;
412                 },
413                 "0": function(elem,prop){
414                         jQuery(elem).addClass("noback");
415                         return 0;
416                 }
417         }, function(tn, t){
418                 test(fn + " to " + tn, function() {
419                         var elem = jQuery.makeTest( fn + " to " + tn );
420         
421                         var t_w = t( elem, "width" );
422                         var f_w = f( elem, "width" );
423                         var t_h = t( elem, "height" );
424                         var f_h = f( elem, "height" );
425                         var t_o = t( elem, "opacity" );
426                         var f_o = f( elem, "opacity" );
427                         
428                         var num = 0;
429                         
430                         if ( t_h == "show" ) num++;
431                         if ( t_w == "show" ) num++;
432                         if ( t_w == "hide"||t_w == "show" ) num++;
433                         if ( t_h == "hide"||t_h == "show" ) num++;
434                         if ( t_o == "hide"||t_o == "show" ) num++;
435                         if ( t_w == "hide" ) num++;
436                         if ( t_o.constructor == Number ) num += 2;
437                         if ( t_w.constructor == Number ) num += 2;
438                         if ( t_h.constructor == Number ) num +=2;
439                         
440                         expect(num);
441                         stop();
442         
443                         var anim = { width: t_w, height: t_h, opacity: t_o };
444         
445                         elem.animate(anim, 50, function(){
446                                 if ( t_w == "show" )
447                                         equals( this.style.display, "block", "Showing, display should block: " + this.style.display);
448                                         
449                                 if ( t_w == "hide"||t_w == "show" )
450                                         equals(this.style.width.indexOf(f_w), 0, "Width must be reset to " + f_w + ": " + this.style.width);
451                                         
452                                 if ( t_h == "hide"||t_h == "show" )
453                                         equals(this.style.height.indexOf(f_h), 0, "Height must be reset to " + f_h + ": " + this.style.height);
454                                         
455                                 var cur_o = jQuery.style(this, "opacity");
456                                 if ( cur_o !== "" ) cur_o = parseFloat( cur_o );
457         
458                                 if ( t_o == "hide"||t_o == "show" )
459                                         equals(cur_o, f_o, "Opacity must be reset to " + f_o + ": " + cur_o);
460                                         
461                                 if ( t_w == "hide" )
462                                         equals(this.style.display, "none", "Hiding, display should be none: " + this.style.display);
463                                         
464                                 if ( t_o.constructor == Number ) {
465                                         equals(cur_o, t_o, "Final opacity should be " + t_o + ": " + cur_o);
466                                         
467                                         ok(jQuery.curCSS(this, "opacity") != "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o);
468                                 }
469                                         
470                                 if ( t_w.constructor == Number ) {
471                                         equals(this.style.width, t_w + "px", "Final width should be " + t_w + ": " + this.style.width);
472                                         
473                                         var cur_w = jQuery.css(this,"width");
474
475                                         ok(this.style.width != "" || cur_w == t_w, "Width should be explicitly set to " + t_w + ", is instead: " + cur_w);
476                                 }
477                                         
478                                 if ( t_h.constructor == Number ) {
479                                         equals(this.style.height, t_h + "px", "Final height should be " + t_h + ": " + this.style.height);
480                                         
481                                         var cur_h = jQuery.css(this,"height");
482
483                                         ok(this.style.height != "" || cur_h == t_h, "Height should be explicitly set to " + t_h + ", is instead: " + cur_w);
484                                 }
485                                 
486                                 if ( t_h == "show" ) {
487                                         var old_h = jQuery.curCSS(this, "height");
488                                         jQuery(elem).append("<br/>Some more text<br/>and some more...");
489                                         ok(old_h != jQuery.css(this, "height" ), "Make sure height is auto.");
490                                 }
491         
492                                 start();
493                         });
494                 });
495         });
496 });
497
498 jQuery.fn.saveState = function(){
499         var check = ['opacity','height','width','display','overflow'];  
500         expect(check.length);
501         
502         stop();
503         return this.each(function(){
504                 var self = this;
505                 self.save = {};
506                 jQuery.each(check, function(i,c){
507                         self.save[c] = jQuery.css(self,c);
508                 });
509         });
510 };
511
512 jQuery.checkState = function(){
513         var self = this;
514         jQuery.each(this.save, function(c,v){
515                 var cur = jQuery.css(self,c);
516                 equals( v, cur, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")");
517         });
518         start();
519 }
520
521 // Chaining Tests
522 test("Chain fadeOut fadeIn", function() {
523         jQuery('#fadein div').saveState().fadeOut('fast').fadeIn('fast',jQuery.checkState);
524 });
525 test("Chain fadeIn fadeOut", function() {
526         jQuery('#fadeout div').saveState().fadeIn('fast').fadeOut('fast',jQuery.checkState);
527 });
528
529 test("Chain hide show", function() {
530         jQuery('#show div').saveState().hide('fast').show('fast',jQuery.checkState);
531 });
532 test("Chain show hide", function() {
533         jQuery('#hide div').saveState().show('fast').hide('fast',jQuery.checkState);
534 });
535
536 test("Chain toggle in", function() {
537         jQuery('#togglein div').saveState().toggle('fast').toggle('fast',jQuery.checkState);
538 });
539 test("Chain toggle out", function() {
540         jQuery('#toggleout div').saveState().toggle('fast').toggle('fast',jQuery.checkState);
541 });
542
543 test("Chain slideDown slideUp", function() {
544         jQuery('#slidedown div').saveState().slideDown('fast').slideUp('fast',jQuery.checkState);
545 });
546 test("Chain slideUp slideDown", function() {
547         jQuery('#slideup div').saveState().slideUp('fast').slideDown('fast',jQuery.checkState);
548 });
549
550 test("Chain slideToggle in", function() {
551         jQuery('#slidetogglein div').saveState().slideToggle('fast').slideToggle('fast',jQuery.checkState);
552 });
553 test("Chain slideToggle out", function() {
554         jQuery('#slidetoggleout div').saveState().slideToggle('fast').slideToggle('fast',jQuery.checkState);
555 });
556
557 jQuery.makeTest = function( text ){
558         var elem = jQuery("<div></div>")
559                 .attr("id", "test" + jQuery.makeTest.id++)
560                 .addClass("box");
561
562         jQuery("<h4></h4>")
563                 .text( text )
564                 .appendTo("#fx-tests")
565                 .click(function(){
566                         jQuery(this).next().toggle();
567                 })
568                 .after( elem );
569
570         return elem;
571 }
572
573 jQuery.makeTest.id = 1;
574
575 test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function () {
576         expect(4);
577   stop();
578
579         var $checkedtest = jQuery("#checkedtest");
580         // IE6 was clearing "checked" in jQuery(elem).show("fast");
581         $checkedtest.hide().show("fast", function() {
582         ok( !! jQuery(":radio:first", $checkedtest).attr("checked"), "Check first radio still checked." );
583         ok( ! jQuery(":radio:last", $checkedtest).attr("checked"), "Check last radio still NOT checked." );
584         ok( !! jQuery(":checkbox:first", $checkedtest).attr("checked"), "Check first checkbox still checked." );
585         ok( ! jQuery(":checkbox:last", $checkedtest).attr("checked"), "Check last checkbox still NOT checked." );
586         start();
587         });
588 });
589
590 test("animate with per-property easing", function(){
591         
592         expect(3);
593         stop();
594         
595         var _test1_called = false;
596         var _test2_called = false;
597         var _default_test_called = false;
598         
599         jQuery.easing['_test1'] = function() {
600                 _test1_called = true;
601         };
602         
603         jQuery.easing['_test2'] = function() {
604                 _test2_called = true;
605         };
606         
607         jQuery.easing['_default_test'] = function() {
608                 _default_test_called = true;
609         };
610         
611         jQuery({a:0,b:0,c:0}).animate({
612                 a: [100, '_test1'],
613                 b: [100, '_test2'],
614                 c: 100
615         }, 400, '_default_test', function(){
616                 start();
617                 ok(_test1_called, "Easing function (1) called");
618                 ok(_test2_called, "Easing function (2) called");
619                 ok(_default_test_called, "Easing function (_default) called");
620         });
621         
622 });