avoid creating a new data cache if we don't need one. Also, short-circuit the case...
[jquery.git] / src / data.js
1 var expando = "jQuery" + now(), uuid = 0, windowData = {};\r
2 var emptyObject = {};\r
3 \r
4 jQuery.extend({\r
5         cache: {},\r
6         \r
7         expando:expando,\r
8 \r
9         data: function( elem, name, data ) {\r
10                 elem = elem == window ?\r
11                         windowData :\r
12                         elem;\r
13 \r
14                 var id = elem[ expando ], cache = jQuery.cache, thisCache;\r
15 \r
16                 // Compute a unique ID for the element\r
17                 if(!id) id = elem[ expando ] = ++uuid;\r
18 \r
19                 // Handle the case where there's no name immediately\r
20                 if ( !name ) { return id; }\r
21 \r
22                 // Avoid generating a new cache unless none exists and we\r
23                 // want to manipulate it.\r
24                 if( cache[ id ] )\r
25                         thisCache = cache[ id ];\r
26                 else if( typeof data === "undefined" )\r
27                         thisCache = emptyObject;\r
28                 else\r
29                         thisCache = cache[ id ] = {};\r
30                 \r
31                 // Prevent overriding the named cache with undefined values\r
32                 if ( data !== undefined ) thisCache[ name ] = data;\r
33 \r
34                 if(name === true) return thisCache;\r
35                 else return thisCache[name];\r
36         },\r
37 \r
38         removeData: function( elem, name ) {\r
39                 elem = elem == window ?\r
40                         windowData :\r
41                         elem;\r
42 \r
43                 var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];\r
44 \r
45                 // If we want to remove a specific section of the element's data\r
46                 if ( name ) {\r
47                         if ( thisCache ) {\r
48                                 // Remove the section of cache data\r
49                                 delete thisCache[ name ];\r
50 \r
51                                 // If we've removed all the data, remove the element's cache\r
52                                 if( jQuery.isEmptyObject(thisCache) )\r
53                                         jQuery.removeData( elem );\r
54                         }\r
55 \r
56                 // Otherwise, we want to remove all of the element's data\r
57                 } else {\r
58                         // Clean up the element expando\r
59                         try {\r
60                                 delete elem[ expando ];\r
61                         } catch(e){\r
62                                 // IE has trouble directly removing the expando\r
63                                 // but it's ok with using removeAttribute\r
64                                 if ( elem.removeAttribute )\r
65                                         elem.removeAttribute( expando );\r
66                         }\r
67 \r
68                         // Completely remove the data cache\r
69                         delete cache[ id ];\r
70                 }\r
71         },\r
72         queue: function( elem, type, data ) {\r
73                 if( !elem ) return;\r
74 \r
75                 type = (type || "fx") + "queue";\r
76                 var q = jQuery.data( elem, type );\r
77 \r
78                 // Speed up dequeue by getting out quickly if this is just a lookup\r
79                 if( !data ) return q || [];\r
80 \r
81                 if ( !q || jQuery.isArray(data) )\r
82                         q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
83                 else\r
84                         q.push( data );\r
85 \r
86                 return q;\r
87         },\r
88 \r
89         dequeue: function( elem, type ){\r
90                 type = type || "fx";\r
91 \r
92                 var queue = jQuery.queue( elem, type ), fn = queue.shift();\r
93 \r
94                 // If the fx queue is dequeued, always remove the progress sentinel\r
95                 if( fn === "inprogress" ) fn = queue.shift();\r
96 \r
97                 if( fn ) {\r
98                         // Add a progress sentinel to prevent the fx queue from being\r
99                         // automatically dequeued\r
100                         if( type == "fx" ) queue.unshift("inprogress");\r
101 \r
102                         fn.call(elem, function() { jQuery.dequeue(elem, type); });\r
103                 }\r
104         }\r
105 });\r
106 \r
107 jQuery.fn.extend({\r
108         data: function( key, value ){\r
109                 if(typeof key === "undefined" && this.length) return jQuery.data(this[0], true);\r
110 \r
111                 var parts = key.split(".");\r
112                 parts[1] = parts[1] ? "." + parts[1] : "";\r
113 \r
114                 if ( value === undefined ) {\r
115                         var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);\r
116 \r
117                         if ( data === undefined && this.length )\r
118                                 data = jQuery.data( this[0], key );\r
119 \r
120                         return data === undefined && parts[1] ?\r
121                                 this.data( parts[0] ) :\r
122                                 data;\r
123                 } else\r
124                         return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){\r
125                                 jQuery.data( this, key, value );\r
126                         });\r
127         },\r
128 \r
129         removeData: function( key ){\r
130                 return this.each(function(){\r
131                         jQuery.removeData( this, key );\r
132                 });\r
133         },\r
134         queue: function(type, data){\r
135                 if ( typeof type !== "string" ) {\r
136                         data = type;\r
137                         type = "fx";\r
138                 }\r
139 \r
140                 if ( data === undefined )\r
141                         return jQuery.queue( this[0], type );\r
142 \r
143                 return this.each(function(i, elem){\r
144                         var queue = jQuery.queue( this, type, data );\r
145 \r
146                         if( type == "fx" && queue[0] !== "inprogress" )\r
147                                 jQuery.dequeue( this, type )\r
148                 });\r
149         },\r
150         dequeue: function(type){\r
151                 return this.each(function(){\r
152                         jQuery.dequeue( this, type );\r
153                 });\r
154         },\r
155         clearQueue: function(type){\r
156                 return this.queue( type || "fx", [] );\r
157         }\r
158 });