Javascript 信用卡字段 - 每四个字符添加一个空格 - 退格键无法正常工作

新手上路,请多包涵

我有一个信用卡字段,我想在用户输入其信用卡号时处理。假设用户可以输入数字和字母字符,并且必须每四个字符添加一个空格。输入部分工作正常,但退格键有问题。如果光标在数字上,使用退格键删除是有效的,但当光标在空格上时,它不能正常工作:在这种情况下,用户必须按住退格键才能正确删除一些输入。

另一个要求是让剪贴板操作(复制、剪切、粘贴)在该字段上正常工作。

我不能为解决方案使用任何插件(如 JQuery Mask 插件),如果可能的话,我不会直接使用 keyCode。

更新 的 JS 小提琴: https ://jsfiddle.net/ot2t9zr4/10/

片段

 $('#credit-card').on('keypress change blur', function () {
  $(this).val(function (index, value) {
    return value.replace(/[^a-z0-9]+/gi, '').replace(/(.{4})/g, '$1 ');
  });
});

$('#credit-card').on('copy cut paste', function () {
  setTimeout(function () {
    $('#credit-card').trigger("change");
  });
});
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
  <form class="" action="" method="post">
    <fieldset>
      <legend>Payment</legend>
      <div class="beautiful-field field-group credit-cart">
        <label class="label" for="credit-card">Credit card</label>
        <input class="field" id="credit-card" value="" autocomplete="off" type="text" />
      </div>
    </fieldset>
  </form>
</div>

原文由 ramo102 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 492
2 个回答

仅绑定 keypress 事件并查看。

 $('#credit-card').on('keypress change', function () {
  $(this).val(function (index, value) {
    return value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ');
  });
});

在这里 检查。

原文由 Developer107 发布,翻译遵循 CC BY-SA 3.0 许可协议

Steve Davies 已经指出了这一点,但如果您仅使用 replace() 重新格式化整个值,插入符号位置将始终位于输入值的末尾,如果用户编辑他之前输入的内容,这可能会很烦人。如果插入符号位置在其他地方或者已经做出选择以用新数字替换它,这将导致糟糕的用户体验。

话虽这么说,摆脱这种行为的一个好方法是创建一个自定义替换函数,其中包含一个遍历每个字符的 for 循环,然后您将能够知道插入的空格是否在当前插入符位置之前并更新如果是这样的话。

纯 javascript 解决方案: https ://jsfiddle.net/pmrotule/217u7fru/。

编辑:我添加了对美国运通格式的支持(15 位而不是 16 位)。

 input_credit_card = function(jQinp)
{
    var format_and_pos = function(input, char, backspace)
    {
        var start = 0;
        var end = 0;
        var pos = 0;
        var value = input.value;

        if (char !== false)
        {
            start = input.selectionStart;
            end = input.selectionEnd;

            if (backspace && start > 0) // handle backspace onkeydown
            {
                start--;

                if (value[start] == " ")
                { start--; }
            }
            // To be able to replace the selection if there is one
            value = value.substring(0, start) + char + value.substring(end);

            pos = start + char.length; // caret position
        }

        var d = 0; // digit count
        var dd = 0; // total
        var gi = 0; // group index
        var newV = "";
        var groups = /^\D*3[47]/.test(value) ? // check for American Express
        [4, 6, 5] : [4, 4, 4, 4];

        for (var i = 0; i < value.length; i++)
        {
            if (/\D/.test(value[i]))
            {
                if (start > i)
                { pos--; }
            }
            else
            {
                if (d === groups[gi])
                {
                    newV += " ";
                    d = 0;
                    gi++;

                    if (start >= i)
                    { pos++; }
                }
                newV += value[i];
                d++;
                dd++;
            }
            if (d === groups[gi] && groups.length === gi + 1) // max length
            { break; }
        }
        input.value = newV;

        if (char !== false)
        { input.setSelectionRange(pos, pos); }
    };

    jQinp.keypress(function(e)
    {
        var code = e.charCode || e.keyCode || e.which;

        // Check for tab and arrow keys (needed in Firefox)
        if (code !== 9 && (code < 37 || code > 40) &&
        // and CTRL+C / CTRL+V
        !(e.ctrlKey && (code === 99 || code === 118)))
        {
            e.preventDefault();

            var char = String.fromCharCode(code);

            // if the character is non-digit
            // -> return false (the character is not inserted)

            if (/\D/.test(char))
            { return false; }

            format_and_pos(this, char);
        }
    }).
    keydown(function(e) // backspace doesn't fire the keypress event
    {
        if (e.keyCode === 8 || e.keyCode === 46) // backspace or delete
        {
            e.preventDefault();
            format_and_pos(this, '', this.selectionStart === this.selectionEnd);
        }
    }).
    on('paste', function()
    {
        // A timeout is needed to get the new value pasted
        setTimeout(function()
        { format_and_pos(jQinp[0], ''); }, 50);
    }).
    blur(function() // reformat onblur just in case (optional)
    {
        format_and_pos(this, false);
    });
};

input_credit_card($('#credit-card'));
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
  <form class="" action="" method="post">
    <fieldset>
      <legend>Payment</legend>
      <div class="beautiful-field field-group credit-cart">
        <label class="label" for="credit-card">Credit card</label>
        <input class="field" id="credit-card" value="" autocomplete="off" type="text" />
      </div>
    </fieldset>
  </form>
</div>

原文由 pmrotule 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题