用于货币/货币的 html5 输入

Posted

技术标签:

【中文标题】用于货币/货币的 html5 输入【英文标题】:html5 input for money/currency 【发布时间】:2014-08-01 13:37:22 【问题描述】:

我似乎不知道用什么来接受表格上的货币值。

我试过了……

<input type="number" min="0" max="10000" step="1" name="Broker_Fees" id="broker_fees" required="required">

但是这样就不允许输入便士了。

我希望增量按钮控件以磅为单位,但仍希望能够输入便士。

谁愿意使用一次移动 1p 的增量按钮?

也许我使用了错误的控件,但我找不到货币/货币控件?

有人可以建议使用 html5 接受货币值(包括逗号、小数位和货币符号)的最佳方式吗?

【问题讨论】:

您必须指定带小数位的step 属性。见:Is there a float input type in HTML(5)? 请再次阅读该问题,并确保您理解我已经这样做了,它会产生不希望的结果......在这种情况下,这怎么可能是另一个线程的重复。 嗯,您要求的是“接受货币价值的最佳方式”。接受输入与提供替代输入方法不同。使用数字输入,用户仍然可以直接插入与给定属性匹配的有效数字。你仍然可以添加额外的按钮,以磅为单位增加…… 不幸的是,您无法使用 HTML5 来控制它。但也许这对你来说可能很有趣:jsfiddle.net/trixta/UC6tG/embedded/result,html,js,css 感谢 farkas,但我似乎无法让它工作,旋转按钮没有任何作用,我也无法输入输入。似乎适用于 FF 但不适用于 IE 【参考方案1】:

为数字输入启用分数/分/小数

为了在 HTML5 数字输入中允许分数(美分),您需要将“step”属性指定为 =“any”:

<input type="number" min="1" step="any" />

这将专门防止 Chrome 在输入小数/小数货币时显示错误。 Mozilla、IE 等...如果您忘记指定 step="any",请不要出错。 W3C 规范指出 step="any" 确实应该需要允许小数。所以,你绝对应该使用它。 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number#step

请注意,如果您希望向上/向下按钮执行特定粒度,则必须指定数字步长,例如“.01”。

此外,数字输入现在得到了相当广泛的支持(>90% 的用户)。


货币/货币有哪些输入选项?

此后问题的标题已更改,含义略有不同。可以同时使用数字或文本输入来接受货币/小数。

对于货币/货币的输入字段,建议使用数字输入类型并指定适当的属性,如上所述。截至 2020 年,没有针对货币或货币的实际输入类型的 W3C 规范。

主要原因是它自动强制用户输入有效的标准货币格式并禁止任何字母数字文本。话虽如此,您当然可以使用常规文本输入并进行一些后处理以仅获取数字/十进制值(在某些时候也应该对此进行服务器端验证)。

OP 详细说明了货币符号和逗号的要求。如果您想要更高级的逻辑/格式,(截至 2020 年),您需要为文本输入创建自定义 JS 逻辑或查找插件。

【讨论】:

【参考方案2】:

使用javascript的Number.prototype.toLocaleString:

var currencyInput = document.querySelector('input[type="currency"]')
var currency = 'GBP' // https://www.currency-iso.org/dam/downloads/lists/list_one.xml

 // format inital value
onBlur(target:currencyInput)

// bind event listeners
currencyInput.addEventListener('focus', onFocus)
currencyInput.addEventListener('blur', onBlur)


function localStringToNumber( s )
  return Number(String(s).replace(/[^0-9.-]+/g,""))


function onFocus(e)
  var value = e.target.value;
  e.target.value = value ? localStringToNumber(value) : ''


function onBlur(e)
  var value = e.target.value

  var options = 
      maximumFractionDigits : 2,
      currency              : currency,
      style                 : "currency",
      currencyDisplay       : "symbol"
  
  
  e.target.value = (value || value === 0) 
    ? localStringToNumber(value).toLocaleString(undefined, options)
    : ''
input
  padding: 10px;
  font: 20px Arial;
  width: 70%;
&lt;input type='currency' value="123" placeholder='Type a number &amp; click outside' /&gt;

? Here's a very simple demo 说明上述方法(仅限 HTML)


如果有人感兴趣,我制作了一个小小的React component

【讨论】:

