Project

General

Profile

1
define([
2
	"./core",
3
	"./var/rnotwhite",
4
	"./core/access",
5
	"./data/var/data_priv",
6
	"./data/var/data_user"
7
], function( jQuery, rnotwhite, access, data_priv, data_user ) {
8

    
9
//	Implementation Summary
10
//
11
//	1. Enforce API surface and semantic compatibility with 1.9.x branch
12
//	2. Improve the module's maintainability by reducing the storage
13
//		paths to a single mechanism.
14
//	3. Use the same single mechanism to support "private" and "user" data.
15
//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
16
//	5. Avoid exposing implementation details on user objects (eg. expando properties)
17
//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
18

    
19
var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
20
	rmultiDash = /([A-Z])/g;
21

    
22
function dataAttr( elem, key, data ) {
23
	var name;
24

    
25
	// If nothing was found internally, try to fetch any
26
	// data from the HTML5 data-* attribute
27
	if ( data === undefined && elem.nodeType === 1 ) {
28
		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
29
		data = elem.getAttribute( name );
30

    
31
		if ( typeof data === "string" ) {
32
			try {
33
				data = data === "true" ? true :
34
					data === "false" ? false :
35
					data === "null" ? null :
36
					// Only convert to a number if it doesn't change the string
37
					+data + "" === data ? +data :
38
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
39
					data;
40
			} catch( e ) {}
41

    
42
			// Make sure we set the data so it isn't changed later
43
			data_user.set( elem, key, data );
44
		} else {
45
			data = undefined;
46
		}
47
	}
48
	return data;
49
}
50

    
51
jQuery.extend({
52
	hasData: function( elem ) {
53
		return data_user.hasData( elem ) || data_priv.hasData( elem );
54
	},
55

    
56
	data: function( elem, name, data ) {
57
		return data_user.access( elem, name, data );
58
	},
59

    
60
	removeData: function( elem, name ) {
61
		data_user.remove( elem, name );
62
	},
63

    
64
	// TODO: Now that all calls to _data and _removeData have been replaced
65
	// with direct calls to data_priv methods, these can be deprecated.
66
	_data: function( elem, name, data ) {
67
		return data_priv.access( elem, name, data );
68
	},
69

    
70
	_removeData: function( elem, name ) {
71
		data_priv.remove( elem, name );
72
	}
73
});
74

    
75
jQuery.fn.extend({
76
	data: function( key, value ) {
77
		var i, name, data,
78
			elem = this[ 0 ],
79
			attrs = elem && elem.attributes;
80

    
81
		// Gets all values
82
		if ( key === undefined ) {
83
			if ( this.length ) {
84
				data = data_user.get( elem );
85

    
86
				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
87
					i = attrs.length;
88
					while ( i-- ) {
89

    
90
						// Support: IE11+
91
						// The attrs elements can be null (#14894)
92
						if ( attrs[ i ] ) {
93
							name = attrs[ i ].name;
94
							if ( name.indexOf( "data-" ) === 0 ) {
95
								name = jQuery.camelCase( name.slice(5) );
96
								dataAttr( elem, name, data[ name ] );
97
							}
98
						}
99
					}
100
					data_priv.set( elem, "hasDataAttrs", true );
101
				}
102
			}
103

    
104
			return data;
105
		}
106

    
107
		// Sets multiple values
108
		if ( typeof key === "object" ) {
109
			return this.each(function() {
110
				data_user.set( this, key );
111
			});
112
		}
113

    
114
		return access( this, function( value ) {
115
			var data,
116
				camelKey = jQuery.camelCase( key );
117

    
118
			// The calling jQuery object (element matches) is not empty
119
			// (and therefore has an element appears at this[ 0 ]) and the
120
			// `value` parameter was not undefined. An empty jQuery object
121
			// will result in `undefined` for elem = this[ 0 ] which will
122
			// throw an exception if an attempt to read a data cache is made.
123
			if ( elem && value === undefined ) {
124
				// Attempt to get data from the cache
125
				// with the key as-is
126
				data = data_user.get( elem, key );
127
				if ( data !== undefined ) {
128
					return data;
129
				}
130

    
131
				// Attempt to get data from the cache
132
				// with the key camelized
133
				data = data_user.get( elem, camelKey );
134
				if ( data !== undefined ) {
135
					return data;
136
				}
137

    
138
				// Attempt to "discover" the data in
139
				// HTML5 custom data-* attrs
140
				data = dataAttr( elem, camelKey, undefined );
141
				if ( data !== undefined ) {
142
					return data;
143
				}
144

    
145
				// We tried really hard, but the data doesn't exist.
146
				return;
147
			}
148

    
149
			// Set the data...
150
			this.each(function() {
151
				// First, attempt to store a copy or reference of any
152
				// data that might've been store with a camelCased key.
153
				var data = data_user.get( this, camelKey );
154

    
155
				// For HTML5 data-* attribute interop, we have to
156
				// store property names with dashes in a camelCase form.
157
				// This might not apply to all properties...*
158
				data_user.set( this, camelKey, value );
159

    
160
				// *... In the case of properties that might _actually_
161
				// have dashes, we need to also store a copy of that
162
				// unchanged property.
163
				if ( key.indexOf("-") !== -1 && data !== undefined ) {
164
					data_user.set( this, key, value );
165
				}
166
			});
167
		}, null, value, arguments.length > 1, null, true );
168
	},
169

    
170
	removeData: function( key ) {
171
		return this.each(function() {
172
			data_user.remove( this, key );
173
		});
174
	}
175
});
176

    
177
return jQuery;
178
});
(6-6/23)