Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safari 6 (Mac OS X and iOS) round long values inside input type="number" #71

Open
zachleat opened this issue Jul 7, 2016 · 14 comments
Open

Comments

@zachleat
Copy link

zachleat commented Jul 7, 2016

vv-number-giftcard

  • Reproducible on Safari 6, fixed in Safari 7.
  • Firefox 47 exhibits the same issue if you set a super long value in JS a la .value = "12341234123412341234";
  • Firefox 47 on Android works as expected
@zachleat zachleat changed the title Mac OS X Safari 6 and iOS Safari 6 round long values inside input type="number" Safari 6 (Mac OS X and iOS) round long values inside input type="number" Jul 7, 2016
@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

Works as expected in Safari 7.

@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

More useful discussion from @dmethvin here: https://twitter.com/davemethvin/status/751107262471606272

@Programmerman1
Copy link

So the problem is that Safari 6 stores and displays the floating-point value rather than the string value, even though the unrounded string is a valid floating-point number per the html 5 spec (and thus can be kept as a string and converted to a rounded double-precision float when needed)? Browser bug sounds about right, maybe even browser quirk.

@domenic
Copy link

domenic commented Jul 7, 2016

I believe that the browser should not be doing this per spec; however, note that this kind of use of <input type="number"> is invalid:

The type=number state is not appropriate for input that happens to only consist of numbers but isn't strictly speaking a number. For example, it would be inappropriate for credit card numbers or US postal codes. A simple way of determining whether to use type=number is to consider whether it would make sense for the input control to have a spinbox interface (e.g. with "up" and "down" arrows). Getting a credit card number wrong by 1 in the last digit isn't a minor mistake, it's as wrong as getting every digit incorrect. So it would not make sense for the user to select a credit card number using "up" and "down" buttons. When a spinbox interface is not appropriate, type=text is probably the right choice (possibly with a pattern attribute).

https://html.spec.whatwg.org/multipage/forms.html#number-state-(type=number)

@dmethvin
Copy link

dmethvin commented Jul 7, 2016

Yeah, the docs seem pretty clear. If you actually want an IEEE floating point value out of the process this bug doesn't make that much difference. Trying to use a type=number input for other purposes is also risky since user input like "9e9" is valid.

@toddparker
Copy link
Collaborator

toddparker commented Jul 7, 2016

Good conversation, thanks for chiming in. Really, the root problem is Android won't show the numeric keypad on Android unless it's a type of number - neither pattern="[0-9]*" (any pattern in fact) or inputmode="numeric" trigger the right keypad (thanks Google!).

So to launch the optimal keypad on Android, we've been trying to make the type=number work for us and there are lots of interesting issues like non-numeric characters can break the input in Firefox so we're filtering out any characters that aren't 0-9, etc. to avoid the situation @dmethvin (hi!) brought up. Yes, we know that the spec designed this only for capturing floating point values but we really want to have a decent UX for data entry and Android isn't doing us any favors.

You can get rid of the spinner buttons with this CSS on webkit and FF with a bit of CSS:

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}

And we've added extra JS to ignore the arrow keys and other triggers that would increment/decrement the value. Fun!

Let's just say this is a messy situation. But I don't think the other answer (use tel) is any good either, at least semantically.

@dmethvin
Copy link

dmethvin commented Jul 7, 2016

Thanks for the detailed explanation @toddparker! Yeah this seems like the perfect place to apply that inputmode=numeric attribute that nobody implements yet.

@toddparker
Copy link
Collaborator

Just for fun, I wanted to see if the latest Android (6) finally supported inputmode
http://jsbin.com/cukeha/

Nope:
image

Good ol number works tho:
image

Using tel just seems like such a bad option, even if it's more accepting of values. The keypad looks like a dialer rather than a numeric keypad here on latest Android which is confusing UX-wise

image

@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

number-safari

Additional Safari 6 test data (note that this input is only 16 digits long and is still rounded)

@Programmerman1
Copy link

I'm pretty sure this is expected: double (64-bit float) can't store that much precision, only 52 bits of precision. That's between 15 and 17 decimal digits.

@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

Worse, this doesn’t seem to be feature testable, given the following:

Safari 6 and Firefox 47

  1. el.value = "12341234123412341234";
  2. Field changes to render 12341234123412300000
  3. el.value returns 12341234123412341234
  4. el.valueAsNumber returns 12341234123412340000 (note the four trailing zeros, as opposed to the five rendered trailing zeros above). This behavior is consistent cross-browser, even on browsers that don’t exhibit this truncating issue in the UI (Chrome).

Note that Firefox 47 exhibits the same behavior for the above feature test attempt, however operates correctly from a UX perspective: typing 12341234123412341234 manually into the field renders correctly.

@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

More test data here:

  1. Rendered value is matches?
  2. value matches?
  3. valueAsNumber matches? If does not match and rendered value also does not match, are they the same?
  4. Value submitted to server matches?

Using the value "12341234123412341234" take the following two paths: setting value with JS or a user entered value. Interesting bullets are bolded.


Safari 6 setting value with JS:

  • Rendered value mismatch: 12341234123412300000
  • value matches
  • valueAsNumber mismatch and does not match rendered value: 12341234123412340000

Feature test would not work.

Safari 6 user typed value:

  • Rendered value mismatch: 12341234123412300000
  • value mismatch: 12341234123412340000
  • valueAsNumber mismatch and does not match rendered value: 12341234123412340000
  • Successful form control value mismatch: 12341234123412340000

Firefox 47 setting value with JS:

  • Rendered value mismatch: 12341234123412300000 (Bugzilla Issue)
  • value matches
  • valueAsNumber mismatch and does not match rendered value: 12341234123412340000

Feature test would not work.

Firefox 47 user typed value:

  • Rendered value matches
  • value matches
  • valueAsNumber mismatch: 12341234123412340000
  • Successful form control value matches

Chrome 51 and Safari 9 setting value with JS:

  • Rendered value matches
  • value matches
  • valueAsNumber mismatch: 12341234123412340000

Chrome 51 and Safari 9 user typed value:

  • Rendered value matches
  • value matches
  • valueAsNumber mismatch: 12341234123412340000
  • Successful form control value matches

Verdict: close but valueAsNumber should probably be NaN


IE11 setting value with JS:

  • Rendered value matches
  • value matches
  • valueAsNumber mismatch: NaN

IE11 user typed value:

  • Rendered value matches
  • value matches
  • valueAsNumber mismatch: NaN

Verdict: this is how it should work in all browsers

@domenic
Copy link

domenic commented Jul 7, 2016

FWIW per spec valueAsNumber should be converted to a floating point number (so by your account "incorrect") whereas value should just be the typed string.

@zachleat
Copy link
Author

zachleat commented Jul 7, 2016

@domenic Ah yeah, sorry. Will correct it to say “mismatched” instead of “incorrect”

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants