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

ram*_*102 6 javascript jquery

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

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

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

更新了 JS Fiddle: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");
  });
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

Dev*_*107 21

keypress仅绑定事件并查看.

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

点击这里.

  • 您可能希望在末尾添加`.trim()`以允许退格 (3认同)
  • 如果您错过了一个数字并尝试返回输入它,这将是一场灾难:-( (3认同)

Mag*_*giQ 5

由于我不能只回复 Developer107 的评论;如果您只想要数字(使用正则表达式并且不想在字段上指定它。您可以这样做:

$('#credit-card').on('keypress change', function () {
   $(this).val(function (index, value) {
       return value.replace(/[^0-9]/g, "").replace(/\W/gi, '').replace(/(.{4})/g, '$1 ');
   });
});
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/ot2t9zr4/4/

  • 是的,我知道这一点;这就是为什么我说我不能只回复他的评论,因为我还没有 50 分! (3认同)

pmr*_*ule 5

史蒂夫戴维斯已经指出了这一点,但如果你只重新编码整个值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'));
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


ril*_*221 5

我想分享我的解决方案,以防有人仍在努力实现所需的效果。

我的代码是@tonybrasunas 答案的改进版本。它将每 4 个字符添加空格,过滤掉非数字字符,固定字符位置,退格,并且仅在字符有效时向前移动光标,但仍然允许使用有效字符进行推送。


// FORMAT CC FIELD
//

$('#credit-card').on('input', function () {

  $(this).val(function (index, value) {
  
    // Store cursor position

    let cursor = $(this).get(0).selectionStart;
    
    // Filter characters and shorten CC (expanded for later use)
    
    const filterSpace = value.replace(/\s+/g, '');
    const filtered = filterSpace.replace(/[^0-9]/g, '');
    
    const cardNum = filtered.substr(0, 16);
    
    // Handle alternate segment length for American Express
    
    const partitions = cardNum.startsWith('34') || cardNum.startsWith('37') ? [4,6,5] : [4,4,4,4];
    
    // Loop through the validated partition, pushing each segment into cardNumUpdated
    
    const cardNumUpdated = [];
    let position = 0;
    
    partitions.forEach(expandCard => {
    
      const segment = cardNum.substr(position, expandCard);
      if (segment) cardNumUpdated.push(segment);
      position += expandCard;
      
    });
    
    // Combine segment array with spaces

    const cardNumFormatted = cardNumUpdated.join(' ');
    
    // Handle cursor position if user edits the number later
    
    if (cursor < cardNumFormatted.length - 1) {
        
      // Determine if the new value entered was valid, and set cursor progression
    
        cursor = filterSpace !== filtered ? cursor - 1 : cursor;
      
      setTimeout(() => {
      
        $(this).get(0).setSelectionRange(cursor, cursor, 'none');
        
      });
      
    }
    
    return cardNumFormatted;
    
  })
  
});

//
// END OF FORMAT CC FIELD

Run Code Online (Sandbox Code Playgroud)