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