jquery data: Closes #3539. Exposed jQuery.queue. Moved all the data and queue functio...
[jquery.git] / src / fx.js
index 116711f..ae472ef 100644 (file)
--- a/src/fx.js
+++ b/src/fx.js
@@ -1,68 +1,74 @@
+var elemdisplay = {};
+
 jQuery.fn.extend({
        show: function(speed,callback){
-               return speed ?
-                       this.animate({
+               if ( speed ) {
+                       return this.animate({
                                height: "show", width: "show", opacity: "show"
-                       }, speed, callback) :
-
-                       this.filter(":hidden").each(function(){
-                               this.style.display = this.oldblock || "";
-                               if ( jQuery.css(this,"display") == "none" ) {
-                                       var elem = jQuery("<" + this.tagName + " />").appendTo("body");
-                                       this.style.display = elem.css("display");
-                                       // handle an edge condition where css is - div { display:none; } or similar
-                                       if (this.style.display == "none")
-                                               this.style.display = "block";
-                                       elem.remove();
+                       }, speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                               
+                               this[i].style.display = old || "";
+                               
+                               if ( jQuery.css(this[i], "display") === "none" ) {
+                                       var tagName = this[i].tagName, display;
+                                       
+                                       if ( elemdisplay[ tagName ] ) {
+                                               display = elemdisplay[ tagName ];
+                                       } else {
+                                               var elem = jQuery("<" + tagName + " />").appendTo("body");
+                                               
+                                               display = elem.css("display");
+                                               if ( display === "none" )
+                                                       display = "block";
+                                               
+                                               elem.remove();
+                                               
+                                               elemdisplay[ tagName ] = display;
+                                       }
+                                       
+                                       this[i].style.display = jQuery.data(this[i], "olddisplay", display);
                                }
-                       }).end();
+                       }
+                       
+                       return this;
+               }
        },
 
        hide: function(speed,callback){
-               return speed ?
-                       this.animate({
+               if ( speed ) {
+                       return this.animate({
                                height: "hide", width: "hide", opacity: "hide"
-                       }, speed, callback) :
-
-                       this.filter(":visible").each(function(){
-                               this.oldblock = this.oldblock || jQuery.css(this,"display");
-                               this.style.display = "none";
-                       }).end();
+                       }, speed, callback);
+               } else {
+                       for ( var i = 0, l = this.length; i < l; i++ ){
+                               var old = jQuery.data(this[i], "olddisplay");
+                               if ( !old && old !== "none" )
+                                       jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+                               this[i].style.display = "none";
+                       }
+                       return this;
+               }
        },
 
        // Save the old toggle function
        _toggle: jQuery.fn.toggle,
 
        toggle: function( fn, fn2 ){
+               var bool = typeof fn === "boolean";
+
                return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
                        this._toggle.apply( this, arguments ) :
-                       fn ?
+                       fn == null || bool ?
+                               this.each(function(){
+                                       var state = bool ? fn : jQuery(this).is(":hidden");
+                                       jQuery(this)[ state ? "show" : "hide" ]();
+                               }) :
                                this.animate({
                                        height: "toggle", width: "toggle", opacity: "toggle"
-                               }, fn, fn2) :
-                               this.each(function(){
-                                       jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
-                               });
-       },
-
-       slideDown: function(speed,callback){
-               return this.animate({height: "show"}, speed, callback);
-       },
-
-       slideUp: function(speed,callback){
-               return this.animate({height: "hide"}, speed, callback);
-       },
-
-       slideToggle: function(speed, callback){
-               return this.animate({height: "toggle"}, speed, callback);
-       },
-
-       fadeIn: function(speed, callback){
-               return this.animate({opacity: "show"}, speed, callback);
-       },
-
-       fadeOut: function(speed, callback){
-               return this.animate({opacity: "hide"}, speed, callback);
+                               }, fn, fn2);
        },
 
        fadeTo: function(speed,to,callback){
@@ -73,17 +79,16 @@ jQuery.fn.extend({
                var optall = jQuery.speed(speed, easing, callback);
 
                return this[ optall.queue === false ? "each" : "queue" ](function(){
-                       if ( this.nodeType != 1)
-                               return false;
-
+               
                        var opt = jQuery.extend({}, optall), p,
-                               hidden = jQuery(this).is(":hidden"), self = this;
-
+                               hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+                               self = this;
+       
                        for ( p in prop ) {
                                if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
                                        return opt.complete.call(this);
 
-                               if ( p == "height" || p == "width" ) {
+                               if ( ( p == "height" || p == "width" ) && this.style ) {
                                        // Store display property
                                        opt.display = jQuery.css(this, "display");
 
@@ -132,27 +137,6 @@ jQuery.fn.extend({
                });
        },
 
-       queue: function(type, fn){
-               if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
-                       fn = type;
-                       type = "fx";
-               }
-
-               if ( !type || (typeof type == "string" && !fn) )
-                       return queue( this[0], type );
-
-               return this.each(function(){
-                       if ( fn.constructor == Array )
-                               queue(this, type, fn);
-                       else {
-                               queue(this, type).push( fn );
-
-                               if ( queue(this, type).length == 1 )
-                                       fn.call(this);
-                       }
-               });
-       },
-
        stop: function(clearQueue, gotoEnd){
                var timers = jQuery.timers;
 
@@ -179,46 +163,31 @@ jQuery.fn.extend({
 
 });
 
-var queue = function( elem, type, array ) {
-       if ( elem ){
-
-               type = type || "fx";
-
-               var q = jQuery.data( elem, type + "queue" );
-
-               if ( !q || array )
-                       q = jQuery.data( elem, type + "queue", jQuery.makeArray(array) );
-
-       }
-       return q;
-};
-
-jQuery.fn.dequeue = function(type){
-       type = type || "fx";
-
-       return this.each(function(){
-               var q = queue(this, type);
-
-               q.shift();
-
-               if ( q.length )
-                       q[0].call( this );
-       });
-};
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: { height:"show" },
+       slideUp: { height: "hide" },
+       slideToggle: { height: "toggle" },
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" }
+}, function( name, props ){
+       jQuery.fn[ name ] = function( speed, callback ){
+               return this.animate( props, speed, callback );
+       };
+});
 
 jQuery.extend({
 
        speed: function(speed, easing, fn) {
-               var opt = speed && speed.constructor == Object ? speed : {
+               var opt = typeof speed === "object" ? speed : {
                        complete: fn || !fn && easing ||
                                jQuery.isFunction( speed ) && speed,
                        duration: speed,
-                       easing: fn && easing || easing && easing.constructor != Function && easing
+                       easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
                };
 
-               opt.duration = (opt.duration && opt.duration.constructor == Number ?
-                       opt.duration :
-                       jQuery.fx.speeds[opt.duration]) || jQuery.fx.speeds.def;
+               opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+                       jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
 
                // Queueing
                opt.old = opt.complete;
@@ -265,13 +234,13 @@ jQuery.fx.prototype = {
                (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
 
                // Set display property to block for height/width animations
-               if ( this.prop == "height" || this.prop == "width" )
+               if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
                        this.elem.style.display = "block";
        },
 
        // Get the current size
        cur: function(force){
-               if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
+               if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
                        return this.elem[ this.prop ];
 
                var r = parseFloat(jQuery.css(this.elem, this.prop, force));
@@ -286,7 +255,6 @@ jQuery.fx.prototype = {
                this.unit = unit || this.unit || "px";
                this.now = this.start;
                this.pos = this.state = 0;
-               this.update();
 
                var self = this;
                function t(gotoEnd){
@@ -297,7 +265,7 @@ jQuery.fx.prototype = {
 
                jQuery.timers.push(t);
 
-               if ( jQuery.timerId == null ) {
+               if ( t() && jQuery.timerId == null ) {
                        jQuery.timerId = setInterval(function(){
                                var timers = jQuery.timers;
 
@@ -345,7 +313,7 @@ jQuery.fx.prototype = {
        step: function(gotoEnd){
                var t = now();
 
-               if ( gotoEnd || t > this.options.duration + this.startTime ) {
+               if ( gotoEnd || t >= this.options.duration + this.startTime ) {
                        this.now = this.end;
                        this.pos = this.state = 1;
                        this.update();
@@ -378,7 +346,6 @@ jQuery.fx.prototype = {
                                                jQuery.attr(this.elem.style, p, this.options.orig[p]);
                        }
 
-                       // If a callback was provided, execute it
                        if ( done )
                                // Execute the complete function
                                this.options.complete.call( this.elem );
@@ -406,23 +373,19 @@ jQuery.extend( jQuery.fx, {
                slow: 600,
                fast: 200,
                // Default speed
-               def: 400
+               _default: 400
        },
        step: {
-               scrollLeft: function(fx){
-                       fx.elem.scrollLeft = fx.now;
-               },
-
-               scrollTop: function(fx){
-                       fx.elem.scrollTop = fx.now;
-               },
 
                opacity: function(fx){
                        jQuery.attr(fx.elem.style, "opacity", fx.now);
                },
 
                _default: function(fx){
-                       fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+                       if( fx.prop in fx.elem ) 
+                               fx.elem[ fx.prop ] = fx.now;
+                       else if( fx.elem.style )
+                               fx.elem.style[ fx.prop ] = fx.now + fx.unit;
                }
        }
 });