2

I'm trying to allow numbers and a minus sign only in a input type="text". I was able to allow numbers only, but I can't allow the minus sign. I tried the following regular expression to allow numbers only:

/\D/

When I add the minus sign, it doesn't seem to work:

/-?\D/

(The reason I have the question mark (?) is because there won't always be a minus sign.) When I try adding a minus sign to the textfield, it doesn't work. Here's the code:

(I tried adding a code snippet, but it wouldn't compile correctly.)

CodePen

<input id="num" type="text" />

var input = document.getElementById('num');
input.addEventListener("keypress", function(e) {
    var keycode = (e.keyCode ? e.keyCode : e.which);
    if (/-?\D/.test(String.fromCharCode(keycode))) { // a non–digit was entered
        e.preventDefault();
    }
});
Jessica
  • 9,379
  • 14
  • 65
  • 136
  • 2
    `\D` means anything _but_ numbers. It doesn’t make sense to use it to allow _only_ numbers. – Sebastian Simon Jan 26 '16 at 19:20
  • You want this: `/-?\d+/` – Enissay Jan 26 '16 at 19:21
  • You can also check the keycode: `keycode >= 48 && keycode <= 59 || keycode == 189` – Andreas Louv Jan 26 '16 at 19:25
  • 1
    I am laughing so hard, @Jessica. Nobody seems to get that you really meant \D, since your code _disallows_ everything what is _not a number_ Literally nobody cared enough to read the line below, nor your //comment. – kecer Jan 26 '16 at 19:26
  • 1
    Use character class: /[0-9\-]/ for allow numbres and digits only and /[^0-9\-]/ for inverse – Aferrercrafter Jan 26 '16 at 19:28
  • 1
    @KiraCrafter The `-` character may not require escaping within class – guest271314 Jan 26 '16 at 19:52
  • @KiraCrafter Your answer is the only one that actually worked! Just 2 pointers. 1 - How can I limit - to only be the first char? 2 - How can I make 0 not be the first **number** if it's not the only number? For example, say the user typed `02`. I want to remove the 0. – Jessica Jan 26 '16 at 22:56

9 Answers9

3

I suggest using this regex to match a valid number:

/^[+-]?\d+$/

and having you logic reversed in test method as this:

var input = document.getElementById('num');
input.addEventListener("change", function(e) {
    if (!/^[+-]?\d+$/.test(this.value)) { // a non–digit was entered
    console.log("non-digit was entered");
    $('#num').val('');
    }
});

CodePen

anubhava
  • 761,203
  • 64
  • 569
  • 643
1

Try using pattern attribute with RegExp [0-9-]+

var input = document.querySelector("input");
input.oninput = function(e) {
  if (!this.checkValidity()) {
    // do stuff
    console.log("invalid input")
  }
}
input:invalid + label[for="num"]:before {
  content: "invalid input";
}
<input id="num" type="text" pattern="[0-9-]+" minlength="1" placeholder="requires input" required /><label for="num"></label>
guest271314
  • 1
  • 15
  • 104
  • 177
  • 2
    try your own demo and enter: `123` – Andreas Louv Jan 26 '16 at 19:26
  • @dev-null See updated post, added `+` following `\d` – guest271314 Jan 26 '16 at 19:28
  • 1
    Now try your own demo and enter: `-123` :-) – Andreas Louv Jan 26 '16 at 19:28
  • @dev-null See updated post. Updated `RegExp` to `-|\d|-\d+|\d+|\d+-` – guest271314 Jan 26 '16 at 19:32
  • 1
    BTW, you just need: `-?\d*` or `-?\d+` depending on weather or not `-` is an allowed input. – Andreas Louv Jan 26 '16 at 19:33
  • @dev-null Yes `RegExp` could probably certainly be shortened ; attempt was to be specific given initial `RegExp` did not return expected results – guest271314 Jan 26 '16 at 19:35
  • @dev-null Actually, current pattern does not return expected results if input is `123-123` , attempting to correct presently. Also, suggested `RegExp`s at comment do not return expected result – guest271314 Jan 26 '16 at 19:42
  • That is correct, but neither would yours. But `-\d+` wont match `123-` either while your part `\d+-` will. I assume OP is interested in detecting positive and negative integers and not ranges, etc... If OP actually want to only allow digits and dashes then you can use a character class: `[-\d]+` – Andreas Louv Jan 26 '16 at 19:47
1

I think this code allow you to only input numbers and minus sign. But because the code also allow "ctrl + c", "ctrl + v", "ctrl + a", etc.., The textfield can be input other characters by "ctrl + v"(paste).

If you want to block "ctrl + v"(paste) also, comment out the code below.

$("#num").on("keydown", function(e){
  
  //character, not with ctrl, alt key
  if(e.keyCode >= 65 && e.keyCode <= 90 && !e.ctrlKey && !e.altKey) {
    return false;
  }

  // number with shift
  if(e.keyCode >= 48 && e.keyCode <= 57 && !!e.shiftKey) {
    return false;
  }
  
  // ` ~ - _ = + \ | [ { ] } ' " ; : / ? , < . >
  var otherKeys = [186, 187, 188, 189, 190, 191, 192, 219, 220, 221, 222];
  if(otherKeys.indexOf(e.keyCode) !== -1) {
  
    // allow minus sign
    if(e.keyCode === 189 && !e.shiftKey) {
      return true;
    }
    
    return false;
  }
  
  // if you want to block "ctrl + v"(paste), comment the below code out
  //if(e.keyCode === 86 && !!e.ctrlKey) {
  // return false;
  //}

  return true;
});
H HARRY
  • 11
  • 2
0

\D refers to non-digits

You were probably thinking of \d

/^-?\d+$/
Richard Hamilton
  • 25,478
  • 10
  • 60
  • 87
0

You are testing against the result of String.fromCharCode(keycode).

This can never be two characters.

if (! /-|\d/.test(String.fromCharCode(keycode))) { // a non–digit was entered

The regex /-|\d/ checks for exactly one character to be either either - or a digit.

For use in your code example the result of the match is negated with !.

As you are testing every single keypress, this will still allow the input to contain - the middle of the value like 123-456-789.

Squeezy
  • 495
  • 4
  • 11
0

After reading all of the suggestions, I'd like you to consider a different approach.

Reason

Your code right now disallows user to modify already inserted input in any way with a keyboard. Pressing backspace or delete won't work. Arrows won't work. This does hardly seem as comfortable thing for user.

Suggestion

Consider this example:

var last = '';
var input = document.getElementById('num');
input.addEventListener('input', function(e){
    if (isNaN(e.target.value))
        e.target.value=last;
    else
        last=e.target.value;
});

CodePen

Explanation

Hooking to event input will allow you to look at the new value of your input field. You can check, if it is a number (this also includes floats and negative numbers) by using method isNaN, which takes string and returns true if the input is not a number, false otherwise. Therefore, if the condition is true (=not a number), you replace the new value with the last correct one (in this case, default was set to '', but could be something like var last = isNaN(e.target.value)?'':e.target.value; (for supporting default values or whatever). Otherwise (the input is indeed a number), you leave the value as it is and record it as last successful.

Benefits are obvious, user is allowed to use keys like arrows, backspace, delete or combinations ctrl+c, ctrl+v, while preserving functionality (wrong input (NaN) is immediately deleted).

Note

If you want strictly signed integers, with this approach you can always cut off floating point if you detect it in else clause. Plus, not only isNaN considers . (dot, but not a comma) to be valid part of a number, it also allows notations like 1e3. Check this post for more detail.

Community
  • 1
  • 1
kecer
  • 3,031
  • 2
  • 21
  • 24
0

I had the same problem, I wanted to allow only digits and only a leading minus sign, to avoid things like ----89 or -89-0-66, or empty spaces, or dots, as I needed an integer

Obviously, I wanted to allow arrow keys and the delete key as well to edit the input value if needed

My 5 min working solution with jQuery:

<input id="input" type="text">

var input = $('input');
var allowed = [
 37, //left arrow
 39, //right arrow
 8 //delete
];

input.on('keyup', function(e) {

 if (allowed.indexOf(e.keyCode) !== -1) {
   return;
 }

 //remove white spaces and dots as I want integers
 var value = $(this).val().trim().replace(/\./g, '');

 if (isNaN(value)) {

   //check negative number validation
   if (value.substring(0, 1) === '-') {
     value = value.replace(/\D/g, '');
     value = '-' + value;
   } else {
     value = value.replace(/\D/g, '');
   }
 }
 $(this).val(value)
});

Codepen

The only thing I noticed is when editing on Chrome, the cursor gets at the end of the value after inserting a digit halfway through, it does not happen in Firefox...

Paranoid Android
  • 4,672
  • 11
  • 54
  • 73
0
$("#id").keypress(function(e){
  if (e.which != 46 && e.which != 45 && e.which != 46 &&
    !(e.which >= 48 && e.which <= 57)) {
       return false;
    }
});

this may help you

0

by given below code you can achieve that. given code allow minus (-) sign only on first place.

<pre><code>
 window.onload=function() {
    var input = document.getElementById("TextBoxId");

    input.onkeypress = function(e) {    e = e || window.event;
        var charCode = (typeof e.which == "number") ? e.which : e.keyCode;

        // Allow non-printable keys
        if (!charCode || charCode == 8 /* Backspace */ ) {
            return;
        }

        var typedChar = String.fromCharCode(charCode);

        // Allow numeric characters
        if (/\d/.test(typedChar)) {
            return;
        }

        // Allow the minus sign (-) if the user enters it first
        if (typedChar == "-" && this.value == "") {
            return;
        }

        // In all other cases, suppress the event
        return false;
    };
    }



</code></pre>
anilam
  • 694
  • 6
  • 7