A follow-up to [6578] (which stopped adding expandos to elements that didn't have...
[jquery.git] / src / data.js
index ac069ce..500f7ea 100644 (file)
@@ -1,32 +1,45 @@
 var expando = "jQuery" + now(), uuid = 0, windowData = {};\r
+var emptyObject = {};\r
 \r
 jQuery.extend({\r
        cache: {},\r
+       \r
+       expando:expando,\r
 \r
        data: function( elem, name, data ) {\r
                elem = elem == window ?\r
                        windowData :\r
                        elem;\r
 \r
-               var id = elem[ expando ];\r
+               var id = elem[ expando ], cache = jQuery.cache, thisCache;\r
 \r
-               // Compute a unique ID for the element\r
-               if ( !id )\r
-                       id = elem[ expando ] = ++uuid;\r
+               // Handle the case where there's no name immediately\r
+               if ( !name && !id ) {\r
+                       return null;\r
+               }\r
 \r
-               // Only generate the data cache if we're\r
-               // trying to access or manipulate it\r
-               if ( name && !jQuery.cache[ id ] )\r
-                       jQuery.cache[ id ] = {};\r
+               // Compute a unique ID for the element\r
+               if ( !id ) { \r
+                       id = ++uuid;\r
+               }\r
 \r
+               // Avoid generating a new cache unless none exists and we\r
+               // want to manipulate it.\r
+               if ( cache[ id ] ) {\r
+                       thisCache = cache[ id ];\r
+               } else if ( typeof data === "undefined" ) {\r
+                       thisCache = emptyObject;\r
+               } else {\r
+                       thisCache = cache[ id ] = {};\r
+               }\r
+               \r
                // Prevent overriding the named cache with undefined values\r
-               if ( data !== undefined )\r
-                       jQuery.cache[ id ][ name ] = data;\r
-\r
-               // Return the named cache data, or the ID for the element\r
-               return name ?\r
-                       jQuery.cache[ id ][ name ] :\r
-                       id;\r
+               if ( data !== undefined ) {\r
+                       elem[ expando ] = id;\r
+                       thisCache[ name ] = data;\r
+               }\r
+               \r
+               return name ? thisCache[ name ] : thisCache;\r
        },\r
 \r
        removeData: function( elem, name ) {\r
@@ -34,22 +47,18 @@ jQuery.extend({
                        windowData :\r
                        elem;\r
 \r
-               var id = elem[ expando ];\r
+               var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];\r
 \r
                // If we want to remove a specific section of the element's data\r
                if ( name ) {\r
-                       if ( jQuery.cache[ id ] ) {\r
+                       if ( thisCache ) {\r
                                // Remove the section of cache data\r
-                               delete jQuery.cache[ id ][ name ];\r
+                               delete thisCache[ name ];\r
 \r
                                // If we've removed all the data, remove the element's cache\r
-                               name = "";\r
-\r
-                               for ( name in jQuery.cache[ id ] )\r
-                                       break;\r
-\r
-                               if ( !name )\r
+                               if ( jQuery.isEmptyObject(thisCache) ) {\r
                                        jQuery.removeData( elem );\r
+                               }\r
                        }\r
 \r
                // Otherwise, we want to remove all of the element's data\r
@@ -57,47 +66,60 @@ jQuery.extend({
                        // Clean up the element expando\r
                        try {\r
                                delete elem[ expando ];\r
-                       } catch(e){\r
+                       } catch( e ) {\r
                                // IE has trouble directly removing the expando\r
                                // but it's ok with using removeAttribute\r
-                               if ( elem.removeAttribute )\r
+                               if ( elem.removeAttribute ) {\r
                                        elem.removeAttribute( expando );\r
+                               }\r
                        }\r
 \r
                        // Completely remove the data cache\r
-                       delete jQuery.cache[ id ];\r
+                       delete cache[ id ];\r
                }\r
        },\r
+       \r
        queue: function( elem, type, data ) {\r
-               if ( elem ){\r
+               if( !elem ) return;\r
 \r
-                       type = (type || "fx") + "queue";\r
+               type = (type || "fx") + "queue";\r
+               var q = jQuery.data( elem, type );\r
 \r
-                       var q = jQuery.data( elem, type );\r
+               // Speed up dequeue by getting out quickly if this is just a lookup\r
+               if( !data ) return q || [];\r
 \r
-                       if ( !q || jQuery.isArray(data) )\r
-                               q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
-                       else if( data )\r
-                               q.push( data );\r
+               if ( !q || jQuery.isArray(data) )\r
+                       q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
+               else\r
+                       q.push( data );\r
 \r
-               }\r
                return q;\r
        },\r
 \r
        dequeue: function( elem, type ){\r
-               var queue = jQuery.queue( elem, type ),\r
-                       fn = queue.shift();\r
+               type = type || "fx";\r
+\r
+               var queue = jQuery.queue( elem, type ), fn = queue.shift();\r
+\r
+               // If the fx queue is dequeued, always remove the progress sentinel\r
+               if( fn === "inprogress" ) fn = queue.shift();\r
 \r
-               if( !type || type === "fx" )\r
-                       fn = queue[0];\r
+               if( fn ) {\r
+                       // Add a progress sentinel to prevent the fx queue from being\r
+                       // automatically dequeued\r
+                       if( type == "fx" ) queue.unshift("inprogress");\r
 \r
-               if( fn !== undefined )\r
-                       fn.call(elem);\r
+                       fn.call(elem, function() { jQuery.dequeue(elem, type); });\r
+               }\r
        }\r
 });\r
 \r
 jQuery.fn.extend({\r
        data: function( key, value ){\r
+               if ( typeof key === "undefined" && this.length ) {\r
+                       return jQuery.data( this[0] );\r
+               }\r
+\r
                var parts = key.split(".");\r
                parts[1] = parts[1] ? "." + parts[1] : "";\r
 \r
@@ -130,16 +152,19 @@ jQuery.fn.extend({
                if ( data === undefined )\r
                        return jQuery.queue( this[0], type );\r
 \r
-               return this.each(function(){\r
+               return this.each(function(i, elem){\r
                        var queue = jQuery.queue( this, type, data );\r
 \r
-                        if( type == "fx" && queue.length == 1 )\r
-                               queue[0].call(this);\r
+                       if( type == "fx" && queue[0] !== "inprogress" )\r
+                               jQuery.dequeue( this, type )\r
                });\r
        },\r
        dequeue: function(type){\r
                return this.each(function(){\r
                        jQuery.dequeue( this, type );\r
                });\r
+       },\r
+       clearQueue: function(type){\r
+               return this.queue( type || "fx", [] );\r
        }\r
-});
\ No newline at end of file
+});\r