HTML输入类型数字千位分隔符

66

我想要在我的输入框中加入千位分隔符(例如1,000,000)。然而,它必须是“数字”类型,因为我需要能够使用“步骤”调整其值。代码:

<input type="number" id='myNumber' value="40,000" step='100'>

我尝试使用JavaScript来调整值,但没有成功。希望得到帮助。谢谢!


1
你可以创建一个自定义控件集来控制“步骤”。 - alex
1
你可以尝试使用autoNumeric插件 http://www.decorplanit.com/plugin/ - Sushil
7
不能在 type=number 中实现该操作。 - charlietfl
2
我非常确定,如果parseFloat()无法解析该值,则“数字”输入字段将无法正常工作。 - Pointy
1
@Sushil 很遗憾,根据文档,autoNumeric不支持输入类型为“number”的元素。 - Alex
显示剩余2条评论
10个回答

11
  • Check this webdesign.tutsplus.com tutorial
  • Final result is summarized here (look at direct Codepen playground)

    $("#formInput".on("keyup", function(event ) {                   
        // When user select text in the document, also abort.
        var selection = window.getSelection().toString(); 
        if (selection !== '') {
            return; 
        }       
        // When the arrow keys are pressed, abort.
        if ($.inArray(event.keyCode, [38, 40, 37, 39]) !== -1) {
            return; 
        }       
        var $this = $(this);            
        // Get the value.
        var input = $this.val();            
        input = input.replace(/[\D\s\._\-]+/g, ""); 
        input = input?parseInt(input, 10):0; 
        $this.val(function () {
            return (input === 0)?"":input.toLocaleString("en-US"); 
        }); 
    }); 
    

注意:

  • toLocaleString() javascript函数可以展示千位分隔符(例子和文档
  • 在控制台中运行下面的代码,可以更好地理解:

    (30000000).toLocaleString('en-US',{useGrouping:true})


2
太棒了,谢谢。我稍微修改了一下,让文本框中保留美元符号,并允许上下箭头按1000递增和递减数值。 https://jsfiddle.net/e3czy926/ - Bill_VA
1
好的解决方案。唯一的缺点是,如果用户按下数字键并快速切换到其他字段,数字将被添加到输入中,但 keyup 事件不会触发,逗号就会出现在错误的位置。 - Paul Evans

9
使用autoNumeric插件,您可以将字段设置为数字输入,并具有不同的分隔符。
包含插件:
<script src="~/Scripts/autoNumeric/autoNumeric.min.js" type="text/javascript"></script>

HTML:

 <input type="text" id="DEMO" data-a-sign="" data-a-dec="," data-a-sep="." class="form-control"> 

脚本:

<script>
 jQuery(function($) {
$('#DEMO').autoNumeric('init');   
 });
</script>

你只能输入数字,如果你输入100000,99,你会看到100.000,99。
更多信息请参见:https://github.com/autoNumeric/autoNumeric

我使用了这个插件。它很棒,但也有一些 bug。当你只想在一个输入元素中使用它时,它可以正常工作,但如果你想用 JavaScript 做一些其他的事情,它会以一种奇怪的方式工作!如果你想使用它,请记住这一点。 - Mahsa
@Mahsa:是的,你说得对。但是对于其他想要解决方案的人,我们现在可以使用watchExternalChanges:true(默认为false)来使用JavaScript管理您的输入(我设置了value和readonly属性)。像这样初始化: let optionsDefault = { ... watchExternalChanges: true, // True when we need to change value by JS. Otherwise, on input hover the value is reset to initial value. unformatOnSubmit: true // on form submit, the rawValue are replacing the formatted value to be sent to server }; new AutoNumeric.multiple('.auto-numeric', null, optionsDefault); - pti_jul
现在是2022年,我使用它来为输入文本框中的大数字添加千位分隔符。它非常好用,特别是配合选项 unformatOnSubmit:true 使用。然而,在我的实现中,我使用了某种确认窗口来阻止提交一段时间,因此我尚未直接测试过提交功能。 - SaidbakR

3
创建一个掩码输入框,显示格式化的数字。此解决方案避免了更改输入框的类型或值。

$("input.mask").each((i,ele)=>{
            let clone=$(ele).clone(false)
            clone.attr("type","text")
            let ele1=$(ele)
            clone.val(Number(ele1.val()).toLocaleString("en"))
            $(ele).after(clone)
            $(ele).hide()
            clone.mouseenter(()=>{

                ele1.show()
                clone.hide()
            })
            setInterval(()=>{
                let newv=Number(ele1.val()).toLocaleString("en")
                if(clone.val()!=newv){
                    clone.val(newv)
                }
            },10)

            $(ele).mouseleave(()=>{
                $(clone).show()
                $(ele1).hide()
            })
            

        })
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="mask" type="number" value="12345.678"/>


这是一个非常有趣且相当可行的解决方案,但我注意到一些小错误:a)当鼠标悬停在输入框上时,逗号会消失。b)当您将光标放在字段中并将鼠标移出该字段后,该字段不会保持聚焦状态。c)通过制表键来聚焦在该字段上时,不会切换到数字输入。如果您将 clone.mouseenter 更改为 clone.focus,则可能可以解决问题 b 和 c。 - amphetamachine

