如何使用HTML5输入类型编号处理浮点数和小数点分隔符


128

我正在构建主要用于移动浏览器的Web应用程序。我使用数字类型的输入字段,因此(大多数)移动浏览器仅调用数字键盘以提供更好的用户体验。此Web应用程序主要用于小数点分隔符是逗号而不是点的区域,因此我需要处理两个小数点分隔符。

如何用点和逗号覆盖整个混乱局面?

我的发现:

桌面版Chrome

  • 输入类型=数字
  • 用户在输入字段中输入“ 4,55”
  • $("#my_input").val(); 返回“ 455”
  • 我无法从输入中获取正确的值

桌面版Firefox

  • 输入类型=数字
  • 用户在输入字段中输入“ 4,55”
  • $("#my_input").val(); 返回“ 4,55”
  • 很好,我可以用点替换逗号并获得正确的浮点数

Android浏览器

  • 输入类型=数字
  • 用户在输入字段中输入“ 4,55”
  • 输入失去焦点时,值将被截断为“ 4”
  • 给用户造成困扰

Windows Phone 8

  • 输入类型=数字
  • 用户在输入字段中输入“ 4,55”
  • $("#my_input").val(); 返回“ 4,55”
  • 很好,我可以用点替换逗号并获得正确的浮点数

当用户可能使用逗号或点作为小数点分隔符并且我想将html输入类型保留为数字以提供更好的用户体验时,这种情况下的“最佳做法”是什么?

我可以将逗号转换为点播中的点,绑定键事件吗,它可以用于数字输入吗?

编辑

Currenlty我没有任何解决方案,如何从类型设置为数字的输入中获取浮点值(字符串或数字)。如果最终用户输入“ 4,55”,则Chrome始终返回“ 455”,Firefox返回“ 4,55”,可以。

同样令人烦恼的是,在Android(经过测试的4.2仿真器)中,当我输入“ 4,55”以输入字段并将焦点更改为其他位置时,输入的数字将被截断为“ 4”。


我的猜测是某些问题的根本原因是浏览器设置为使用点作为小数点分隔符的美国语言环境。Chrome和Android似乎以不同的方式对此感到困惑-Chrome将逗号视为数字分隔符,然后将输入转换为数字,然后再次将其转换为字符串.val(),Android则有些奇怪。将系统语言设置为适当的语言时,是否可以检查它们的行为是否相同?
millimoose

1
Nvm将此作为答案发布
kjetilh 2013年


这种情况甚至比您描述的还要糟糕:根据选择的键盘语言,WP数字键盘上会出现小数点或逗号。也没有办法找出哪个是输入语言环境(不一定是首选的浏览器语言)...因此,我能想到的最好的方法(以及对我来说足够好的方法)是: var number = $(...).get(0).valueAsNumber; if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.'); 但是,只有当已放入的数字只包含1个逗号,没有多余的点...
bert bruynooghe 2015年

Answers:


107

我认为上述答案中缺少的是需要为step属性指定其他值,该属性的默认值为1。如果希望输入的验证算法允许浮点值,请相应地指定一个步骤。

例如,我想要美元金额,因此我指定了以下步骤:

 <input type="number" name="price"
           pattern="[0-9]+([\.,][0-9]+)?" step="0.01"
            title="This should be a number with up to 2 decimal places.">

使用jQuery检索值没有错,但是您会发现直接使用DOM API来获取元素的validity.valid属性很有用。

我的小数点也有类似的问题,但是我意识到存在问题的原因是因为Twitter Bootstrap的样式添加到具有无效值的数字输入中。

这是一个小提琴,它证明了添加step属性使它起作用,并且还测试了当前值是否有效:

TL; DR: 将a step属性设置为浮点值,因为它的默认值为1

注意:逗号不能为我验证,但是我怀疑如果我将OS语言/区域设置设置为使用逗号作为小数点分隔符的某处,它将起作用。*注意*:在Ubuntu / Gnome 14.04中,操作系统语言/键盘设置*德语*并非如此。


