Project

General

Profile

1
define([
2
	"../core",
3
	"../var/rnotwhite",
4
	"./accepts"
5
], function( jQuery, rnotwhite ) {
6

    
7
function Data() {
8
	// Support: Android<4,
9
	// Old WebKit does not have Object.preventExtensions/freeze method,
10
	// return new empty object instead with no [[set]] accessor
11
	Object.defineProperty( this.cache = {}, 0, {
12
		get: function() {
13
			return {};
14
		}
15
	});
16

    
17
	this.expando = jQuery.expando + Data.uid++;
18
}
19

    
20
Data.uid = 1;
21
Data.accepts = jQuery.acceptData;
22

    
23
Data.prototype = {
24
	key: function( owner ) {
25
		// We can accept data for non-element nodes in modern browsers,
26
		// but we should not, see #8335.
27
		// Always return the key for a frozen object.
28
		if ( !Data.accepts( owner ) ) {
29
			return 0;
30
		}
31

    
32
		var descriptor = {},
33
			// Check if the owner object already has a cache key
34
			unlock = owner[ this.expando ];
35

    
36
		// If not, create one
37
		if ( !unlock ) {
38
			unlock = Data.uid++;
39

    
40
			// Secure it in a non-enumerable, non-writable property
41
			try {
42
				descriptor[ this.expando ] = { value: unlock };
43
				Object.defineProperties( owner, descriptor );
44

    
45
			// Support: Android<4
46
			// Fallback to a less secure definition
47
			} catch ( e ) {
48
				descriptor[ this.expando ] = unlock;
49
				jQuery.extend( owner, descriptor );
50
			}
51
		}
52

    
53
		// Ensure the cache object
54
		if ( !this.cache[ unlock ] ) {
55
			this.cache[ unlock ] = {};
56
		}
57

    
58
		return unlock;
59
	},
60
	set: function( owner, data, value ) {
61
		var prop,
62
			// There may be an unlock assigned to this node,
63
			// if there is no entry for this "owner", create one inline
64
			// and set the unlock as though an owner entry had always existed
65
			unlock = this.key( owner ),
66
			cache = this.cache[ unlock ];
67

    
68
		// Handle: [ owner, key, value ] args
69
		if ( typeof data === "string" ) {
70
			cache[ data ] = value;
71

    
72
		// Handle: [ owner, { properties } ] args
73
		} else {
74
			// Fresh assignments by object are shallow copied
75
			if ( jQuery.isEmptyObject( cache ) ) {
76
				jQuery.extend( this.cache[ unlock ], data );
77
			// Otherwise, copy the properties one-by-one to the cache object
78
			} else {
79
				for ( prop in data ) {
80
					cache[ prop ] = data[ prop ];
81
				}
82
			}
83
		}
84
		return cache;
85
	},
86
	get: function( owner, key ) {
87
		// Either a valid cache is found, or will be created.
88
		// New caches will be created and the unlock returned,
89
		// allowing direct access to the newly created
90
		// empty data object. A valid owner object must be provided.
91
		var cache = this.cache[ this.key( owner ) ];
92

    
93
		return key === undefined ?
94
			cache : cache[ key ];
95
	},
96
	access: function( owner, key, value ) {
97
		var stored;
98
		// In cases where either:
99
		//
100
		//   1. No key was specified
101
		//   2. A string key was specified, but no value provided
102
		//
103
		// Take the "read" path and allow the get method to determine
104
		// which value to return, respectively either:
105
		//
106
		//   1. The entire cache object
107
		//   2. The data stored at the key
108
		//
109
		if ( key === undefined ||
110
				((key && typeof key === "string") && value === undefined) ) {
111

    
112
			stored = this.get( owner, key );
113

    
114
			return stored !== undefined ?
115
				stored : this.get( owner, jQuery.camelCase(key) );
116
		}
117

    
118
		// [*]When the key is not a string, or both a key and value
119
		// are specified, set or extend (existing objects) with either:
120
		//
121
		//   1. An object of properties
122
		//   2. A key and value
123
		//
124
		this.set( owner, key, value );
125

    
126
		// Since the "set" path can have two possible entry points
127
		// return the expected data based on which path was taken[*]
128
		return value !== undefined ? value : key;
129
	},
130
	remove: function( owner, key ) {
131
		var i, name, camel,
132
			unlock = this.key( owner ),
133
			cache = this.cache[ unlock ];
134

    
135
		if ( key === undefined ) {
136
			this.cache[ unlock ] = {};
137

    
138
		} else {
139
			// Support array or space separated string of keys
140
			if ( jQuery.isArray( key ) ) {
141
				// If "name" is an array of keys...
142
				// When data is initially created, via ("key", "val") signature,
143
				// keys will be converted to camelCase.
144
				// Since there is no way to tell _how_ a key was added, remove
145
				// both plain key and camelCase key. #12786
146
				// This will only penalize the array argument path.
147
				name = key.concat( key.map( jQuery.camelCase ) );
148
			} else {
149
				camel = jQuery.camelCase( key );
150
				// Try the string as a key before any manipulation
151
				if ( key in cache ) {
152
					name = [ key, camel ];
153
				} else {
154
					// If a key with the spaces exists, use it.
155
					// Otherwise, create an array by matching non-whitespace
156
					name = camel;
157
					name = name in cache ?
158
						[ name ] : ( name.match( rnotwhite ) || [] );
159
				}
160
			}
161

    
162
			i = name.length;
163
			while ( i-- ) {
164
				delete cache[ name[ i ] ];
165
			}
166
		}
167
	},
168
	hasData: function( owner ) {
169
		return !jQuery.isEmptyObject(
170
			this.cache[ owner[ this.expando ] ] || {}
171
		);
172
	},
173
	discard: function( owner ) {
174
		if ( owner[ this.expando ] ) {
175
			delete this.cache[ owner[ this.expando ] ];
176
		}
177
	}
178
};
179

    
180
return Data;
181
});
(1-1/2)