2

在修改https://dev59.com/_lwZ5IYBdhLWcg3wFM3D#70726755后,我成功地实现了以下功能:

  1. 由于未使用Number(),代码实际上并没有添加逗号。
  2. 当初始值为空时,它会删除整个字段。
  3. 没有提供演示。
  4. 不是说原始方法是错误的或者不正确的,但我选择直接在输入框本身上使用onfocusonblur

因此,这是一个修订后的答案:

  • <input type="text">开始。您仍然可以添加minmaxstep属性。
  • onfocusonblur处理程序添加到<input>节点中:

function use_number(node) {
  var empty_val = false;
  const value = node.value;
  if (node.value == '')
    empty_val = true;
  node.type = 'number';
  if (!empty_val)
    node.value = Number(value.replace(/,/g, '')); // or equivalent per locale
}

function use_text(node) {
  var empty_val = false;
  const value = Number(node.value);
  if (node.value == '')
    empty_val = true;
  node.type = 'text';
  if (!empty_val)
    node.value = value.toLocaleString('en');  // or other formatting
}
<input type="text" min=0 onfocus="use_number(this)" onblur="use_text(this)">


2
您可以使用伪元素来显示逗号版本,从而模拟此功能。
div[comma-value]{
  position:relative;
}
div[comma-value]:before{
  content: attr(comma-value);
  position:absolute;
  left:0;
}
div[comma-value] input{
  color:#fff;
}

需要一个包装 div,因为输入框不能有伪元素。

<div>
  <input type="number" id='myNumber' value="40000" step='100'>
</div>

再加上一点JavaScript代码,每三个字符插入一个逗号

myNumber.value = commify(myNumber.value)
myNumber.addEventListener("change", function(){
  commify(event.target.value)
})

function commify(value){
  var chars = value.split("").reverse()
  var withCommas = []
  for(var i = 1; i <= chars.length; i++ ){
    withCommas.push(chars[i-1])
    if(i%3==0 && i != chars.length ){  
      withCommas.push(",")
    }
  }
  var val = withCommas.reverse().join("")
  myNumber.parentNode.setAttribute("comma-value",val)
}

查看fiddle示例。


无法看到输入的过程,可能需要进行一些修改。 - iplus26
这个存在的问题有: 用户可以输入一个值,但伪字段不会更新(您可以添加一个额外的更改监听器来解决此问题); 您仍然可以突出显示数字字段的白色文本。总的来说,这不是一个用户友好或浏览器友好的解决方案。 - jarodsmk
1
我个人不喜欢这个。试着突出输入内容,你自己就会看到了。 - dokgu
2
这在Chrome中有效,但在FF中无效。其他浏览器未尝试过。 - dokgu
它至少应该测试数字是否大于等于1000或小于等于-1000...否则它将失败:http://i.imgur.com/BAfWzaQ.png。 - curly_brackets
2
您不能编辑该值,如果它们需要小数点 - 这在法国或印度数字中无法正常工作。 - web_bod