8
如果要允许任意多个小数位,请将该step属性指定为,"any"而不是例如"0.01"此处所示。观看nathciketa的小提琴的调整后版本以进行演示。
Mark Amery 2014年

4
我还遇到了逗号无法验证的问题,尽管我在中输入了“ 1,234.56” <input type="number" step="any">。我还没有找到关闭HTML5验证的方法。我可以关闭或自定义错误消息,但是从输入中检索值始终是错误的。有任何想法吗?
尼克G.

5
This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.因此,这种模式毫无用处type="number"
迈克尔·拉法格

就像michael所说,请将更改typetext,否则您的答案没有任何意义。
phil294

23

根据w3.org,数字输入value属性定义为浮点数。浮点数的语法似乎只接受点作为小数点分隔符。

我在下面列出了一些可能对您有帮助的选项:

1.使用模式属性

使用pattern属性,可以以兼容HTML5的方式用正则表达式指定允许的格式。在这里,您可以指定允许使用逗号,如果模式失败,则可以提供有用的反馈消息。

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" name="my-num"
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

注意:跨浏览器的支持差异很大。它可能是完整的,部分的或不存在的。

2. JavaScript验证

您可以尝试将一个简单的回调绑定到例如onchange(和/或blur)事件,该事件将替换逗号或一起验证所有事件。

3.禁用浏览器验证##

第三,您可以尝试在数字输入上使用formnovalidate属性,以完全禁用该字段的浏览器验证。

<input type="number" formnovalidate />

4.组合..?

<input type="number" pattern="[0-9]+([,\.][0-9]+)?" 
           name="my-num" formnovalidate
           title="The number input must start with a number and use either comma or a dot as a decimal character."/>

2
input.valueAsNumber- 没有帮助,因为它仅适用于以点作为小数点分隔符,在我的情况下,最终用户可能使用点或逗号。 表单标签novalidate-对此没有任何影响。
devha 2013年

不幸的是,我的想法不多了,所以我不确定如果没有解决方法,您是否能够跨浏览器进行这项工作。我已经更新了答案,包括了pattern属性,我还发现可以直接在输入字段上使用formnovalidate属性。我知道你不会喜欢它,但如果一切都失败,你绝对需要逗号,然后输入=“文本”可能是唯一的方式..
kjetilh

看起来输入类型编号产生的问题比实际改善用户体验的问题更多。在移动设备中,如果我希望用户仅输入数字,则只能对用户打开数字键盘,那就太好了。无论如何,我需要重新考虑一下……
devha 2013年

因为我们还需要支持使用点和逗号作为小数点分隔符,所以我们计划结合使用type =“ text”将模式用于桌面验证。然后,我们将添加功能检测以检测移动设备,并在适用时使用type =“ number”。
2014年

9

对于小数点分隔符使用逗号还是句点完全取决于浏览器。浏览器根据操作系统或浏览器的区域设置做出决定,或者某些浏览器从网站获取提示。我制作了一个浏览器比较表,显示了不同的浏览器支持如何处理不同的本地化方法。Safari是唯一可互换处理逗号和句点的浏览器。

基本上,作为网络作者,您无法真正控制它。一些解决方法涉及使用两个带有整数的输入字段。这样,每个用户都可以按预期输入数据。它不是特别性感,但是在所有情况下都适用于所有用户。


7

使用valueAsNumber代替.val()

输入。valueAsNumber [=值]

返回一个表示表单控件值的数字(如果适用);否则,返回null。
可以设置,更改值。
如果控件既不是基于日期或时间的也不是数字的,则抛出INVALID_STATE_ERR异常。


2
问题是他想支持逗号作为小数点分隔符,并且在输入逗号时始终在输入上使用type =“ number”给出无效数字。
2014年

似乎在Windows Phone上无法始终如一地工作;总是返回NaN
bert bruynooghe,2015年

@bertbruynooghe,您要分配什么作为值?
Mike Samuel

似乎不起作用,也不能与'9','9,1','9.1'一起使用。电话配置为美国,键盘布局通过en-US,nl-BE测试。
bert bruynooghe'2

