0

I have read many similar questions, but could not find one that works for these 2 conditions (only digits input with maximum length of 5). I have tried different variations, one of them is:

<div class="input text">
    <input id="zip" name="zip" type="number"  min="0" max="99999" ng-model="formData.zip" placeholder="Type here..." class="input-medium" ng-init="0">

For this one I am still able to type in as many digits as I want, so the min max attributes do not really do anything.

0

2 Answers 2

1

A more aggressive approach that uses the keydown event and blocks all unwanted input via preventDefault:

Edit: I've also included a version that allows for copy/pasting for comparison, but in this case you need to use keyup to allow the paste to occur before fixing the pasted content.

For any other key or key combination that you want to allow you can simply add them to the first if statement as allowed input.

/////////////////////////////////////////////////////
// Super strict version only allows numbers as input
/////////////////////////////////////////////////////
var input = document.getElementById('num');

input.addEventListener('keydown', function(event) {
  // always allow backspace, delete, left/right arrow keys
  if (event.which == 8 || event.which == 46 || event.which == 37 || event.which == 39) { 
    return;
  }
  // prevent all other input if already at 5 chars or not a number
  else if (input.value.length >= 5 || event.which < 48 || event.which > 57) {
    event.preventDefault();
    return;
  }
});

/////////////////////////////////////////////////////
// Version that allows for copy/pasting
/////////////////////////////////////////////////////
var inputPaste = document.getElementById('paste-num');

inputPaste.addEventListener('keydown', function(event) {
  // always allow backspace, delete, left/right arrow, copy, paste, select all
  if (event.which == 8 || event.which == 46 || event.which == 37 || event.which == 39 || (event.ctrlKey && event.which == 67) || (event.ctrlKey && event.which == 86) || (event.ctrlKey && event.which == 65)) { 
    return;
  }
  // prevent all other input if already at 5 chars or not a number
  else if (inputPaste.value.length >= 5 || event.which < 48 || event.which > 57) {
    event.preventDefault();
    return;
  }
});

// clean anything that gets pasted in
inputPaste.addEventListener('keyup', function(event) {
  if (event.ctrlKey && event.which == 86) {
    // remove non numbers
    inputPaste.value = inputPaste.value.replace(/[^0-9]/g, "");
    // trim to first 5 digits
    inputPaste.value = inputPaste.value.substr(0, 5);
  }
});
Numbers Only: <input id="num" name="num" placeholder="#####"> <br>
Numbers Only(can copy/paste):<input id="paste-num" name="paste-num" placeholder="#####">

Sign up to request clarification or add additional context in comments.

3 Comments

Nice solution. Also blocks use of arrow keys though.
Ahh yeah, any other keys you want to allow default actions you can add to the first if statement. I'll add delete and arrow keys to my answer.
Thank you @crapier. Note that if you add type="number" min="0" max="99999" to the input, it does the cropping automatically, and takes the first 5 digits of what you have pasted. Foe example, if you paste "CA 90345" it takes the "90345" so the last block of code in unnecessary.
1

Here's a way to do it. On keyup the handler checks the input value; if there are more than five characters, it doesn't let the user add any more. If a non-numeric character is entered, the function removes it.

UPDATE: This code can now handle inserting numbers in the beginning or middle of the pack as well when five characters are already present.

var inputEl = document.getElementById('zip');
var prev = "";

inputEl.addEventListener('keyup', function(e) {
  if (e.which == 8) { // if backspace
    prev = inputEl.value;
    return;
  }
  // check for >5 characters
  if (inputEl.value.length > 5) {
    if (e.which < 48 || e.which > 57) { // if new char is a number
      inputEl.value = prev;
    } else {
      inputEl.value = inputEl.value.slice(0, inputEl.value.length - 1);
    }
    if (inputEl.value.length > 5) { // if still >5 after parsing
      inputEl.value = inputEl.value.slice(0, 5);
    }
  }
  // check for a digit (code 48 to 57)
  else if (e.which < 48 || e.which > 57) {
    (inputEl.value.length > 1) ? inputEl.value = prev: inputEl.value = "";
  }
  prev = inputEl.value;
});

inputEl.focus();
<div class="input text">
  <input id="zip" name="zip" placeholder="Type here...">
</div>

(Focus was added to the input box for ease of testing.)

2 Comments

Thank you! however, it works only if you type one digit at a time. If you press a key continuously, you can type more than the 5 digits an it will delete only the last one, so I will have to resolve this.
@RD8 Ah, thanks for noticing that. I've fixed it now, so continuous key pressing will still be trimmed down to 5 chars.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.