如何处理浮点数和十进制分隔符与 html5输入类型数

我建立的网络应用程序,主要是为移动浏览器。我使用带有数字类型的输入字段,因此(大多数)移动浏览器只调用数字键盘以获得更好的用户体验。这个 web 应用程序主要用于小数点是逗号而不是点的区域,所以我需要同时处理两个小数分隔符。

如何用点和逗号来掩盖这一切?

我的发现是:

桌面 Chrome

  • 输入 type = number
  • 用户在输入栏输入“4,55”
  • $("#my_input").val();返回“455”
  • 我无法从输入中得到正确的值

桌面火狐

  • 输入 type = number
  • 用户在输入栏输入“4,55”
  • $("#my_input").val();返回“4,55”
  • 这很好,我可以用点代替逗号,得到正确的 float

Android 浏览器

  • 输入 type = number
  • 用户在输入栏输入“4,55”
  • 当输入失去焦点时,值被截断为“4”
  • 让用户感到困惑

Windows Phone 8

  • 输入 type = number
  • 用户在输入栏输入“4,55”
  • $("#my_input").val();返回“4,55”
  • 这很好,我可以用点代替逗号,得到正确的 float

在这种情况下,当用户可能使用逗号或点作为小数点,我希望保留 html 输入类型作为数字,以提供更好的用户体验时,什么是“最佳实践”?

我可以转换逗号点“在动态”,绑定关键事件,它是否与数字输入工作?

剪辑

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

另外,在 Android (测试过的4.2模拟器)中,当我输入“4,55”到输入字段并将焦点转移到其他地方时,输入的数字会被截断为“4”,这非常恼人。

264854 次浏览

使用 valueAsNumber而不是 .val()

Input. valueAsNumber [ = value ]

如果适用,返回表示窗体控件值的数字; 否则返回 null。
可以设置,以更改值。
如果控件既不是基于日期或时间的,也不是数字的,则引发 INVALID _ STATE _ ERR 异常。

根据 w3.org,数字输入价值属性被定义为 浮点数浮点数浮点数。浮点数的语法似乎只接受点作为十进制分隔符。

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

1. 使用 pattern 属性

使用 < a href = “ http://www.w3.org/TR/html5/forms.html # the-pattern-tribute”> 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 验证

您可以尝试将一个简单的回调绑定到例如 改变(和/或 很模糊)事件,该事件要么替换逗号,要么一起验证。

3. 禁用浏览器验证 # #

第三,您可以尝试对数字输入使用 一个 href = “ http://www.w3.org/TR/html5/forms.html # attr-fs-formnovalid”> formnovalid属性,以便禁用该字段的所有浏览器验证。

<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."/>

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

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

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

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

我认为上面的答案中缺少的是需要为 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属性非常有用。

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

下面的小提琴演示了添加 step属性是如何工作的,并测试当前值是否有效:

step属性设置为一个浮点值,因为它默认为 1

注意 : 逗号对我来说不起作用,但是我怀疑如果我将我的操作系统语言/区域设置设置为使用逗号作为小数点,它会起作用。* Note in note * : 这不是 Ubuntu/Gnome 14.04中操作系统语言/键盘设置的情况 * 德语 * 。

听起来像是您希望在数值输入中使用 toLocaleString ()。

请参阅 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString了解其用法。

数字在 JS 中的本地化也包括在 国际化(编号格式为“ num.toLocaleString ()”)不适用于 chrome

是否使用逗号或句号作为小数点完全取决于浏览器。浏览器根据操作系统或浏览器的地区来做出决定,或者一些浏览器从网站上获取提示。我做了一个 浏览器比较图浏览器比较图,展示了不同的浏览器如何支持处理不同的本地化方法。Safari 是唯一可以互换逗号和句点的浏览器。

基本上,你作为一个网络作者不能真正控制这一点。一些变通方法涉及使用两个带有整数的输入字段。这允许每个用户按照您的期望输入数据。它不是特别的性感,但是对所有用户都适用。

