| define( [ |
| "../core", |
| "../core/camelCase", |
| "../var/rnothtmlwhite", |
| "./var/acceptData" |
| ], function( jQuery, camelCase, rnothtmlwhite, acceptData ) { |
| |
| "use strict"; |
| |
| function Data() { |
| this.expando = jQuery.expando + Data.uid++; |
| } |
| |
| Data.uid = 1; |
| |
| Data.prototype = { |
| |
| cache: function( owner ) { |
| |
| // Check if the owner object already has a cache |
| var value = owner[ this.expando ]; |
| |
| // If not, create one |
| if ( !value ) { |
| value = {}; |
| |
| // We can accept data for non-element nodes in modern browsers, |
| // but we should not, see #8335. |
| // Always return an empty object. |
| if ( acceptData( owner ) ) { |
| |
| // If it is a node unlikely to be stringify-ed or looped over |
| // use plain assignment |
| if ( owner.nodeType ) { |
| owner[ this.expando ] = value; |
| |
| // Otherwise secure it in a non-enumerable property |
| // configurable must be true to allow the property to be |
| // deleted when data is removed |
| } else { |
| Object.defineProperty( owner, this.expando, { |
| value: value, |
| configurable: true |
| } ); |
| } |
| } |
| } |
| |
| return value; |
| }, |
| set: function( owner, data, value ) { |
| var prop, |
| cache = this.cache( owner ); |
| |
| // Handle: [ owner, key, value ] args |
| // Always use camelCase key (gh-2257) |
| if ( typeof data === "string" ) { |
| cache[ camelCase( data ) ] = value; |
| |
| // Handle: [ owner, { properties } ] args |
| } else { |
| |
| // Copy the properties one-by-one to the cache object |
| for ( prop in data ) { |
| cache[ camelCase( prop ) ] = data[ prop ]; |
| } |
| } |
| return cache; |
| }, |
| get: function( owner, key ) { |
| return key === undefined ? |
| this.cache( owner ) : |
| |
| // Always use camelCase key (gh-2257) |
| owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; |
| }, |
| access: function( owner, key, value ) { |
| |
| // In cases where either: |
| // |
| // 1. No key was specified |
| // 2. A string key was specified, but no value provided |
| // |
| // Take the "read" path and allow the get method to determine |
| // which value to return, respectively either: |
| // |
| // 1. The entire cache object |
| // 2. The data stored at the key |
| // |
| if ( key === undefined || |
| ( ( key && typeof key === "string" ) && value === undefined ) ) { |
| |
| return this.get( owner, key ); |
| } |
| |
| // When the key is not a string, or both a key and value |
| // are specified, set or extend (existing objects) with either: |
| // |
| // 1. An object of properties |
| // 2. A key and value |
| // |
| this.set( owner, key, value ); |
| |
| // Since the "set" path can have two possible entry points |
| // return the expected data based on which path was taken[*] |
| return value !== undefined ? value : key; |
| }, |
| remove: function( owner, key ) { |
| var i, |
| cache = owner[ this.expando ]; |
| |
| if ( cache === undefined ) { |
| return; |
| } |
| |
| if ( key !== undefined ) { |
| |
| // Support array or space separated string of keys |
| if ( Array.isArray( key ) ) { |
| |
| // If key is an array of keys... |
| // We always set camelCase keys, so remove that. |
| key = key.map( camelCase ); |
| } else { |
| key = camelCase( key ); |
| |
| // If a key with the spaces exists, use it. |
| // Otherwise, create an array by matching non-whitespace |
| key = key in cache ? |
| [ key ] : |
| ( key.match( rnothtmlwhite ) || [] ); |
| } |
| |
| i = key.length; |
| |
| while ( i-- ) { |
| delete cache[ key[ i ] ]; |
| } |
| } |
| |
| // Remove the expando if there's no more data |
| if ( key === undefined || jQuery.isEmptyObject( cache ) ) { |
| |
| // Support: Chrome <=35 - 45 |
| // Webkit & Blink performance suffers when deleting properties |
| // from DOM nodes, so set to undefined instead |
| // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) |
| if ( owner.nodeType ) { |
| owner[ this.expando ] = undefined; |
| } else { |
| delete owner[ this.expando ]; |
| } |
| } |
| }, |
| hasData: function( owner ) { |
| var cache = owner[ this.expando ]; |
| return cache !== undefined && !jQuery.isEmptyObject( cache ); |
| } |
| }; |
| |
| return Data; |
| } ); |