Tests: include github ref in concurrency group
[jquery.git] / src / data.js
blobce2813e972216bee23eb95873d41a48ff9eff5f2
1 import { jQuery } from "./core.js";
2 import { access } from "./core/access.js";
3 import { camelCase } from "./core/camelCase.js";
4 import { dataPriv } from "./data/var/dataPriv.js";
5 import { dataUser } from "./data/var/dataUser.js";
7 //      Implementation Summary
8 //
9 //      1. Enforce API surface and semantic compatibility with 1.9.x branch
10 //      2. Improve the module's maintainability by reducing the storage
11 //              paths to a single mechanism.
12 //      3. Use the same single mechanism to support "private" and "user" data.
13 //      4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
14 //      5. Avoid exposing implementation details on user objects (eg. expando properties)
15 //      6. Provide a clear path for implementation upgrade to WeakMap in 2014
17 var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
18         rmultiDash = /[A-Z]/g;
20 function getData( data ) {
21         if ( data === "true" ) {
22                 return true;
23         }
25         if ( data === "false" ) {
26                 return false;
27         }
29         if ( data === "null" ) {
30                 return null;
31         }
33         // Only convert to a number if it doesn't change the string
34         if ( data === +data + "" ) {
35                 return +data;
36         }
38         if ( rbrace.test( data ) ) {
39                 return JSON.parse( data );
40         }
42         return data;
45 function dataAttr( elem, key, data ) {
46         var name;
48         // If nothing was found internally, try to fetch any
49         // data from the HTML5 data-* attribute
50         if ( data === undefined && elem.nodeType === 1 ) {
51                 name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
52                 data = elem.getAttribute( name );
54                 if ( typeof data === "string" ) {
55                         try {
56                                 data = getData( data );
57                         } catch ( e ) {}
59                         // Make sure we set the data so it isn't changed later
60                         dataUser.set( elem, key, data );
61                 } else {
62                         data = undefined;
63                 }
64         }
65         return data;
68 jQuery.extend( {
69         hasData: function( elem ) {
70                 return dataUser.hasData( elem ) || dataPriv.hasData( elem );
71         },
73         data: function( elem, name, data ) {
74                 return dataUser.access( elem, name, data );
75         },
77         removeData: function( elem, name ) {
78                 dataUser.remove( elem, name );
79         },
81         // TODO: Now that all calls to _data and _removeData have been replaced
82         // with direct calls to dataPriv methods, these can be deprecated.
83         _data: function( elem, name, data ) {
84                 return dataPriv.access( elem, name, data );
85         },
87         _removeData: function( elem, name ) {
88                 dataPriv.remove( elem, name );
89         }
90 } );
92 jQuery.fn.extend( {
93         data: function( key, value ) {
94                 var i, name, data,
95                         elem = this[ 0 ],
96                         attrs = elem && elem.attributes;
98                 // Gets all values
99                 if ( key === undefined ) {
100                         if ( this.length ) {
101                                 data = dataUser.get( elem );
103                                 if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
104                                         i = attrs.length;
105                                         while ( i-- ) {
107                                                 // Support: IE 11+
108                                                 // The attrs elements can be null (trac-14894)
109                                                 if ( attrs[ i ] ) {
110                                                         name = attrs[ i ].name;
111                                                         if ( name.indexOf( "data-" ) === 0 ) {
112                                                                 name = camelCase( name.slice( 5 ) );
113                                                                 dataAttr( elem, name, data[ name ] );
114                                                         }
115                                                 }
116                                         }
117                                         dataPriv.set( elem, "hasDataAttrs", true );
118                                 }
119                         }
121                         return data;
122                 }
124                 // Sets multiple values
125                 if ( typeof key === "object" ) {
126                         return this.each( function() {
127                                 dataUser.set( this, key );
128                         } );
129                 }
131                 return access( this, function( value ) {
132                         var data;
134                         // The calling jQuery object (element matches) is not empty
135                         // (and therefore has an element appears at this[ 0 ]) and the
136                         // `value` parameter was not undefined. An empty jQuery object
137                         // will result in `undefined` for elem = this[ 0 ] which will
138                         // throw an exception if an attempt to read a data cache is made.
139                         if ( elem && value === undefined ) {
141                                 // Attempt to get data from the cache
142                                 // The key will always be camelCased in Data
143                                 data = dataUser.get( elem, key );
144                                 if ( data !== undefined ) {
145                                         return data;
146                                 }
148                                 // Attempt to "discover" the data in
149                                 // HTML5 custom data-* attrs
150                                 data = dataAttr( elem, key );
151                                 if ( data !== undefined ) {
152                                         return data;
153                                 }
155                                 // We tried really hard, but the data doesn't exist.
156                                 return;
157                         }
159                         // Set the data...
160                         this.each( function() {
162                                 // We always store the camelCased key
163                                 dataUser.set( this, key, value );
164                         } );
165                 }, null, value, arguments.length > 1, null, true );
166         },
168         removeData: function( key ) {
169                 return this.each( function() {
170                         dataUser.remove( this, key );
171                 } );
172         }
173 } );
175 export { jQuery, jQuery as $ };