bd34c3094f1c7e35da90bd573b3275699797d8b3
[jquery.git] / fx / fx.js
1 jQuery.fn.extend({
2
3         // overwrite the old show method
4         _show: jQuery.fn.show,
5         
6         /**
7          * The effects module overloads the show method to now allow 
8          * for a speed to the show operation. What actually happens is 
9          * that the height, width, and opacity to the matched elements 
10          * are changed dynamically. The only three current speeds are 
11          * "slow", "normal", and "fast". For example:
12          *   $("p").show("slow");
13          * Note: You should not run the show method on things 
14          * that are already shown. This can be circumvented by doing this:
15          *   $("p:hidden").show("slow");
16          */
17         show: function(speed,callback){
18                 return speed ? this.animate({
19                         height: "show", width: "show", opacity: "show"
20                 }, speed, callback) : this._show();
21         },
22         
23         // Overwrite the old hide method
24         _hide: jQuery.fn.hide,
25         
26         /**
27          * The hide function behaves very similary to the show function, 
28          * but is just the opposite.
29          *   $("p:visible").hide("slow");
30          */
31         hide: function(speed,callback){
32                 return speed ? this.animate({
33                         height: "hide", width: "hide", opacity: "hide"
34                 }, speed, callback) : this._hide();
35         },
36         
37         /**
38          * This function increases the height and opacity for all matched 
39          * elements. This is very similar to 'show', but does not change 
40          * the width - creating a neat sliding effect.
41          *   $("p:hidden").slideDown("slow");
42          */
43         slideDown: function(speed,callback){
44                 return this.animate({height: "show"}, speed, callback);
45         },
46         
47         /**
48          * Just like slideDown, only it hides all matched elements.
49          *   $("p:visible").slideUp("slow");
50          */
51         slideUp: function(speed,callback){
52                 return this.animate({height: "hide"}, speed, callback);
53         },
54         
55         /**
56          * Adjusts the opacity of all matched elements from a hidden, 
57          * to a fully visible, state.
58          *   $("p:hidden").fadeIn("slow");
59          */
60         fadeIn: function(speed,callback){
61                 return this.animate({opacity: "show"}, speed, callback);
62         },
63         
64         /**
65          * Same as fadeIn, but transitions from a visible, to a hidden state.
66          *   $("p:visible").fadeOut("slow");
67          */
68         fadeOut: function(speed,callback){
69                 return this.animate({opacity: "hide"}, speed, callback);
70         },
71         
72         /**
73          * ...
74          */
75         fadeTo: function(speed,to,callback){
76                 return this.animate({opacity: to}, speed, callback);
77         },
78         
79         /**
80          *
81          */
82         animate: function(prop,speed,callback) {
83                 return this.queue(function(){
84                         var i = 0;
85                         for ( var p in prop ) {
86                                 var e = new jQuery.fx( this, jQuery.speed(speed,callback,i++), p );
87                                 if ( prop[p].constructor == Number )
88                                         e.custom( e.cur(), prop[p] );
89                                 else
90                                         e[ prop[p] ]();
91                         }
92                 });
93         },
94         
95         /**
96          *
97          * @private
98          */
99         queue: function(type,fn){
100                 if ( !fn ) {
101                         fn = type;
102                         type = "fx";
103                 }
104         
105                 return this.each(function(){
106                         if ( !this.queue )
107                                 this.queue = {};
108         
109                         if ( !this.queue[type] )
110                                 this.queue[type] = [];
111         
112                         this.queue[type].push( fn );
113                 
114                         if ( this.queue[type].length == 1 )
115                                 fn.apply(this);
116                 });
117         }
118
119 });
120
121 jQuery.extend({
122
123         setAuto: function(e,p) {
124                 // Remember the original height
125                 var a = e.style[p];
126
127                 // Figure out the size of the height right now
128                 var o = jQuery.curCSS(e,p,1);
129
130                 // Set the height to auto
131                 e.style[p] = e.currentStyle ? "" : "auto";
132
133                 // See what the size of "auto" is
134                 var n = jQuery.curCSS(e,p,1);
135
136                 // Revert back to the original size
137                 if ( o != n && n != "auto" ) e.style[p] = a;
138         },
139         
140         speed: function(s,o,i) {
141                 o = o || {};
142                 
143                 if ( o.constructor == Function )
144                         o = { complete: o };
145                 
146                 var ss = { slow: 600, fast: 200 };
147                 o.duration = (s && s.constructor == Number ? s : ss[s]) || 400;
148         
149                 // Queueing
150                 o.oldComplete = o.complete;
151                 o.complete = function(){
152                         jQuery.dequeue(this, "fx");
153                         if ( o.oldComplete && o.oldComplete.constructor == Function )
154                                 o.oldComplete.apply( this );
155                 };
156                 
157                 if ( i > 0 )
158                         o.complete = null;
159         
160                 return o;
161         },
162         
163         queue: {},
164         
165         dequeue: function(elem,type){
166                 type = type || "fx";
167         
168                 if ( elem.queue && elem.queue[type] ) {
169                         // Remove self
170                         elem.queue[type].shift();
171         
172                         // Get next function
173                         var f = elem.queue[type][0];
174                 
175                         if ( f )
176                                 f.apply( elem );
177                 }
178         },
179
180         /*
181          * I originally wrote fx() as a clone of moo.fx and in the process
182          * of making it small in size the code became illegible to sane
183          * people. You've been warned.
184          */
185         
186         fx: function( elem, options, prop ){
187         
188                 var z = this;
189         
190                 // The users options
191                 z.o = {
192                         duration: options.duration || 400,
193                         complete: options.complete
194                 };
195         
196                 // The element
197                 z.el = elem;
198         
199                 // The styles
200                 var y = z.el.style;
201         
202                 // Simple function for setting a style value
203                 z.a = function(){
204                         if ( prop == "opacity" ) {
205                                 if (z.now == 1) z.now = 0.9999;
206                                 if (window.ActiveXObject)
207                                         y.filter = "alpha(opacity=" + z.now*100 + ")";
208                                 y.opacity = z.now;
209
210                         // My hate for IE will never die
211                         } else if ( parseInt(z.now) )
212                                         y[prop] = parseInt(z.now) + "px";
213                 };
214         
215                 // Figure out the maximum number to run to
216                 z.max = function(){
217                         return parseFloat( jQuery.css(z.el,prop) );
218                 };
219         
220                 // Get the current size
221                 z.cur = function(){
222                         return parseFloat( jQuery.curCSS(z.el,prop) ) || z.max();
223                 };
224         
225                 // Start an animation from one number to another
226                 z.custom = function(from,to){
227                         z.startTime = (new Date()).getTime();
228                         z.now = from;
229                         z.a();
230         
231                         z.timer = setInterval(function(){
232                                 z.step(from, to);
233                         }, 13);
234                 };
235         
236                 // Simple 'show' function
237                 z.show = function(){
238                         if ( !z.el.orig ) z.el.orig = {};
239
240                         // Remember where we started, so that we can go back to it later
241                         z.el.orig[prop] = this.cur();
242
243                         if ( !y[prop] ) z.o.auto = true;
244
245                         z.custom(0,z.max());
246
247                         // Stupid IE, look what you made me do
248                         if ( prop != "opacity" )
249                                 y[prop] = "1px";
250
251                         y.display = "block";
252                 };
253         
254                 // Simple 'hide' function
255                 z.hide = function(){
256                         if ( !z.el.orig ) z.el.orig = {};
257
258                         // Remember where we started, so that we can go back to it later
259                         z.el.orig[prop] = this.cur();
260
261                         z.o.hide = true;
262
263                         // Begin the animation
264                         z.custom(z.cur(),0);
265                 };
266         
267                 // IE has trouble with opacity if it does not have layout
268                 if ( jQuery.browser.msie && !z.el.currentStyle.hasLayout )
269                         y.zoom = 1;
270         
271                 // Remember  the overflow of the element
272                 z.oldOverflow = y.overflow;
273         
274                 // Make sure that nothing sneaks out
275                 y.overflow = "hidden";
276         
277                 // Each step of an animation
278                 z.step = function(firstNum, lastNum){
279                         var t = (new Date()).getTime();
280         
281                         if (t > z.o.duration + z.startTime) {
282                                 // Stop the timer
283                                 clearInterval(z.timer);
284                                 z.timer = null;
285
286                                 z.now = lastNum;
287                                 z.a();
288
289                                 // Hide the element if the "hide" operation was done
290                                 if ( z.o.hide ) y.display = 'none';
291         
292                                 // Reset the overflow
293                                 y.overflow = z.oldOverflow;
294
295                                 // If a callback was provided, execute it
296                                 if( z.o.complete && z.o.complete.constructor == Function )
297                                         // Execute the complete function
298                                         z.o.complete.apply( z.el );
299
300                                 // Reset the property, if the item has been hidden
301                                 if ( z.o.hide )
302                                         y[ prop ] = z.el.orig[ prop ].constructor == Number && prop != "opacity" ? z.el.orig[prop] + "px" : z.el.orig[prop];
303
304                                 // set its height and/or width to auto
305                                 jQuery.setAuto( z.el, prop );
306                         } else {
307                                 // Figure out where in the animation we are and set the number
308                                 var p = (t - this.startTime) / z.o.duration;
309                                 z.now = ((-Math.cos(p*Math.PI)/2) + 0.5) * (lastNum-firstNum) + firstNum;
310         
311                                 // Perform the next step of the animation
312                                 z.a();
313                         }
314                 };
315         
316         }
317
318 });