当你调用 $("#my_input").val();时,它返回为字符串变量。因此使用 parseFloatparseInt进行转换。 当您使用 parseFloat您的桌面或手机 本身了解变量的含义。

另外,你可以通过使用 toFixed将浮点数转换成字符串,它的参数数字计数如下:

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

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

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

如果用户输入一个逗号,它将输出与逗号在每一个现代浏览器我尝试(最新的 FF,IE,边缘,歌剧,铬,Safari 桌面,机器人铬)。

主要问题是:

  • 移动用户将看到他们的手机键盘可能有所不同 而不是数字键盘。
  • 更糟糕的是,手机键盘甚至可能没有一个逗号键。

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

  • 用逗号显示初始值(firefox 将其删除为 Type = number)
  • 不要让 html5验证失败(如果有逗号)
  • 让该字段准确地作为输入读取(可以使用逗号)

如果你有一个类似的需求,这应该为您工作。

注意: 我不喜欢模式属性的支持。

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

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

Inputmode 标记是解决方案

显然浏览器仍然存在问题(尽管 Chrome 和 Firefox 每晚都运行良好)。 对于那些真正需要使用数字字段的人们,我有一个拙劣的方法(可能是因为文本字段没有小箭头)。

我的解决方案

我在表单输入中添加了一个 keyup事件处理程序,并跟踪状态,并在状态再次有效时设置值。

纯 JS 片段

var currentString = '';
var badState = false;
var lastCharacter = null;


document.getElementById("field").addEventListener("keyup",($event) => {
if ($event.target.value && !$event.target.validity.badInput) {
currentString = $event.target.value;
} else if ($event.target.validity.badInput) {
if (badState && lastCharacter && lastCharacter.match(/[\.,]/) && !isNaN(+$event.key)) {
$event.target.value = ((+currentString) + (+$event.key / 10));
badState = false;
} else {
badState = true;
}
}
document.getElementById("number").textContent = $event.target.value;
lastCharacter = $event.key;
});


document.getElementById("field").addEventListener("blur",($event) => {
if (badState) {
$event.target.value = (+currentString);
badState = false;
document.getElementById("number").textContent = $event.target.value;
}
});
#result{
padding: 10px;
background-color: orange;
font-size: 25px;
width: 400px;
margin-top: 10px;
display: inline-block;
}


#field{
padding: 5px;
border-radius: 5px;
border: 1px solid grey;
width: 400px;
}
<input type="number" id="field" keyup="keyUpFunction" step="0.01" placeholder="Field for both comma separators">


<span id="result" >
<span >Current value: </span>
<span id="number"></span>
</span>

角9片段

@Directive({
selector: '[appFloatHelper]'
})
export class FloatHelperDirective {
private currentString = '';
private badState = false;
private lastCharacter: string = null;


@HostListener("blur", ['$event']) onBlur(event) {
if (this.badState) {
this.model.update.emit((+this.currentString));
this.badState = false;
}
}


constructor(private renderer: Renderer2, private el: ElementRef, private change: ChangeDetectorRef, private zone: NgZone, private model: NgModel) {
this.renderer.listen(this.el.nativeElement, 'keyup', (e: KeyboardEvent) => {
if (el.nativeElement.value && !el.nativeElement.validity.badInput) {
this.currentString = el.nativeElement.value;
} else if (el.nativeElement.validity.badInput) {
if (this.badState && this.lastCharacter && this.lastCharacter.match(/[\.,]/) && !isNaN(+e.key)) {
model.update.emit((+this.currentString) + (+e.key / 10));
el.nativeElement.value = (+this.currentString) + (+e.key / 10);
this.badState = false;
} else {
this.badState = true;
}
}
this.lastCharacter = e.key;
});
}
  

}
<input type="number" matInput placeholder="Field for both comma separators" appFloatHelper [(ngModel)]="numberModel">