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