Bug Tracker

Ticket #11060 (closed enhancement: duplicate)

Opened 3 years ago

Last modified 17 months ago

Proposal to change the design of .data() slightly

Reported by: latchkey@… Owned by:
Priority: undecided Milestone: None
Component: unfiled Version: 1.7.1
Keywords: Cc:
Blocking: Blocked by:

Description

Dear jQuery experts and my mentors:

I know that this has been brought up multiple times in other ways, but I'm going to bring it up again, in hopefully a different way, so please be kind enough to hear me out.

Suppose you have this:

.data('foo', 'bar')

.data('foo') === 'bar'

Ok, no big deal. String in, string out.

.data('ack', 1.400)

.data('ack') === 1.4

Yes, I'm well aware that putting a float will return me a float, who's value will lose the precision of the two 0's. That is fine, no big deal.

The issue I'm having with .data is when the values of data are assigned from an element in the DOM like this:

<button data-id="1.400"></button>

data('id') === 1.4 (the float, instead of the string 1.400)

What I would like to propose is that:

#1. .data() be changed to always return the same type of what goes into data() #2. make what goes into data(), from elements, always be a string since you can't really assume what the type is or assume that you are doing a conversion here.

This will do four major things:

#1. not break existing code. we can't have that. #2. negate the need to use attr() to retrieve the unmolested value of data() from elements. #3. prevent me from having to write everything as data-id="'1.400'" (using single quotes). this is arguably very error prone. #4. remove a potentially bug inducing bit of design. if i suddenly decide to change my id from an integer to a float (this happened recently, so that is what brought this up, so i know it is a real world issue).

Again, I thank you for your time and patience and understanding.

Change History

comment:1 Changed 3 years ago by dmethvin

  • Status changed from new to closed
  • Resolution set to duplicate

comment:2 Changed 3 years ago by dmethvin

Duplicate of #7579.

comment:3 Changed 2 years ago by anonymous

This seems ok to you?

 http://jsfiddle.net/rKnFu/

I'm trying to store a number as hex, but jquery assumes I really meant exponential notation? WTF?

comment:4 Changed 2 years ago by rwaldron

Use attr()

comment:5 Changed 2 years ago by jeremy.lecour@…

I'm honestly not trolling here, but this is pretty much like what PHP does ; automatic type-guessing without a proper way to tell it how to do it. IMHO it's bad

At least in JSON we have a syntax to indicate the type.

I'd like to have .data() to always return a string and have convenient helpers to easily/manually change the type if needed.

Using .attr() is a good replacement for .data() in many cases, especially if you want a read/write behavior and expect to reflect the value in the "real" html attribute. But some times, you want the benefit of .data(), but this type mess.

comment:6 Changed 2 years ago by dmethvin

I'd like to have .data() to always return a string and have convenient helpers to easily/manually change the type if needed.

You mean if someone set a Boolean using .data("visited", false) we would return the string "false" for .data("visited")? Go think about the havoc that would cause to existing code.

comment:7 Changed 2 years ago by latchkey

As the submitter of this ticket, I do NOT agree with what Jeremy just said.

I think that .data() should *always* return what you put into it. But, any element attribute which was written in HTML, not via JS dom manipulation, ie: <div data-foo="">, should return String since casting is dangerous and unreliable in this case. There is no type information that can be assumed, other than String, and existing behavior cannot work correctly for all cases.

fyi, my blog posting on this has received over 10k views. This is clearly an issue for a lot of people. It would be good if the JQuery community took it more seriously, but I'm not holding my breath.

comment:8 Changed 2 years ago by dmethvin

latchkey, the majority of the confusion comes from the expectation that .data() is used ONLY to get and set data- attributes. Unfortunately, since the method predates HTML5 and data- attributes, it has different semantics and capabilities. If you look at the dup ticket #7579 referenced here, we tweaked things a bit in 1.8.0 to only convert something to a number if it wouldn't change the representation, so data-number="1.80000000" will stay a string since it would otherwise clip the zeroes.

I don't think there is anything we can do to meet everyone's expectations yet avoid breaking code. In any case, a closed duplicate ticket isn't a good place to discuss.

comment:9 follow-up: ↓ 10 Changed 17 months ago by anonymous

I've got a case where a large number is stored as a data- attribute in the HTML. When you fetch the value using $.data, the coercion is buggering up the number and it breaks my code because I'm not getting back EXACTLY what has been put into the HTML.

For example:

<tr data-id="201319611370584515">etc</tr>

When I call .data to fetch that value, I get the integer value 201319611370584500 back and because I need that id to match elsewhere of course it fails.

If I place an alpha character at the beginning of the attribute, for example data-id="x201319611370584515", then I get back exactly what I put in there.

It's beyond me how this behaviour can be considered justifiable when you are dealing with a data format that is patently not typed (HTML). I can't see any rationalisation for it returning a different value to what actually appears in the HTML.

I guess I will use .attr but I think this peculiar behaviour with large numbers needs to be explicitly spelled out in the documentation (or even better fixed) because I had to Google this issue and came upon this bug by way of the blog post mentioned above after scratching my head for over an hour trying to work out what the hell was going on.

comment:10 in reply to: ↑ 9 Changed 17 months ago by rwaldron

Replying to anonymous:

I've got a case where a large number is stored as a data- attribute in the HTML. When you fetch the value using $.data, the coercion is buggering up the number and it breaks my code because I'm not getting back EXACTLY what has been put into the HTML.

For example:

<tr data-id="201319611370584515">etc</tr>

When I call .data to fetch that value, I get the integer value 201319611370584500 back and because I need that id to match elsewhere of course it fails.

If I place an alpha character at the beginning of the attribute, for example data-id="x201319611370584515", then I get back exactly what I put in there.

It's beyond me how this behaviour can be considered justifiable when you are dealing with a data format that is patently not typed (HTML). I can't see any rationalisation for it returning a different value to what actually appears in the HTML.

I guess I will use .attr but I think this peculiar behaviour with large numbers needs to be explicitly spelled out in the documentation (or even better fixed) because I had to Google this issue and came upon this bug by way of the blog post mentioned above after scratching my head for over an hour trying to work out what the hell was going on.

This is already fixed, please upgrade your version of jQuery.

JavaScript numbers are IEEE standard 754, double-precision binary floating-point 64-bit numbers. This means that only even numbers greater then (2^53) are representable. jQuery had enough bug report/complaints about larger numbers (eg. 201319611370584515) being rounded that the only solution was to use a string to represent data values that were not representable as numbers. This way you get the actual value, despite the type being incorrect.

Last edited 17 months ago by rwaldron (previous) (diff)
Note: See TracTickets for help on using tickets.