1

csq 建议使用 jQuery autoNumeric 插件。我发现它非常易于使用。

我唯一的不满是它强制使用 <input type="text"> 而不是 <input type="number">。这意味着您会失去 step 的功能,但您可以让用户在字段中使用逗号。

我想你可以将期望值小于1,000的设置为 <input type="number">,而大于1,000的设置为 <input type="text">


我还没有测试过这个是否适用于移动设备。我怀疑它不是。 - kurdtpage
AutoNumeric支持Android Chrome,正如它们的网站上所说:https://autonumeric.github.io/ - Alex

0

function addCommas(nStr) { ....

除了yovanny的答案外,我还创建了一个使用这个函数的Vue组件。

    Vue.component("in-n", {
    template:
        `<input @keyup="keyup" @keypress="isNumber($event)" v-model="text" type="text" />`,
    props: ["value"],
    data() {
        return {
            text: ""
        }
    },
    methods: {
        addCommas(nStr) {
            nStr += '';
            x = nStr.split('.');
            x1 = x[0];
            x2 = x.length > 1 ? ',' + x[1] : '';
            var rgx = /(\d+)(\d{3})/;
            while (rgx.test(x1)) {
                x1 = x1.replace(rgx, '$1' + ',' + '$2');
            }
            return x1 + x2;
        },
        isNumber: function (evt) {
            evt = (evt) ? evt : window.event;
            var charCode = (evt.which) ? evt.which : evt.keyCode;
            if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) {
                evt.preventDefault();;
            } else {
                return true;
            }
        },
        keyup() {
            this.text = this.addCommas(this.text.replace(/,/g, ''));
            this.$emit("input", parseInt(this.text.replace(/,/g, '')))
        }
    }
})

0

我已经更新了@CollenZhou的回答https://dev59.com/_lwZ5IYBdhLWcg3wFM3D#67295023 ,因为鼠标离开时,输入框会失去焦点,这是很烦人的。我还将所有输入类型数字添加到选择器和类中。

$('input.thousands-separator, input[type="number"]').each((i,ele)=>{
        let clone=$(ele).clone(false)
        clone.attr('type','text')
        let ele1=$(ele)
        clone.val(Number(ele1.val()).toLocaleString('en'))
        $(ele).after(clone)
        $(ele).hide()
        clone.mouseenter(()=>{
            ele1.show()
            clone.hide()
        })
        setInterval(()=>{
            let newv=Number(ele1.val()).toLocaleString('en')
            if(clone.val()!=newv){
                clone.val(newv)
            }
        },10)

        $(ele).mouseleave((event)=>{
            if ($(ele).is(':focus')) {
                event.preventDefault();
            } else {
                $(clone).show()
                $(ele1).hide()
            }
        })
        $(ele).focusout(()=>{
            $(clone).show()
            $(ele1).hide()
        })
    })

0

我找到了一个更简单的答案:

  • <input type="text"> 开始。您仍然可以添加 min、max 和 step 属性。
  • 将 onfocus 和 onblur 处理程序添加到 <input> 节点中:
node.addEventListener('onfocus', () => {
  const value = node.value;
  node.type = 'number';
  node.value = Number(value.replace(/,/g, '')); // or equivalent per locale
});

node.addEventListener('onblur', () => {
  const value = node.value;
  node.type = 'text';
  node.value = value.toLocaleString();  // or other formatting
});

当用户选择输入时,它将转换为一个带有正常微调器的普通数字输入,千位分隔符被删除。当用户模糊输入时,它将恢复格式化文本。
我添加了一个onkeyup处理程序,当按下“enter”键时,它会使输入失焦。

请查看修订后的答案 - LWC

-1

尝试

function addCommas(nStr)
{
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? ',' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

你能否改进你的回答以满足提问者的要求?“我想在我的输入框中添加千位分隔符(例如1,000,000)。”虽然你的函数可能适用于将千位分隔符添加到任意数字,但你的回答并没有回答提问者的问题。 - amphetamachine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接