0
|
1 define( [
|
|
2 "../core",
|
|
3 "../core/camelCase",
|
|
4 "../var/rnothtmlwhite",
|
|
5 "./var/acceptData"
|
|
6 ], function( jQuery, camelCase, rnothtmlwhite, acceptData ) {
|
|
7
|
|
8 "use strict";
|
|
9
|
|
10 function Data() {
|
|
11 this.expando = jQuery.expando + Data.uid++;
|
|
12 }
|
|
13
|
|
14 Data.uid = 1;
|
|
15
|
|
16 Data.prototype = {
|
|
17
|
|
18 cache: function( owner ) {
|
|
19
|
|
20 // Check if the owner object already has a cache
|
|
21 var value = owner[ this.expando ];
|
|
22
|
|
23 // If not, create one
|
|
24 if ( !value ) {
|
|
25 value = {};
|
|
26
|
|
27 // We can accept data for non-element nodes in modern browsers,
|
|
28 // but we should not, see #8335.
|
|
29 // Always return an empty object.
|
|
30 if ( acceptData( owner ) ) {
|
|
31
|
|
32 // If it is a node unlikely to be stringify-ed or looped over
|
|
33 // use plain assignment
|
|
34 if ( owner.nodeType ) {
|
|
35 owner[ this.expando ] = value;
|
|
36
|
|
37 // Otherwise secure it in a non-enumerable property
|
|
38 // configurable must be true to allow the property to be
|
|
39 // deleted when data is removed
|
|
40 } else {
|
|
41 Object.defineProperty( owner, this.expando, {
|
|
42 value: value,
|
|
43 configurable: true
|
|
44 } );
|
|
45 }
|
|
46 }
|
|
47 }
|
|
48
|
|
49 return value;
|
|
50 },
|
|
51 set: function( owner, data, value ) {
|
|
52 var prop,
|
|
53 cache = this.cache( owner );
|
|
54
|
|
55 // Handle: [ owner, key, value ] args
|
|
56 // Always use camelCase key (gh-2257)
|
|
57 if ( typeof data === "string" ) {
|
|
58 cache[ camelCase( data ) ] = value;
|
|
59
|
|
60 // Handle: [ owner, { properties } ] args
|
|
61 } else {
|
|
62
|
|
63 // Copy the properties one-by-one to the cache object
|
|
64 for ( prop in data ) {
|
|
65 cache[ camelCase( prop ) ] = data[ prop ];
|
|
66 }
|
|
67 }
|
|
68 return cache;
|
|
69 },
|
|
70 get: function( owner, key ) {
|
|
71 return key === undefined ?
|
|
72 this.cache( owner ) :
|
|
73
|
|
74 // Always use camelCase key (gh-2257)
|
|
75 owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
|
|
76 },
|
|
77 access: function( owner, key, value ) {
|
|
78
|
|
79 // In cases where either:
|
|
80 //
|
|
81 // 1. No key was specified
|
|
82 // 2. A string key was specified, but no value provided
|
|
83 //
|
|
84 // Take the "read" path and allow the get method to determine
|
|
85 // which value to return, respectively either:
|
|
86 //
|
|
87 // 1. The entire cache object
|
|
88 // 2. The data stored at the key
|
|
89 //
|
|
90 if ( key === undefined ||
|
|
91 ( ( key && typeof key === "string" ) && value === undefined ) ) {
|
|
92
|
|
93 return this.get( owner, key );
|
|
94 }
|
|
95
|
|
96 // When the key is not a string, or both a key and value
|
|
97 // are specified, set or extend (existing objects) with either:
|
|
98 //
|
|
99 // 1. An object of properties
|
|
100 // 2. A key and value
|
|
101 //
|
|
102 this.set( owner, key, value );
|
|
103
|
|
104 // Since the "set" path can have two possible entry points
|
|
105 // return the expected data based on which path was taken[*]
|
|
106 return value !== undefined ? value : key;
|
|
107 },
|
|
108 remove: function( owner, key ) {
|
|
109 var i,
|
|
110 cache = owner[ this.expando ];
|
|
111
|
|
112 if ( cache === undefined ) {
|
|
113 return;
|
|
114 }
|
|
115
|
|
116 if ( key !== undefined ) {
|
|
117
|
|
118 // Support array or space separated string of keys
|
|
119 if ( Array.isArray( key ) ) {
|
|
120
|
|
121 // If key is an array of keys...
|
|
122 // We always set camelCase keys, so remove that.
|
|
123 key = key.map( camelCase );
|
|
124 } else {
|
|
125 key = camelCase( key );
|
|
126
|
|
127 // If a key with the spaces exists, use it.
|
|
128 // Otherwise, create an array by matching non-whitespace
|
|
129 key = key in cache ?
|
|
130 [ key ] :
|
|
131 ( key.match( rnothtmlwhite ) || [] );
|
|
132 }
|
|
133
|
|
134 i = key.length;
|
|
135
|
|
136 while ( i-- ) {
|
|
137 delete cache[ key[ i ] ];
|
|
138 }
|
|
139 }
|
|
140
|
|
141 // Remove the expando if there's no more data
|
|
142 if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
|
|
143
|
|
144 // Support: Chrome <=35 - 45
|
|
145 // Webkit & Blink performance suffers when deleting properties
|
|
146 // from DOM nodes, so set to undefined instead
|
|
147 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
|
|
148 if ( owner.nodeType ) {
|
|
149 owner[ this.expando ] = undefined;
|
|
150 } else {
|
|
151 delete owner[ this.expando ];
|
|
152 }
|
|
153 }
|
|
154 },
|
|
155 hasData: function( owner ) {
|
|
156 var cache = owner[ this.expando ];
|
|
157 return cache !== undefined && !jQuery.isEmptyObject( cache );
|
|
158 }
|
|
159 };
|
|
160
|
|
161 return Data;
|
|
162 } );
|