这是一个简洁的解决方案,但要注意 localStringToNumber 转换对于某些国家/地区的用户来说会失败。例如,法国使用逗号作为小数点。在这种情况下,123 的起始值被转换为 123,00(正确),但随后在焦点处变为 12300,在模糊处变为 12300,00。本质上,每个焦点和模糊都会无意中将值乘以 100! @peteredhead - 如何重现?您是否将 currency 变量更改为其他变量? toLocaleString 的第一个参数是用于格式化的语言环境。在您的代码中,它设置为未定义,因此使用浏览器/系统设置。如果您想测试它对另一个国家/地区的用户的工作方式,您可以将其设置为“fr-FR”,例如 非常有趣。这是一个list of countries,它使用 comma小数点 I see it is very difficult 将数字(在表示为 Strings 的不同语言环境中)转换回数字。有许多不同的数字系统。它需要检测正确的语言环境并相应地应用转换函数。许多转换函数要提前准备好,这会使代码库膨胀。好伤心。【参考方案3】:

我偶然发现这篇文章正在寻找类似的答案。我阅读了@vsync 示例Using javascript's Number.prototype.toLocaleString:,它似乎运行良好。我唯一的抱怨是,如果你的页面中有多个input type="currency",它只会修改它的第一个实例。

正如他在他的 cmets 中提到的,它只是作为 *** 的示例而设计的。

然而,这个例子对我来说效果很好,虽然我对 JS 的经验很少,但我想出了如何修改它,以便它可以在页面上使用 document.querySelectorAll 而不是 document.querySelector 与多个 input type="currency" 一起使用添加一个 for 循环。

我希望这对其他人有用。 (大部分代码的功劳是@vsync)

var currencyInput = document.querySelectorAll( 'input[type="currency"]' );

for ( var i = 0; i < currencyInput.length; i++ ) 

    var currency = 'GBP'
    onBlur( 
        target: currencyInput[ i ]
     )

    currencyInput[ i ].addEventListener( 'focus', onFocus )
    currencyInput[ i ].addEventListener( 'blur', onBlur )

    function localStringToNumber( s ) 
        return Number( String( s ).replace( /[^0-9.-]+/g, "" ) )
    

    function onFocus( e ) 
        var value = e.target.value;
        e.target.value = value ? localStringToNumber( value ) : ''
    

    function onBlur( e ) 
        var value = e.target.value

        var options = 
            maximumFractionDigits: 2,
            currency: currency,
            style: "currency",
            currencyDisplay: "symbol"
        

        e.target.value = ( value || value === 0 ) ?
            localStringToNumber( value ).toLocaleString( undefined, options ) :
            ''
    

    var currencyInput = document.querySelectorAll( 'input[type="currency"]' );

    for ( var i = 0; i < currencyInput.length; i++ ) 

        var currency = 'GBP'
        onBlur( 
            target: currencyInput[ i ]
         )

        currencyInput[ i ].addEventListener( 'focus', onFocus )
        currencyInput[ i ].addEventListener( 'blur', onBlur )

        function localStringToNumber( s ) 
            return Number( String( s ).replace( /[^0-9.-]+/g, "" ) )
        

        function onFocus( e ) 
            var value = e.target.value;
            e.target.value = value ? localStringToNumber( value ) : ''
        

        function onBlur( e ) 
            var value = e.target.value

            var options = 
                maximumFractionDigits: 2,
                currency: currency,
                style: "currency",
                currencyDisplay: "symbol"
            

            e.target.value = ( value || value === 0 ) ?
                localStringToNumber( value ).toLocaleString( undefined, options ) :
                ''
        
    
.input_date 
    margin:1px 0px 50px 0px;
    font-family: 'Roboto', sans-serif;
    font-size: 18px;
    line-height: 1.5;
    color: #111;
    display: block;
    background: #ddd;
    height: 50px;
    border-radius: 5px;
    border: 2px solid #111111;
    padding: 0 20px 0 20px;
    width: 100px;
    <label for="cost_of_sale">Cost of Sale</label>
    <input class="input_date" type="currency" name="cost_of_sale" id="cost_of_sale" value="0.00">

    <label for="sales">Sales</label>
    <input class="input_date" type="currency" name="sales" id="sales" value="0.00">

     <label for="gm_pounds">GM Pounds</label>
     <input class="input_date" type="currency" name="gm_pounds" id="gm_pounds" value="0.00">

【讨论】:

这也是一种将事件绑定到多个元素的非常低效的方式。大约十年来,正确的方法是事件委托【参考方案4】:

