scottjehl / Device-Bugs

Just a collection of quirks and issues that occur on browser platforms (particularly those unlikely to update)
864 stars 19 forks source link

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

Open zachleat opened 8 years ago

zachleat commented 8 years ago

vv-number-giftcard

zachleat commented 8 years ago

Works as expected in Safari 7.

zachleat commented 8 years ago

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

Programmerman1 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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

toddparker commented 8 years ago

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 commented 8 years ago

number-safari

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

Programmerman1 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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:

Feature test would not work.

Safari 6 user typed value:


Firefox 47 setting value with JS:

Feature test would not work.

Firefox 47 user typed value:


Chrome 51 and Safari 9 setting value with JS:

Chrome 51 and Safari 9 user typed value:

Verdict: close but valueAsNumber should probably be NaN


IE11 setting value with JS:

IE11 user typed value:

Verdict: this is how it should work in all browsers

domenic commented 8 years ago

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 commented 8 years ago

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