4
\$\begingroup\$

How to make my script shorter and better? This code allows only digits, auto-format card number like this XXXX XXXX XXXX XXXX. If the user hits delete or backspace to delete space in between digits, nothing happens caret just moves 1 space forward or backward, it depends on which key user pressed (delete or backspace). If user hits backspace after digit and the previous second symbol is space then backspace deletes the digit and moves 2 spaces back like this (XXXX X|XXX XXXX XXXX -> XXXX| XXXX XXXX XXX ). Delete key dose the same but vice versa like this (XXX|X XXXX XXXX XXXX -> XXXX |XXXX XXXX XXX ). It also allows ctrl+c,ctrl+v,ctrl+a,ctrl+x.

let input = document.querySelector('input');

input.addEventListener('keyup', function (e) {
    let cursor = input.selectionStart;
    let inpVal = input.value;
    let cardCode = inpVal.replace(/\s/g, '').substring(0, 16);
    cardCode = cardCode != '' ? cardCode.match(/.{1,4}/g).join(' ') : '';
    input.value = cardCode;
    let key = e.keyCode || e.which;
    // let ctrl = e.ctrlKey || key === 17 || e.metaKey;
    if ((key >= 48 && key <= 57) || (key >= 96 && key <= 105)) {
        if (cursor < parseInt(inpVal.length)) {
            input.selectionEnd = cursor;
        }
    } else if (key == 8) {
        if (input.value[cursor - 1] == ' ') {
            input.selectionEnd = cursor - 1;
        } else {
            input.selectionEnd = cursor;
        }
    } else if (key == 46) {
        if (input.value[cursor + 1] == ' ') {
            input.selectionEnd = cursor + 2;
        } else {
            input.selectionEnd = cursor;
        }
    }
});
input.addEventListener('keydown', function (e) {
    let inpVal = input.value;
    let cursor = input.selectionStart;
    let key = e.keyCode || e.which;
    let ctrl = e.ctrlKey || key === 17 || e.metaKey;
    if (
        key == 9 ||
        // Ctrl+A
        (key == 65 && ctrl === true) ||
        // Ctrl+C
        (key == 67 && ctrl === true) ||
        // Ctrl+X
        (key == 88 && ctrl === true) ||
        // Ctrl+V
        (key == 86 && ctrl === true) ||
        // home, end, влево, вправо
        (key >= 35 && key <= 40) ||
        (key >= 48 && key <= 57) ||
        (key >= 96 && key <= 105)
    ) {
        return;
    } else if (key == 8) {
        if (input.value[cursor - 1] == ' ' && cursor < parseInt(inpVal.length)) {
            e.preventDefault();
            input.selectionEnd = cursor - 1;
        }
    } else if (key == 46) {
        if (input.value[cursor] == ' ' && cursor < parseInt(inpVal.length)) {
            e.preventDefault();
            input.selectionStart = cursor + 1;
        }
    } else {
        e.preventDefault();
    }
});
<form method="GET" action="#" class="card">
                <label style="font-size: 20px; display: block; padding: 10px" for="cardnum">Credit Card number</label>
                <input style="font-size: 20px; padding: 10px" autocomplete="off" id="cardnum" name="cardnum" type="text" maxlength="19" title="Please enter a card number in XXXX XXXX XXXX XXXX format" pattern="^\d{4}\s\d{4}\s\d{4}\s\d{4}$" inputmode="numeric" required />
            </form>

\$\endgroup\$
1
  • \$\begingroup\$ Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$
    – Mast
    Commented May 28, 2021 at 15:45

1 Answer 1

4
\$\begingroup\$

I've mainly got three points:

  1. The whole thing should be wrapped in a function with the reference to the input element passed in. Currently it is hard coded to (only) apply to the first input on the page, which doesn't seem like a practical scenerio.

  2. Instead of using the deprecated/non-standard keyCode and which, you should be using key. And if you do use keyCode you should define all code numbers as constants.

  3. Unless I'm missing some side-effect, the use of parseInt on inpVal.length is pointless.

\$\endgroup\$
1
  • \$\begingroup\$ ...should be wrapped in a function. Double-Plus Good! \$\endgroup\$
    – radarbob
    Commented Jul 26 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.