Data.js 3.9 KB

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