Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Data: update both hyphenated and camel case keys #1515

Closed
wants to merge 1 commit into from

3 participants

@rwaldron
Collaborator

Fixes #14799

@rwaldron rwaldron referenced this pull request in jquery/api.jquery.com
Closed

data method, is this a bug? #444

@gibson042
Collaborator

Given that we're talking about breaking changes anyway, I think any commit is premature before we settle on a desired API. The possibilities are numerous:

1.x Backcompatiphilia

  • attribute reader camelCases but never overwrites
  • setter( key, value ) camelCases (and therefore ignores hyphenated keys from setter( obj ))
    • (dropping 2.x behavior of writing to hyphenated keys after overwriting corresponding camelCased keys)
  • setter( obj ) shallow jQuery.extends (and therefore does not camelCase)
  • getter( key ) uses camelCase for fallback
  • getter() returns only camelCase keys except for those from setter( obj )
    • (dropping 2.x behavior of also returning hyphenated keys after setter( hyphenated, value ) overwrites data)
  • weird cases follow setter( objWithHyphenatedKey )
    • signature-dependent key translation: "uh-oh" in obj.data({ "uh-oh": "foo" }).data() ); !( "uh-oh" in obj.data( "uh-oh", "foo" ).data() )
    • hyphenated/camelCase mismatch: obj.data({ "uh-oh": "foo" }).data( "uh-oh", "bar" ).data( "uh-oh" ) === "foo"; obj.data({ "uh-oh": "foo" }).data( "uh-oh", "bar" ).data( "uhOh" ) === "bar"

Embrace HTML5

  • attribute reader camelCases but never overwrites
  • setter( key, value ) camelCases
  • setter( obj ) camelCases all properties (and therefore can self-overwrite)
  • getter( key ) camelCases before lookup
  • getter() returns only camelCase keys
  • weird cases follow setter( objWithHyphenatedKey )
    • key translation: !( "uh-oh" in obj.data({ "uh-oh": "foo" }).data() ); !( "uh-oh" in obj.data( "uh-oh", "foo" ).data() )

Garbage In, Garbage Out

  • attribute reader camelCases but never overwrites
  • setter( key, value ) does not camelCase
  • setter( obj ) shallow jQuery.extends (and therefore does not camelCase)
  • getter( key ) uses camelCase for fallback (or doesn't; who cares?)
  • getter() returns whatever mix was used for setting
  • weird cases abound, but only affect inconsistent-input scenarios

Smorgasbord

  • attribute reader tries to set both hyphenated and camelCase keys, but never overwrites
  • setter( key, value ) sets both unmodified and camelCase keys
  • setter( obj ) sets both unmodified and camelCase keys
  • getter( key ) uses unmodified input
  • getter() returns a identical data under a pair of keys for each input
  • weird cases: I dunno, all of them?

Super-Smorgasbord

  • like "Smorgasbord", but we also reverse camelCase input keys

I'm partial to "Embrace HTML5" and "Garbage In, Garbage Out".

Also, it's worth remembering that all of them technically allow tricky business via manipulating the (otherwise purely internal) object returned from a no-argument getter (e.g., obj.data()[ "I-can-hyphenate-all-I-want-2!" ] = true).

@dmethvin
Owner

@gibson042 thanks for laying out all the options. I like GIGO myself but will think about it some more.

@dmethvin
Owner

Actually I created a spreadsheet to see the carnage at a glance. I'm thinking the Embrace HTML5 option may cause less breakage since we have said we camelized internally, but camelizing the keys we merge bugs me. Ask for edit access if I've screwed something up, which seems likely.

@dmethvin
Owner

Per our discussion in the core meeting we decided to leave this behavior for the .1 releases but change it to "Embrase HTML5" in 2.2, making behavior more consistent with 1.12. We don't want to have both forms stored in the data cache.

@dmethvin dmethvin closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 15, 2014
  1. @rwaldron
This page is out of date. Refresh to see the latest.
Showing with 22 additions and 2 deletions.
  1. +8 −2 src/data.js
  2. +14 −0 test/unit/data.js
View
10 src/data.js
@@ -147,7 +147,9 @@ jQuery.fn.extend({
this.each(function() {
// First, attempt to store a copy or reference of any
// data that might've been store with a camelCased key.
- var data = data_user.get( this, camelKey );
+ var data = data_user.get( this, camelKey ),
+ hasDataAttrs = data_priv.get( this, "hasDataAttrs" ),
+ isHyphenated = key.indexOf("-") !== -1;
// For HTML5 data-* attribute interop, we have to
// store property names with dashes in a camelCase form.
@@ -157,7 +159,11 @@ jQuery.fn.extend({
// *... In the case of properties that might _actually_
// have dashes, we need to also store a copy of that
// unchanged property.
- if ( key.indexOf("-") !== -1 && data !== undefined ) {
+ if ( isHyphenated && data !== undefined ) {
+ data_user.set( this, key, value );
+ }
+
+ if ( isHyphenated && hasDataAttrs === undefined ) {
data_user.set( this, key, value );
}
});
View
14 test/unit/data.js
@@ -558,6 +558,19 @@ test(".data should not miss preset data-* w/ hyphenated property names", functio
});
});
+test(".data should not miss data-* w/ hyphenated property names #14799", function() {
+
+ expect(2);
+
+ var div = jQuery("<div>");
+
+ div.data({ "foo-bar": 1 });
+ div.data( "foo-bar", 2 );
+
+ equal( div.data( "foo-bar" ), 2, "data with property 'foo-bar' is correct");
+ equal( div.data( "fooBar" ), 2, "data with property 'fooBar' is correct");
+});
+
test("jQuery.data should not miss data-* w/ hyphenated property names #14047", function() {
expect(1);
@@ -696,6 +709,7 @@ test( ".removeData supports removal of hyphenated properties via array (#12786)"
// From batch assignment .data({ "a-a": 1 })
"a-a": 1,
// From property, value assignment .data( "b-b", 1 )
+ "b-b": 1,
"bB": 1
};
Something went wrong with that request. Please try again.