Geen omschrijving

data.js 33KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. QUnit.module( "data", { afterEach: moduleTeardown } );
  2. QUnit.test( "expando", function( assert ) {
  3. assert.expect( 1 );
  4. assert.equal( jQuery.expando !== undefined, true, "jQuery is exposing the expando" );
  5. } );
  6. QUnit.test( "jQuery.data & removeData, expected returns", function( assert ) {
  7. assert.expect( 4 );
  8. var elem = document.body;
  9. assert.equal(
  10. jQuery.data( elem, "hello", "world" ), "world",
  11. "jQuery.data( elem, key, value ) returns value"
  12. );
  13. assert.equal(
  14. jQuery.data( elem, "hello" ), "world",
  15. "jQuery.data( elem, key ) returns value"
  16. );
  17. assert.deepEqual(
  18. jQuery.data( elem, { goodnight: "moon" } ), { goodnight: "moon" },
  19. "jQuery.data( elem, obj ) returns obj"
  20. );
  21. assert.equal(
  22. jQuery.removeData( elem, "hello" ), undefined,
  23. "jQuery.removeData( elem, key, value ) returns undefined"
  24. );
  25. } );
  26. QUnit.test( "jQuery._data & _removeData, expected returns", function( assert ) {
  27. assert.expect( 4 );
  28. var elem = document.body;
  29. assert.equal(
  30. jQuery._data( elem, "hello", "world" ), "world",
  31. "jQuery._data( elem, key, value ) returns value"
  32. );
  33. assert.equal(
  34. jQuery._data( elem, "hello" ), "world",
  35. "jQuery._data( elem, key ) returns value"
  36. );
  37. assert.deepEqual(
  38. jQuery._data( elem, { goodnight: "moon" } ), { goodnight: "moon" },
  39. "jQuery._data( elem, obj ) returns obj"
  40. );
  41. assert.equal(
  42. jQuery._removeData( elem, "hello" ), undefined,
  43. "jQuery._removeData( elem, key, value ) returns undefined"
  44. );
  45. } );
  46. QUnit.test( "jQuery.hasData no side effects", function( assert ) {
  47. assert.expect( 1 );
  48. var obj = {};
  49. jQuery.hasData( obj );
  50. assert.equal( Object.getOwnPropertyNames( obj ).length, 0,
  51. "No data expandos where added when calling jQuery.hasData(o)"
  52. );
  53. } );
  54. function dataTests( elem, assert ) {
  55. var dataObj, internalDataObj;
  56. assert.equal( jQuery.data( elem, "foo" ), undefined, "No data exists initially" );
  57. assert.strictEqual( jQuery.hasData( elem ), false, "jQuery.hasData agrees no data exists initially" );
  58. dataObj = jQuery.data( elem );
  59. assert.equal( typeof dataObj, "object", "Calling data with no args gives us a data object reference" );
  60. assert.strictEqual( jQuery.data( elem ), dataObj, "Calling jQuery.data returns the same data object when called multiple times" );
  61. assert.strictEqual( jQuery.hasData( elem ), false, "jQuery.hasData agrees no data exists even when an empty data obj exists" );
  62. dataObj[ "foo" ] = "bar";
  63. assert.equal( jQuery.data( elem, "foo" ), "bar", "Data is readable by jQuery.data when set directly on a returned data object" );
  64. assert.strictEqual( jQuery.hasData( elem ), true, "jQuery.hasData agrees data exists when data exists" );
  65. jQuery.data( elem, "foo", "baz" );
  66. assert.equal( jQuery.data( elem, "foo" ), "baz", "Data can be changed by jQuery.data" );
  67. assert.equal( dataObj[ "foo" ], "baz", "Changes made through jQuery.data propagate to referenced data object" );
  68. jQuery.data( elem, "foo", undefined );
  69. assert.equal( jQuery.data( elem, "foo" ), "baz", "Data is not unset by passing undefined to jQuery.data" );
  70. jQuery.data( elem, "foo", null );
  71. assert.strictEqual( jQuery.data( elem, "foo" ), null, "Setting null using jQuery.data works OK" );
  72. jQuery.data( elem, "foo", "foo1" );
  73. jQuery.data( elem, { "bar": "baz", "boom": "bloz" } );
  74. assert.strictEqual( jQuery.data( elem, "foo" ), "foo1", "Passing an object extends the data object instead of replacing it" );
  75. assert.equal( jQuery.data( elem, "boom" ), "bloz", "Extending the data object works" );
  76. jQuery._data( elem, "foo", "foo2", true );
  77. assert.equal( jQuery._data( elem, "foo" ), "foo2", "Setting internal data works" );
  78. assert.equal( jQuery.data( elem, "foo" ), "foo1", "Setting internal data does not override user data" );
  79. internalDataObj = jQuery._data( elem );
  80. assert.ok( internalDataObj, "Internal data object exists" );
  81. assert.notStrictEqual( dataObj, internalDataObj, "Internal data object is not the same as user data object" );
  82. assert.strictEqual( elem.boom, undefined, "Data is never stored directly on the object" );
  83. jQuery.removeData( elem, "foo" );
  84. assert.strictEqual( jQuery.data( elem, "foo" ), undefined, "jQuery.removeData removes single properties" );
  85. jQuery.removeData( elem );
  86. assert.strictEqual( jQuery._data( elem ), internalDataObj, "jQuery.removeData does not remove internal data if it exists" );
  87. jQuery.data( elem, "foo", "foo1" );
  88. jQuery._data( elem, "foo", "foo2" );
  89. assert.equal( jQuery.data( elem, "foo" ), "foo1", "(sanity check) Ensure data is set in user data object" );
  90. assert.equal( jQuery._data( elem, "foo" ), "foo2", "(sanity check) Ensure data is set in internal data object" );
  91. assert.strictEqual( jQuery._data( elem, jQuery.expando ), undefined, "Removing the last item in internal data destroys the internal data object" );
  92. jQuery._data( elem, "foo", "foo2" );
  93. assert.equal( jQuery._data( elem, "foo" ), "foo2", "(sanity check) Ensure data is set in internal data object" );
  94. jQuery.removeData( elem, "foo" );
  95. assert.equal( jQuery._data( elem, "foo" ), "foo2", "(sanity check) jQuery.removeData for user data does not remove internal data" );
  96. }
  97. QUnit.test( "jQuery.data(div)", function( assert ) {
  98. assert.expect( 25 );
  99. var div = document.createElement( "div" );
  100. dataTests( div, assert );
  101. } );
  102. QUnit.test( "jQuery.data({})", function( assert ) {
  103. assert.expect( 25 );
  104. dataTests( {}, assert );
  105. } );
  106. QUnit.test( "jQuery.data(window)", function( assert ) {
  107. assert.expect( 25 );
  108. // remove bound handlers from window object to stop potential false positives caused by fix for #5280 in
  109. // transports/xhr.js
  110. jQuery( window ).off( "unload" );
  111. dataTests( window, assert );
  112. } );
  113. QUnit.test( "jQuery.data(document)", function( assert ) {
  114. assert.expect( 25 );
  115. dataTests( document, assert );
  116. } );
  117. QUnit.test( "jQuery.data(<embed>)", function( assert ) {
  118. assert.expect( 25 );
  119. dataTests( document.createElement( "embed" ), assert );
  120. } );
  121. QUnit.test( "jQuery.data(object/flash)", function( assert ) {
  122. assert.expect( 25 );
  123. var flash = document.createElement( "object" );
  124. flash.setAttribute( "classid", "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" );
  125. dataTests( flash, assert );
  126. } );
  127. // attempting to access the data of an undefined jQuery element should be undefined
  128. QUnit.test( "jQuery().data() === undefined (#14101)", function( assert ) {
  129. assert.expect( 2 );
  130. assert.strictEqual( jQuery().data(), undefined );
  131. assert.strictEqual( jQuery().data( "key" ), undefined );
  132. } );
  133. QUnit.test( ".data()", function( assert ) {
  134. assert.expect( 5 );
  135. var div, dataObj, nodiv, obj;
  136. div = jQuery( "#foo" );
  137. assert.strictEqual( div.data( "foo" ), undefined, "Make sure that missing result is undefined" );
  138. div.data( "test", "success" );
  139. dataObj = div.data();
  140. assert.deepEqual( dataObj, { test: "success" }, "data() returns entire data object with expected properties" );
  141. assert.strictEqual( div.data( "foo" ), undefined, "Make sure that missing result is still undefined" );
  142. nodiv = jQuery( "#unfound" );
  143. assert.equal( nodiv.data(), null, "data() on empty set returns null" );
  144. obj = { foo: "bar" };
  145. jQuery( obj ).data( "foo", "baz" );
  146. dataObj = jQuery.extend( true, {}, jQuery( obj ).data() );
  147. assert.deepEqual( dataObj, { "foo": "baz" }, "Retrieve data object from a wrapped JS object (#7524)" );
  148. } );
  149. function testDataTypes( $obj, assert ) {
  150. jQuery.each( {
  151. "null": null,
  152. "true": true,
  153. "false": false,
  154. "zero": 0,
  155. "one": 1,
  156. "empty string": "",
  157. "empty array": [],
  158. "array": [ 1 ],
  159. "empty object": {},
  160. "object": { foo: "bar" },
  161. "date": new Date(),
  162. "regex": /test/,
  163. "function": function() {}
  164. }, function( type, value ) {
  165. assert.strictEqual( $obj.data( "test", value ).data( "test" ), value, "Data set to " + type );
  166. } );
  167. }
  168. QUnit.test( "jQuery(Element).data(String, Object).data(String)", function( assert ) {
  169. assert.expect( 18 );
  170. var parent = jQuery( "<div><div></div></div>" ),
  171. div = parent.children();
  172. assert.strictEqual( div.data( "test" ), undefined, "No data exists initially" );
  173. assert.strictEqual( div.data( "test", "success" ).data( "test" ), "success", "Data added" );
  174. assert.strictEqual( div.data( "test", "overwritten" ).data( "test" ), "overwritten", "Data overwritten" );
  175. assert.strictEqual( div.data( "test", undefined ).data( "test" ), "overwritten", ".data(key,undefined) does nothing but is chainable (#5571)" );
  176. assert.strictEqual( div.data( "notexist" ), undefined, "No data exists for unset key" );
  177. testDataTypes( div, assert );
  178. parent.remove();
  179. } );
  180. QUnit.test( "jQuery(plain Object).data(String, Object).data(String)", function( assert ) {
  181. assert.expect( 16 );
  182. // #3748
  183. var $obj = jQuery( { exists: true } );
  184. assert.strictEqual( $obj.data( "nothing" ), undefined, "Non-existent data returns undefined" );
  185. assert.strictEqual( $obj.data( "exists" ), undefined, "Object properties are not returned as data" );
  186. testDataTypes( $obj, assert );
  187. // Clean up
  188. $obj.removeData();
  189. assert.deepEqual( $obj[ 0 ], { exists: true }, "removeData does not clear the object" );
  190. } );
  191. QUnit.test( ".data(object) does not retain references. #13815", function( assert ) {
  192. assert.expect( 2 );
  193. var $divs = jQuery( "<div></div><div></div>" ).appendTo( "#qunit-fixture" );
  194. $divs.data( { "type": "foo" } );
  195. $divs.eq( 0 ).data( "type", "bar" );
  196. assert.equal( $divs.eq( 0 ).data( "type" ), "bar", "Correct updated value" );
  197. assert.equal( $divs.eq( 1 ).data( "type" ), "foo", "Original value retained" );
  198. } );
  199. QUnit.test( "data-* attributes", function( assert ) {
  200. assert.expect( 46 );
  201. var prop, i, l, metadata, elem,
  202. obj, obj2, check, num, num2,
  203. parseJSON = JSON.parse,
  204. div = jQuery( "<div>" ),
  205. child = jQuery( "<div data-myobj='old data' data-ignored=\"DOM\" data-other='test' data-foo-42='boosh'></div>" ),
  206. dummy = jQuery( "<div data-myobj='old data' data-ignored=\"DOM\" data-other='test' data-foo-42='boosh'></div>" );
  207. assert.equal( div.data( "attr" ), undefined, "Check for non-existing data-attr attribute" );
  208. div.attr( "data-attr", "exists" );
  209. assert.equal( div.data( "attr" ), "exists", "Check for existing data-attr attribute" );
  210. div.attr( "data-attr", "exists2" );
  211. assert.equal( div.data( "attr" ), "exists", "Check that updates to data- don't update .data()" );
  212. div.data( "attr", "internal" ).attr( "data-attr", "external" );
  213. assert.equal( div.data( "attr" ), "internal", "Check for .data('attr') precedence (internal > external data-* attribute)" );
  214. div.remove();
  215. child.appendTo( "#qunit-fixture" );
  216. assert.equal( child.data( "myobj" ), "old data", "Value accessed from data-* attribute" );
  217. assert.equal( child.data( "foo-42" ), "boosh", "camelCasing does not affect numbers (#1751)" );
  218. child.data( "myobj", "replaced" );
  219. assert.equal( child.data( "myobj" ), "replaced", "Original data overwritten" );
  220. child.data( "ignored", "cache" );
  221. assert.equal( child.data( "ignored" ), "cache", "Cached data used before DOM data-* fallback" );
  222. obj = child.data();
  223. obj2 = dummy.data();
  224. check = [ "myobj", "ignored", "other", "foo-42" ];
  225. num = 0;
  226. num2 = 0;
  227. dummy.remove();
  228. for ( i = 0, l = check.length; i < l; i++ ) {
  229. assert.ok( obj[ check[ i ] ], "Make sure data- property exists when calling data-." );
  230. assert.ok( obj2[ check[ i ] ], "Make sure data- property exists when calling data-." );
  231. }
  232. for ( prop in obj ) {
  233. num++;
  234. }
  235. assert.equal( num, check.length, "Make sure that the right number of properties came through." );
  236. for ( prop in obj2 ) {
  237. num2++;
  238. }
  239. assert.equal( num2, check.length, "Make sure that the right number of properties came through." );
  240. child.attr( "data-other", "newvalue" );
  241. assert.equal( child.data( "other" ), "test", "Make sure value was pulled in properly from a .data()." );
  242. // attribute parsing
  243. i = 0;
  244. JSON.parse = function() {
  245. i++;
  246. return parseJSON.apply( this, arguments );
  247. };
  248. child
  249. .attr( "data-true", "true" )
  250. .attr( "data-false", "false" )
  251. .attr( "data-five", "5" )
  252. .attr( "data-point", "5.5" )
  253. .attr( "data-pointe", "5.5E3" )
  254. .attr( "data-grande", "5.574E9" )
  255. .attr( "data-hexadecimal", "0x42" )
  256. .attr( "data-pointbad", "5..5" )
  257. .attr( "data-pointbad2", "-." )
  258. .attr( "data-bigassnum", "123456789123456789123456789" )
  259. .attr( "data-badjson", "{123}" )
  260. .attr( "data-badjson2", "[abc]" )
  261. .attr( "data-notjson", " {}" )
  262. .attr( "data-notjson2", "[] " )
  263. .attr( "data-empty", "" )
  264. .attr( "data-space", " " )
  265. .attr( "data-null", "null" )
  266. .attr( "data-string", "test" );
  267. assert.strictEqual( child.data( "true" ), true, "Primitive true read from attribute" );
  268. assert.strictEqual( child.data( "false" ), false, "Primitive false read from attribute" );
  269. assert.strictEqual( child.data( "five" ), 5, "Integer read from attribute" );
  270. assert.strictEqual( child.data( "point" ), 5.5, "Floating-point number read from attribute" );
  271. assert.strictEqual( child.data( "pointe" ), "5.5E3",
  272. "Exponential-notation number read from attribute as string" );
  273. assert.strictEqual( child.data( "grande" ), "5.574E9",
  274. "Big exponential-notation number read from attribute as string" );
  275. assert.strictEqual( child.data( "hexadecimal" ), "0x42",
  276. "Hexadecimal number read from attribute as string" );
  277. assert.strictEqual( child.data( "pointbad" ), "5..5",
  278. "Extra-point non-number read from attribute as string" );
  279. assert.strictEqual( child.data( "pointbad2" ), "-.",
  280. "No-digit non-number read from attribute as string" );
  281. assert.strictEqual( child.data( "bigassnum" ), "123456789123456789123456789",
  282. "Bad bigass number read from attribute as string" );
  283. assert.strictEqual( child.data( "badjson" ), "{123}", "Bad JSON object read from attribute as string" );
  284. assert.strictEqual( child.data( "badjson2" ), "[abc]", "Bad JSON array read from attribute as string" );
  285. assert.strictEqual( child.data( "notjson" ), " {}",
  286. "JSON object with leading non-JSON read from attribute as string" );
  287. assert.strictEqual( child.data( "notjson2" ), "[] ",
  288. "JSON array with trailing non-JSON read from attribute as string" );
  289. assert.strictEqual( child.data( "empty" ), "", "Empty string read from attribute" );
  290. assert.strictEqual( child.data( "space" ), " ", "Whitespace string read from attribute" );
  291. assert.strictEqual( child.data( "null" ), null, "Primitive null read from attribute" );
  292. assert.strictEqual( child.data( "string" ), "test", "Typical string read from attribute" );
  293. assert.equal( i, 2, "Correct number of JSON parse attempts when reading from attributes" );
  294. JSON.parse = parseJSON;
  295. child.remove();
  296. // tests from metadata plugin
  297. function testData( index, elem ) {
  298. switch ( index ) {
  299. case 0:
  300. assert.equal( jQuery( elem ).data( "foo" ), "bar", "Check foo property" );
  301. assert.equal( jQuery( elem ).data( "bar" ), "baz", "Check baz property" );
  302. break;
  303. case 1:
  304. assert.equal( jQuery( elem ).data( "test" ), "bar", "Check test property" );
  305. assert.equal( jQuery( elem ).data( "bar" ), "baz", "Check bar property" );
  306. break;
  307. case 2:
  308. assert.equal( jQuery( elem ).data( "zoooo" ), "bar", "Check zoooo property" );
  309. assert.deepEqual( jQuery( elem ).data( "bar" ), { "test":"baz" }, "Check bar property" );
  310. break;
  311. case 3:
  312. assert.equal( jQuery( elem ).data( "number" ), true, "Check number property" );
  313. assert.deepEqual( jQuery( elem ).data( "stuff" ), [ 2, 8 ], "Check stuff property" );
  314. break;
  315. default:
  316. assert.ok( false, [ "Assertion failed on index ", index, ", with data" ].join( "" ) );
  317. }
  318. }
  319. metadata = "<ol><li class='test test2' data-foo='bar' data-bar='baz' data-arr='[1,2]'>Some stuff</li><li class='test test2' data-test='bar' data-bar='baz'>Some stuff</li><li class='test test2' data-zoooo='bar' data-bar='{\"test\":\"baz\"}'>Some stuff</li><li class='test test2' data-number=true data-stuff='[2,8]'>Some stuff</li></ol>";
  320. elem = jQuery( metadata ).appendTo( "#qunit-fixture" );
  321. elem.find( "li" ).each( testData );
  322. elem.remove();
  323. } );
  324. QUnit.test( ".data(Object)", function( assert ) {
  325. assert.expect( 4 );
  326. var obj, jqobj,
  327. div = jQuery( "<div></div>" );
  328. div.data( { "test": "in", "test2": "in2" } );
  329. assert.equal( div.data( "test" ), "in", "Verify setting an object in data" );
  330. assert.equal( div.data( "test2" ), "in2", "Verify setting an object in data" );
  331. obj = { test:"unset" };
  332. jqobj = jQuery( obj );
  333. jqobj.data( "test", "unset" );
  334. jqobj.data( { "test": "in", "test2": "in2" } );
  335. assert.equal( jQuery.data( obj )[ "test" ], "in", "Verify setting an object on an object extends the data object" );
  336. assert.equal( obj[ "test2" ], undefined, "Verify setting an object on an object does not extend the object" );
  337. // manually clean up detached elements
  338. div.remove();
  339. } );
  340. QUnit.test( "jQuery.removeData", function( assert ) {
  341. assert.expect( 10 );
  342. var obj,
  343. div = jQuery( "#foo" )[ 0 ];
  344. jQuery.data( div, "test", "testing" );
  345. jQuery.removeData( div, "test" );
  346. assert.equal( jQuery.data( div, "test" ), undefined, "Check removal of data" );
  347. jQuery.data( div, "test2", "testing" );
  348. jQuery.removeData( div );
  349. assert.ok( !jQuery.data( div, "test2" ), "Make sure that the data property no longer exists." );
  350. assert.ok( !div[ jQuery.expando ], "Make sure the expando no longer exists, as well." );
  351. jQuery.data( div, {
  352. test3: "testing",
  353. test4: "testing"
  354. } );
  355. jQuery.removeData( div, "test3 test4" );
  356. assert.ok( !jQuery.data( div, "test3" ) || jQuery.data( div, "test4" ), "Multiple delete with spaces." );
  357. jQuery.data( div, {
  358. test3: "testing",
  359. test4: "testing"
  360. } );
  361. jQuery.removeData( div, [ "test3", "test4" ] );
  362. assert.ok( !jQuery.data( div, "test3" ) || jQuery.data( div, "test4" ), "Multiple delete by array." );
  363. jQuery.data( div, {
  364. "test3 test4": "testing",
  365. "test3": "testing"
  366. } );
  367. jQuery.removeData( div, "test3 test4" );
  368. assert.ok( !jQuery.data( div, "test3 test4" ), "Multiple delete with spaces deleted key with exact name" );
  369. assert.ok( jQuery.data( div, "test3" ), "Left the partial matched key alone" );
  370. obj = {};
  371. jQuery.data( obj, "test", "testing" );
  372. assert.equal( jQuery( obj ).data( "test" ), "testing", "verify data on plain object" );
  373. jQuery.removeData( obj, "test" );
  374. assert.equal( jQuery.data( obj, "test" ), undefined, "Check removal of data on plain object" );
  375. jQuery.data( window, "BAD", true );
  376. jQuery.removeData( window, "BAD" );
  377. assert.ok( !jQuery.data( window, "BAD" ), "Make sure that the value was not still set." );
  378. } );
  379. QUnit.test( ".removeData()", function( assert ) {
  380. assert.expect( 6 );
  381. var div = jQuery( "#foo" );
  382. div.data( "test", "testing" );
  383. div.removeData( "test" );
  384. assert.equal( div.data( "test" ), undefined, "Check removal of data" );
  385. div.data( "test", "testing" );
  386. div.data( "test.foo", "testing2" );
  387. div.removeData( "test.bar" );
  388. assert.equal( div.data( "test.foo" ), "testing2", "Make sure data is intact" );
  389. assert.equal( div.data( "test" ), "testing", "Make sure data is intact" );
  390. div.removeData( "test" );
  391. assert.equal( div.data( "test.foo" ), "testing2", "Make sure data is intact" );
  392. assert.equal( div.data( "test" ), undefined, "Make sure data is intact" );
  393. div.removeData( "test.foo" );
  394. assert.equal( div.data( "test.foo" ), undefined, "Make sure data is intact" );
  395. } );
  396. if ( window.JSON && window.JSON.stringify ) {
  397. QUnit.test( "JSON serialization (#8108)", function( assert ) {
  398. assert.expect( 1 );
  399. var obj = { "foo": "bar" };
  400. jQuery.data( obj, "hidden", true );
  401. assert.equal( JSON.stringify( obj ), "{\"foo\":\"bar\"}", "Expando is hidden from JSON.stringify" );
  402. } );
  403. }
  404. QUnit.test( ".data should follow html5 specification regarding camel casing", function( assert ) {
  405. assert.expect( 12 );
  406. var div = jQuery( "<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>" )
  407. .prependTo( "body" );
  408. assert.equal( div.data()[ "wTF" ], "ftw", "Verify single letter data-* key" );
  409. assert.equal( div.data()[ "bigALittleA" ], "bouncing-b", "Verify single letter mixed data-* key" );
  410. assert.equal( div.data()[ "foo" ], "a", "Verify single word data-* key" );
  411. assert.equal( div.data()[ "fooBar" ], "b", "Verify multiple word data-* key" );
  412. assert.equal( div.data()[ "fooBarBaz" ], "c", "Verify multiple word data-* key" );
  413. assert.equal( div.data( "foo" ), "a", "Verify single word data-* key" );
  414. assert.equal( div.data( "fooBar" ), "b", "Verify multiple word data-* key" );
  415. assert.equal( div.data( "fooBarBaz" ), "c", "Verify multiple word data-* key" );
  416. div.data( "foo-bar", "d" );
  417. assert.equal( div.data( "fooBar" ), "d", "Verify updated data-* key" );
  418. assert.equal( div.data( "foo-bar" ), "d", "Verify updated data-* key" );
  419. assert.equal( div.data( "fooBar" ), "d", "Verify updated data-* key (fooBar)" );
  420. assert.equal( div.data( "foo-bar" ), "d", "Verify updated data-* key (foo-bar)" );
  421. div.remove();
  422. } );
  423. QUnit.test( ".data should not miss preset data-* w/ hyphenated property names", function( assert ) {
  424. assert.expect( 2 );
  425. var div = jQuery( "<div></div>", { id: "hyphened" } ).appendTo( "#qunit-fixture" ),
  426. test = {
  427. "camelBar": "camelBar",
  428. "hyphen-foo": "hyphen-foo"
  429. };
  430. div.data( test );
  431. jQuery.each( test, function( i, k ) {
  432. assert.equal( div.data( k ), k, "data with property '" + k + "' was correctly found" );
  433. } );
  434. } );
  435. QUnit.test( "jQuery.data should not miss data-* w/ hyphenated property names #14047", function( assert ) {
  436. assert.expect( 1 );
  437. var div = jQuery( "<div></div>" );
  438. div.data( "foo-bar", "baz" );
  439. assert.equal( jQuery.data( div[ 0 ], "foo-bar" ), "baz", "data with property 'foo-bar' was correctly found" );
  440. } );
  441. QUnit.test( ".data should not miss attr() set data-* with hyphenated property names", function( assert ) {
  442. assert.expect( 2 );
  443. var a, b;
  444. a = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" );
  445. a.attr( "data-long-param", "test" );
  446. a.data( "long-param", { a: 2 } );
  447. assert.deepEqual( a.data( "long-param" ), { a: 2 }, "data with property long-param was found, 1" );
  448. b = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" );
  449. b.attr( "data-long-param", "test" );
  450. b.data( "long-param" );
  451. b.data( "long-param", { a: 2 } );
  452. assert.deepEqual( b.data( "long-param" ), { a: 2 }, "data with property long-param was found, 2" );
  453. } );
  454. QUnit.test( ".data always sets data with the camelCased key (gh-2257)", function( assert ) {
  455. assert.expect( 18 );
  456. var div = jQuery( "<div>" ).appendTo( "#qunit-fixture" ),
  457. datas = {
  458. "non-empty": {
  459. key: "nonEmpty",
  460. value: "a string"
  461. },
  462. "empty-string": {
  463. key: "emptyString",
  464. value: ""
  465. },
  466. "one-value": {
  467. key: "oneValue",
  468. value: 1
  469. },
  470. "zero-value": {
  471. key: "zeroValue",
  472. value: 0
  473. },
  474. "an-array": {
  475. key: "anArray",
  476. value: []
  477. },
  478. "an-object": {
  479. key: "anObject",
  480. value: {}
  481. },
  482. "bool-true": {
  483. key: "boolTrue",
  484. value: true
  485. },
  486. "bool-false": {
  487. key: "boolFalse",
  488. value: false
  489. },
  490. // JSHint enforces double quotes,
  491. // but JSON strings need double quotes to parse
  492. // so we need escaped double quotes here
  493. "some-json": {
  494. key: "someJson",
  495. value: "{ \"foo\": \"bar\" }"
  496. }
  497. };
  498. jQuery.each( datas, function( key, val ) {
  499. div.data( key, val.value );
  500. var allData = div.data();
  501. assert.equal( allData[ key ], undefined, ".data does not store with hyphenated keys" );
  502. assert.equal( allData[ val.key ], val.value, ".data stores the camelCased key" );
  503. } );
  504. } );
  505. QUnit.test( ".data should not strip more than one hyphen when camelCasing (gh-2070)", function( assert ) {
  506. assert.expect( 3 );
  507. var div = jQuery( "<div data-nested-single='single' data-nested--double='double' data-nested---triple='triple'></div>" ).appendTo( "#qunit-fixture" ),
  508. allData = div.data();
  509. assert.equal( allData.nestedSingle, "single", "Key is correctly camelCased" );
  510. assert.equal( allData[ "nested-Double" ], "double", "Key with double hyphens is correctly camelCased" );
  511. assert.equal( allData[ "nested--Triple" ], "triple", "Key with triple hyphens is correctly camelCased" );
  512. } );
  513. QUnit.test( ".data supports interoperable hyphenated/camelCase get/set of properties with arbitrary non-null|NaN|undefined values", function( assert ) {
  514. var div = jQuery( "<div></div>", { id: "hyphened" } ).appendTo( "#qunit-fixture" ),
  515. datas = {
  516. "non-empty": {
  517. key: "nonEmpty",
  518. value: "a string"
  519. },
  520. "empty-string": {
  521. key: "emptyString",
  522. value: ""
  523. },
  524. "one-value": {
  525. key: "oneValue",
  526. value: 1
  527. },
  528. "zero-value": {
  529. key: "zeroValue",
  530. value: 0
  531. },
  532. "an-array": {
  533. key: "anArray",
  534. value: []
  535. },
  536. "an-object": {
  537. key: "anObject",
  538. value: {}
  539. },
  540. "bool-true": {
  541. key: "boolTrue",
  542. value: true
  543. },
  544. "bool-false": {
  545. key: "boolFalse",
  546. value: false
  547. },
  548. // JSHint enforces double quotes,
  549. // but JSON strings need double quotes to parse
  550. // so we need escaped double quotes here
  551. "some-json": {
  552. key: "someJson",
  553. value: "{ \"foo\": \"bar\" }"
  554. },
  555. "num-1-middle": {
  556. key: "num-1Middle",
  557. value: true
  558. },
  559. "num-end-2": {
  560. key: "numEnd-2",
  561. value: true
  562. },
  563. "2-num-start": {
  564. key: "2NumStart",
  565. value: true
  566. }
  567. };
  568. assert.expect( 24 );
  569. jQuery.each( datas, function( key, val ) {
  570. div.data( key, val.value );
  571. assert.deepEqual( div.data( key ), val.value, "get: " + key );
  572. assert.deepEqual( div.data( val.key ), val.value, "get: " + val.key );
  573. } );
  574. } );
  575. QUnit.test( ".data supports interoperable removal of hyphenated/camelCase properties", function( assert ) {
  576. var div = jQuery( "<div></div>", { id: "hyphened" } ).appendTo( "#qunit-fixture" ),
  577. rdashAlpha = /-([a-z])/g,
  578. datas = {
  579. "non-empty": "a string",
  580. "empty-string": "",
  581. "one-value": 1,
  582. "zero-value": 0,
  583. "an-array": [],
  584. "an-object": {},
  585. "bool-true": true,
  586. "bool-false": false,
  587. // JSHint enforces double quotes,
  588. // but JSON strings need double quotes to parse
  589. // so we need escaped double quotes here
  590. "some-json": "{ \"foo\": \"bar\" }"
  591. };
  592. assert.expect( 27 );
  593. function fcamelCase( all, letter ) {
  594. return letter.toUpperCase();
  595. }
  596. jQuery.each( datas, function( key, val ) {
  597. div.data( key, val );
  598. assert.deepEqual( div.data( key ), val, "get: " + key );
  599. assert.deepEqual(
  600. div.data( key.replace( rdashAlpha, fcamelCase ) ),
  601. val,
  602. "get: " + key.replace( rdashAlpha, fcamelCase )
  603. );
  604. div.removeData( key );
  605. assert.equal( div.data( key ), undefined, "get: " + key );
  606. } );
  607. } );
  608. QUnit.test( ".data supports interoperable removal of properties SET TWICE #13850", function( assert ) {
  609. var div = jQuery( "<div>" ).appendTo( "#qunit-fixture" ),
  610. datas = {
  611. "non-empty": "a string",
  612. "empty-string": "",
  613. "one-value": 1,
  614. "zero-value": 0,
  615. "an-array": [],
  616. "an-object": {},
  617. "bool-true": true,
  618. "bool-false": false,
  619. // JSHint enforces double quotes,
  620. // but JSON strings need double quotes to parse
  621. // so we need escaped double quotes here
  622. "some-json": "{ \"foo\": \"bar\" }"
  623. };
  624. assert.expect( 9 );
  625. jQuery.each( datas, function( key, val ) {
  626. div.data( key, val );
  627. div.data( key, val );
  628. div.removeData( key );
  629. assert.equal( div.data( key ), undefined, "removal: " + key );
  630. } );
  631. } );
  632. QUnit.test( ".removeData supports removal of hyphenated properties via array (#12786, gh-2257)", function( assert ) {
  633. assert.expect( 4 );
  634. var div, plain, compare;
  635. div = jQuery( "<div>" ).appendTo( "#qunit-fixture" );
  636. plain = jQuery( {} );
  637. // Properties should always be camelCased
  638. compare = {
  639. // From batch assignment .data({ "a-a": 1 })
  640. "aA": 1,
  641. // From property, value assignment .data( "b-b", 1 )
  642. "bB": 1
  643. };
  644. // Mixed assignment
  645. div.data( { "a-a": 1 } ).data( "b-b", 1 );
  646. plain.data( { "a-a": 1 } ).data( "b-b", 1 );
  647. assert.deepEqual( div.data(), compare, "Data appears as expected. (div)" );
  648. assert.deepEqual( plain.data(), compare, "Data appears as expected. (plain)" );
  649. div.removeData( [ "a-a", "b-b" ] );
  650. plain.removeData( [ "a-a", "b-b" ] );
  651. assert.deepEqual( div.data(), {}, "Data is empty. (div)" );
  652. assert.deepEqual( plain.data(), {}, "Data is empty. (plain)" );
  653. } );
  654. // Test originally by Moschel
  655. QUnit.test( ".removeData should not throw exceptions. (#10080)", function( assert ) {
  656. var done = assert.async();
  657. assert.expect( 1 );
  658. var frame = jQuery( "#loadediframe" );
  659. jQuery( frame[ 0 ].contentWindow ).on( "unload", function() {
  660. assert.ok( true, "called unload" );
  661. done();
  662. } );
  663. // change the url to trigger unload
  664. frame.attr( "src", baseURL + "iframe.html?param=true" );
  665. } );
  666. QUnit.test( ".data only checks element attributes once. #8909", function( assert ) {
  667. assert.expect( 2 );
  668. var testing = {
  669. "test": "testing",
  670. "test2": "testing"
  671. },
  672. element = jQuery( "<div data-test='testing'>" ),
  673. node = element[ 0 ];
  674. // set an attribute using attr to ensure it
  675. node.setAttribute( "data-test2", "testing" );
  676. assert.deepEqual( element.data(), testing, "Sanity Check" );
  677. node.setAttribute( "data-test3", "testing" );
  678. assert.deepEqual( element.data(), testing, "The data didn't change even though the data-* attrs did" );
  679. // clean up data cache
  680. element.remove();
  681. } );
  682. QUnit.test( "data-* with JSON value can have newlines", function( assert ) {
  683. assert.expect( 1 );
  684. var x = jQuery( "<div data-some='{\n\"foo\":\n\t\"bar\"\n}'></div>" );
  685. assert.equal( x.data( "some" ).foo, "bar", "got a JSON data- attribute with spaces" );
  686. x.remove();
  687. } );
  688. QUnit.test( ".data doesn't throw when calling selection is empty. #13551", function( assert ) {
  689. assert.expect( 1 );
  690. try {
  691. jQuery( null ).data( "prop" );
  692. assert.ok( true, "jQuery(null).data('prop') does not throw" );
  693. } catch ( e ) {
  694. assert.ok( false, e.message );
  695. }
  696. } );
  697. QUnit.test( "acceptData", function( assert ) {
  698. assert.expect( 10 );
  699. var flash, pdf, form;
  700. assert.equal( jQuery( document ).data( "test", 42 ).data( "test" ), 42, "document" );
  701. assert.equal( jQuery( document.documentElement ).data( "test", 42 ).data( "test" ), 42, "documentElement" );
  702. assert.equal( jQuery( {} ).data( "test", 42 ).data( "test" ), 42, "object" );
  703. assert.equal( jQuery( document.createElement( "embed" ) ).data( "test", 42 ).data( "test" ), 42, "embed" );
  704. flash = document.createElement( "object" );
  705. flash.setAttribute( "classid", "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" );
  706. assert.equal( jQuery( flash ).data( "test", 42 ).data( "test" ), 42, "flash" );
  707. pdf = document.createElement( "object" );
  708. pdf.setAttribute( "classid", "clsid:CA8A9780-280D-11CF-A24D-444553540000" );
  709. assert.equal( jQuery( pdf ).data( "test", 42 ).data( "test" ), 42, "pdf" );
  710. assert.strictEqual( jQuery( document.createComment( "" ) ).data( "test", 42 ).data( "test" ), undefined, "comment" );
  711. assert.strictEqual( jQuery( document.createTextNode( "" ) ).data( "test", 42 ).data( "test" ), undefined, "text" );
  712. assert.strictEqual( jQuery( document.createDocumentFragment() ).data( "test", 42 ).data( "test" ), undefined, "documentFragment" );
  713. form = jQuery( "#form" ).append( "<input id='nodeType'/><input id='nodeName'/>" )[ 0 ];
  714. assert.equal( jQuery( form ) .data( "test", 42 ).data( "test" ), 42, "form with aliased DOM properties" );
  715. } );
  716. QUnit.test( "Check proper data removal of non-element descendants nodes (#8335)", function( assert ) {
  717. assert.expect( 1 );
  718. var div = jQuery( "<div>text</div>" ),
  719. text = div.contents();
  720. text.data( "test", "test" ); // This should be a noop.
  721. div.remove();
  722. assert.ok( !text.data( "test" ), "Be sure data is not stored in non-element" );
  723. } );
  724. testIframe(
  725. "enumerate data attrs on body (#14894)",
  726. "data/dataAttrs.html",
  727. function( assert, jQuery, window, document, result ) {
  728. assert.expect( 1 );
  729. assert.equal( result, "ok", "enumeration of data- attrs on body" );
  730. }
  731. );
  732. QUnit.test( "Check that the expando is removed when there's no more data", function( assert ) {
  733. assert.expect( 2 );
  734. var key,
  735. div = jQuery( "<div></div>" );
  736. div.data( "some", "data" );
  737. assert.equal( div.data( "some" ), "data", "Data is added" );
  738. div.removeData( "some" );
  739. // Make sure the expando is gone
  740. for ( key in div[ 0 ] ) {
  741. if ( /^jQuery/.test( key ) ) {
  742. assert.strictEqual( div[ 0 ][ key ], undefined, "Expando was not removed when there was no more data" );
  743. }
  744. }
  745. } );
  746. QUnit.test( "Check that the expando is removed when there's no more data on non-nodes", function( assert ) {
  747. assert.expect( 1 );
  748. var key,
  749. obj = jQuery( { key: 42 } );
  750. obj.data( "some", "data" );
  751. assert.equal( obj.data( "some" ), "data", "Data is added" );
  752. obj.removeData( "some" );
  753. // Make sure the expando is gone
  754. for ( key in obj[ 0 ] ) {
  755. if ( /^jQuery/.test( key ) ) {
  756. assert.ok( false, "Expando was not removed when there was no more data" );
  757. }
  758. }
  759. } );
  760. QUnit.test( ".data(prop) does not create expando", function( assert ) {
  761. assert.expect( 1 );
  762. var key,
  763. div = jQuery( "<div></div>" );
  764. div.data( "foo" );
  765. assert.equal( jQuery.hasData( div[ 0 ] ), false, "No data exists after access" );
  766. // Make sure no expando has been added
  767. for ( key in div[ 0 ] ) {
  768. if ( /^jQuery/.test( key ) ) {
  769. assert.ok( false, "Expando was created on access" );
  770. }
  771. }
  772. } );
  773. QUnit.test( ".data() returns a regular object (jQuery <4 only, gh-4665)", function( assert ) {
  774. assert.expect( 4 );
  775. function verifyRegularObject( assert, object ) {
  776. assert.strictEqual( object.hasOwnProperty, Object.prototype.hasOwnProperty,
  777. "Data object has the hasOwnProperty method" );
  778. assert.strictEqual( object + "", "[object Object]",
  779. "Data object can be stringified" );
  780. }
  781. var elem = jQuery( "<div></div>" );
  782. verifyRegularObject( assert, elem.data() );
  783. elem.data( "foo", "bar" );
  784. verifyRegularObject( assert, elem.data() );
  785. } );