如果你有 vue.js 会更简单漂亮 v-money-spinner :)

【讨论】:

【参考方案5】:

var currencyInput = document.querySelector('input[type="currency"]')
var currency = 'USD' // https://www.currency-iso.org/dam/downloads/lists/list_one.xml

 // format inital value
onBlur(target:currencyInput)

// bind event listeners
currencyInput.addEventListener('focus', onFocus)
currencyInput.addEventListener('blur', onBlur)


function localStringToNumber( s )
  return Number(String(s).replace(/[^0-9.-]+/g,""))


function onFocus(e)
  var value = e.target.value;
  e.target.value = value ? localStringToNumber(value) : ''


function onBlur(e)
  var value = e.target.value

  var options = 
      maximumFractionDigits : 2,
      currency              : currency,
      style                 : "currency",
      currencyDisplay       : "symbol"
  
  
  e.target.value = value 
    ? localStringToNumber(value).toLocaleString(undefined, options)
    : ''
input
  padding: 10px;
  font: 20px Arial;
  width: 70%;
&lt;input type='currency' value="123" placeholder='Type a number &amp; click outside' /&gt;

【讨论】:

请补充一些解释性的cmets 这里已经有一个 +40 票的答案,该答案是在您回答前一年发布的,而您只是复制了它。 ***.com/a/54534797/1311025【参考方案6】:

尝试使用step="0.01",那么它每次都会增加一分钱。

例如:

&lt;input type="number" min="0.00" max="10000.00" step="0.01" /&gt;

【讨论】:

这很好用。但值得注意的是,它会循环显示像“1.28...1.29...1.3...1.31...”这样的数字。 IE。没有尾随零(因为它是数字而不是货币)。相关:How can I make the HTML5 number field display trailing zeroes? 请记住,并非所有语言的货币系统都使用十进制。【参考方案7】:

我们在接受欧元的货币值时遇到了同样的问题,因为&lt;input type="number" /&gt; 无法显示欧元十进制和逗号格式。

我们想出了一个解决方案,使用&lt;input type="number" /&gt; 进行用户输入。用户输入值后,我们将其格式化并显示为欧元格式,只需切换到&lt;input type="text" /&gt;。这是一个 Javascript 解决方案,因为您需要一个条件来决定“用户正在输入”和“向用户显示”模式。

这里是我们解决方案的 Visuals 链接: Input field type "Currency" problem solved

希望这在某种程度上有所帮助!

【讨论】:

你能修复链接吗?它坏了【参考方案8】:

最后我不得不通过实现 HTML5/CSS 解决方案做出妥协,放弃了 IE 中的增量按钮(无论如何,它们在 FF 中有点坏了!),但获得了 JQuery 微调器不提供的数字验证。虽然我不得不走整数的一步。

span.gbp 
    float: left;
    text-align: left;


span.gbp::before 
    float: left;
    content: "\00a3"; /* £ */
    padding: 3px 4px 3px 3px;


span.gbp input 
     width: 280px !important;
<label for="broker_fees">Broker Fees</label>
<span class="gbp">
    <input type="number" placeholder="Enter whole GBP (&pound;) or zero for none" min="0" max="10000" step="1" value="" name="Broker_Fees" id="broker_fees" required="required" />
</span>

跨浏览器的验证有点不稳定,其中 IE/FF 允许逗号和小数位(只要它是 .00),而 Chrome/Opera 则不需要并且只需要数字。

我想 JQuery 微调器不能与数字类型输入一起工作是一种耻辱,但文档明确声明不要这样做:-( 我很困惑为什么数字微调器小部件允许输入任何ascii 字符?

【讨论】:

上面的 JSFiddle - jsfiddle.net/yz9w9g3r JSFiddle 的调整,但可以更好地定位货币字符 - jsfiddle.net/yz9w9g3r/1 很好,但应该注意这不是一个非常国际化的解决方案。 (话又说回来,浏览器还没有为&lt;input type="number"&gt; 提供 i18n 功能,或者:***.com/questions/15303940/…)

以上是关于用于货币/货币的 html5 输入的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery/JS 键入时使用 1000 个分隔符和 2 个小数位格式化货币输入?

iOS 货币输入栏

在输入掩码货币中更改货币符号或将其删除

如何为离子输入实现货币输入指令

SwiftUI TextField 中的货币输入

React-native 货币输入