4

使用文本类型,但强制使用数字键盘

<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">

inputmode标签是解决方案


但是它并不与所有浏览器兼容,仅与iOS Safari,Chrome,Chromium,Opera的最新版本兼容... caniuse.com/#feat=input-inputmode :(
pgarciacamou

另外,您在移动设备上没有这种简洁的数字键盘。
WoIIe

3

我还没有找到一个完美的解决方案,但是我能做的最好的就是使用type =“ tel”并禁用html5验证(formnovalidate):

<input name="txtTest" type="tel" value="1,200.00" formnovalidate="formnovalidate" />

如果用户输入逗号,它将在我尝试的每种现代浏览器(最新FF,IE,edge,opera,chrome,safari桌面,android chrome)中与逗号一起输出。

主要问题是:

  • 移动用户将看到其电话键盘可能与数字键盘不同。
  • 更糟糕的是,电话键盘甚至可能没有逗号键。

对于我的用例,我只需要:

  • 用逗号显示初始值(Firefox将其剥离为type = number)
  • 不会通过html5验证(如果有逗号)
  • 让字段完全按输入读取(可能用逗号)

如果您有类似的要求,这应该适合您。

注意:我不喜欢pattern属性的支持。该formnovalidate似乎更好地工作。


1

调用时,$("#my_input").val();它作为字符串变量返回。因此使用parseFloatparseInt进行转换。当您使用parseFloat台式机或电话时,ITSELF会理解变量的含义。

另外,您还可以通过以下方式将浮点数转换为字符串toFixed

var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01

不起作用。尝试在IE11中使用parseFloat(“ 1,5”)。返回值1. OS和IE的语言均为德语。
T3rm1 '16

1

显然,浏览器仍然有麻烦(尽管Chrome和Firefox Nightly可以正常工作)。对于确实需要使用数字字段的人,我有一个拙劣的做法(也许是因为文本字段没有小箭头)。

我的解决方案

keyup在表单输入中添加了一个事件处理程序,并跟踪状态并在该值再次生效后对其进行设置。

纯JS代码段 JSFIDDLE

Angular 9代码段


0

我的推荐?完全不要使用jQuery。我和你有同样的问题。我发现$('#my_input').val()总是返回一些奇怪的结果。

尝试使用document.getElementById('my_input').valueAsNumber代替,$("#my_input").val();然后使用Number(your_value_retrieved)尝试创建一个数字。如果值为NaN,则您肯定会知道这不是数字。

要添加的一件事是,当您在输入上写一个数字时,输入实际上将接受几乎任何字符(我可以写欧元符号,美元和所有其他特殊字符),因此最好使用.valueAsNumber而不是使用jQuery。

哦,顺便说一句,这允许您的用户添加国际化(即:支持逗号而不是点来创建十进制数字)。可以说,只要让该Number()对象为您创建东西,它将是十进制安全的。


该问题不是由jQuery引起的,而且我发现valueAsNumber在浏览器中也无法始终如一地工作。
bert bruynooghe,2015年

0

听起来好像您想在数字输入上使用toLocaleString()。

有关其用法,请参见https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString

不适用于chrome的国际化(数字格式为“ num.toLocaleString()”)也涵盖了JS中数字的本地化


2
即使答案完全被链接的内容覆盖,通常也要对解决方案进行更多说明。
IvanH

如果后端服务器确定语言环境而不是浏览器本身,则此方法似乎比其他方法更好。不幸的是,toLocaleString跨平台并不可靠。
bert bruynooghe

跨平台支持似乎足够宽,我在2015年看到如Mozillas国际信息发展。但是,如果您仍然很担心,请在此处找到可能的解决方案。
stackasec 2015年

Mozillas Devnet对移动浏览器几乎不显示任何兼容性,而这正是数字文本字段可以提供最大好处的地方。(请参阅原始问题。)
bert bruynooghe,2015年

...并且已经显示和引用了足够多的替代方法。玩得开心。
stackasec 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.