我正在构建主要用于移动浏览器的网络应用程序。我使用数字类型的输入字段,因此(大多数)移动浏览器仅调用数字键盘以获得更好的用户体验。这个网络应用程序主要用于小数点分隔符是逗号而不是点的区域,所以我需要处理两个小数点分隔符。
如何用点和逗号覆盖整个混乱?
我的发现:
桌面铬
输入类型=数字
用户输入“4,55”输入字段
$("#my_input").val();返回“455”
我无法从输入中获得正确的值
桌面火狐
输入类型=数字
用户输入“4,55”输入字段
$("#my_input").val();返回“4,55”
没关系,我可以用点替换逗号并获得正确的浮点数
安卓浏览器
输入类型=数字
用户输入“4,55”输入字段
当输入失去焦点时,值被截断为“4”
让用户感到困惑
视窗电话 8
输入类型=数字
用户输入“4,55”输入字段
$("#my_input").val();返回“4,55”
没关系,我可以用点替换逗号并获得正确的浮点数
在这种情况下,当用户可能使用逗号或点作为小数点分隔符并且我想将 html 输入类型保留为数字以提供更好的用户体验时,有哪些“最佳实践”?
我可以将逗号“即时”转换为点,绑定键事件,它是否与数字输入一起使用?
编辑
目前我没有任何解决方案,如何从类型设置为数字的输入中获取浮点值(作为字符串或数字)。如果最终用户输入“4,55”,Chrome 总是返回“455”,Firefox 返回“4,55”,这很好。
同样令人讨厌的是,在 Android(经过测试的 4.2 模拟器)中,当我输入“4,55”以输入字段并将焦点更改为其他位置时,输入的数字会被截断为“4”。
.val()
的字符串,Android 做了一些奇怪的事情。当您将系统语言设置为适当的语言时,您能否检查它们的行为是否相同?
var number = $(...).get(0).valueAsNumber;
if (isNaN(number)) number = parseFloat($(...).val().replace(',', '.');
但是该解决方案仅在输入的数字仅包含 1 个逗号且没有多余的点时才有效...
我认为上述答案中缺少的是需要为 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
属性使其工作,并测试当前值是否有效:
jsFiddle
TL;DR: 将 step
属性设置为浮点值,因为它默认为 1
。
注意:逗号对我无效,但我怀疑如果我将操作系统语言/区域设置设置为使用逗号作为小数分隔符的某个位置,它会起作用。 *注中*:在 Ubuntu/Gnome 14.04 中,操作系统语言/键盘设置 *德语* 不是这种情况。
根据 w3.org,number input 的 value 属性被定义为 floating-point number。浮点数的语法似乎只接受点作为小数分隔符。
我在下面列出了一些可能对您有帮助的选项:
1.使用pattern属性
使用 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(和/或模糊)事件。
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."/>
是否使用逗号或句点作为小数点分隔符完全取决于浏览器。浏览器根据操作系统或浏览器的语言环境做出决定,或者某些浏览器从网站中获取提示。我制作了一个 browser comparison chart,展示了不同的浏览器支持如何处理不同的本地化方法。 Safari 是唯一可以互换处理逗号和句点的浏览器。
基本上,您作为网络作者无法真正控制这一点。一些变通方法涉及使用两个带整数的输入字段。这允许每个用户按照您的期望输入数据。它不是特别性感,但它适用于所有用户。
使用 valueAsNumber
而不是 .val()
。
输入 。 valueAsNumber [ = value ] 如果适用,则返回表示表单控件值的数字;否则,返回 null。可以设置,改变值。如果控件既不是基于日期或时间的也不是数字的,则引发 INVALID_STATE_ERR 异常。
NaN
。
使用文本类型但强制显示数字键盘
<input value="12,4" type="text" inputmode="numeric" pattern="[-+]?[0-9]*[.,]?[0-9]+">
inputmode 标签是解决方案
我还没有找到完美的解决方案,但我能做的最好的就是使用 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 验证(如果有逗号)
让字段与输入完全相同(可能带有逗号)
如果您有类似的要求,这应该适合您。
注意:我不喜欢对模式属性的支持。 formnovalidate 似乎工作得更好。
当您调用 $("#my_input").val();
时,它会作为字符串变量返回。所以使用 parseFloat
和 parseInt
进行转换。当您使用 parseFloat
时,您的桌面或手机 ITSELF 会理解变量的含义。
另外,您可以使用 toFixed
将浮点数转换为字符串,该参数具有如下位数的参数:
var i = 0.011;
var ss = i.toFixed(2); //It returns 0.01
显然浏览器仍然有问题(尽管 Chrome 和 Firefox Nightly 做得很好)。对于那些真正必须使用数字字段的人,我有一个 hacky 方法(可能是因为文本字段没有的小箭头)。
我的解决方案
我在表单输入中添加了一个 keyup
事件处理程序并跟踪状态并在它再次有效时设置值。
纯 JS 片段 JSFIDDLE
var currentString = '';变坏状态 = 假; 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;最后一个字符 = $event.key; }); document.getElementById("field").addEventListener("blur",($event) => { if (badState) { $event.target.value = (+currentString); badState = false; document.getElementById("number" ).textContent = $event.target.value; } }); #result{ 填充:10px;背景颜色:橙色;字体大小:25px;宽度:400px;边距顶部:10px;显示:内联块; } #field{ 填充:5px;边框半径:5px;边框:1px 纯灰色;宽度:400px; } 当前值:
Angular 9 片段
@Directive({ selector: '[appFloatHelper]' }) 导出类 FloatHelperDirective { private currentString = '';私人坏状态=假;私人最后一个字符:字符串=空; @HostListener("blur", ['$event']) onBlur(event) { if (this.badState) { this.model.update.emit((+this.currentString)); this.badState = false; } } 构造函数(私有渲染器:Renderer2,私有 el:ElementRef,私有更改:ChangeDetectorRef,私有区域:NgZone,私有模型: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; }); } }
我的推荐?根本不要使用 jQuery。我和你有同样的问题。我发现 $('#my_input').val()
总是返回一些奇怪的结果。
尝试使用 document.getElementById('my_input').valueAsNumber
而不是 $("#my_input").val();
,然后使用 Number(your_value_retrieved)
尝试创建一个数字。如果值为 NaN,您肯定知道这不是一个数字。
要添加的一件事是,当您在输入上写一个数字时,输入实际上将接受几乎任何字符(我可以写欧元符号、美元和所有其他特殊字符),因此最好使用检索值.valueAsNumber
而不是使用 jQuery。
哦,顺便说一句,这允许您的用户添加国际化(即:支持逗号而不是点来创建十进制数字)。只需让 Number()
对象为您创建一些东西,它就会是十进制安全的,可以这么说。
valueAsNumber
在浏览器中也无法始终如一地工作。
听起来您想在数字输入上使用 toLocaleString() 。
Internationalization(Number formatting "num.toLocaleString()") not working for chrome 中还介绍了 JS 中数字的本地化
toLocaleString
跨平台不可靠。
step
属性指定为"any"
而不是例如此处所示的"0.01"
。有关演示,请参阅 nathciketa 的小提琴 this tweaked version。<input type="number" step="any">
中输入了“1,234.56”,但我也遇到了逗号无法验证的问题。我还没有找到关闭 HTML5 验证的方法。我可以关闭或自定义错误消息,但从输入中检索值总是一个废话。有任何想法吗?This attribute applies when the value of the type attribute is text, search, tel, url, email, or password, otherwise it is ignored.
所以模式对type="number"
没有用处type
更改为text
,否则您的回答毫无意义。