Question

Is there a quick way to set an HTML text input (<input type=text />) to only allow numeric keystrokes (plus '.')?

Was it helpful?

Solution

Note: This is an updated answer. Comments below refer to an old version which messed around with keycodes.

JavaScript

The setInputFilter function below allows you to use any kind of input filter on a text <input>, including various numeric filters (see below).

Unlike most other solutions, this correctly supports Copy+Paste, Drag+Drop, all keyboard shortcuts, all context menu operations, all non-typeable keys (e.g. cursor and navigation keys), the caret position, all keyboard layouts of all languages and platforms, and all browsers since IE 9.

Try it yourself on JSFiddle.

// Restricts input for the given textbox to the given inputFilter.
function setInputFilter(textbox, inputFilter) {
  ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function(event) {
    textbox.addEventListener(event, function() {
      if (inputFilter(this.value)) {
        this.oldValue = this.value;
        this.oldSelectionStart = this.selectionStart;
        this.oldSelectionEnd = this.selectionEnd;
      } else if (this.hasOwnProperty("oldValue")) {
        this.value = this.oldValue;
        this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
      }
    });
  });
}

// Restrict input to digits and '.' by using a regular expression filter.
setInputFilter(document.getElementById("myTextBox"), function(value) {
  return /^\d*\.?\d*$/.test(value);
});

Some input filters you might want to use:

  • Integer values (positive only):
    /^\d*$/.test(value)
  • Integer values (positive and up to a particular limit):
    /^\d*$/.test(value) && (value === "" || parseInt(value) <= 500)
  • Integer values (both positive and negative):
    /^-?\d*$/.test(value)
  • Floating point values (allowing both . and , as decimal separator):
    /^-?\d*[.,]?\d*$/.test(value)
  • Currency values (i.e. at most two decimal places):
    /^-?\d*[.,]?\d{0,2}$/.test(value)
  • A-Z only (i.e. basic Latin letters):
    /^[a-z]*$/i.test(value)
  • Latin letters only (i.e. English and most European languages, see https://unicode-table.com for details about Unicode character ranges):
    /^[a-z\u00c0-\u024f]*$/i.test(value)
  • Hexadecimal values:
    /^[0-9a-f]*$/i.test(value)

Note that you still must do server side validation!

jQuery

There is also a jQuery version of this. See this answer or try it yourself on JSFiddle.

HTML 5

HTML 5 has a native solution with <input type="number"> (see the specification), but note that browser support varies:

  • Most browsers will only validate the input when submitting the form, and not when typing.
  • Most mobile browsers don't support the step, min and max attributes.
  • Chrome (version 71.0.3578.98) still allows the user to enter the characters e and E into the field. Also see this question.
  • Firefox (version 64.0) and Edge (EdgeHTML version 17.17134) still allow the user to enter any text into the field.

Try it yourself on w3schools.com.

OTHER TIPS

Use this DOM

<input type='text' onkeypress='validate(event)' />

And this script

function validate(evt) {
  var theEvent = evt || window.event;

  // Handle paste
  if (theEvent.type === 'paste') {
      key = event.clipboardData.getData('text/plain');
  } else {
  // Handle key press
      var key = theEvent.keyCode || theEvent.which;
      key = String.fromCharCode(key);
  }
  var regex = /[0-9]|\./;
  if( !regex.test(key) ) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
  }
}

I've searched long and hard for a good answer to this, and we desperately need <input type="number", but short of that, these 2 are the most concise ways I could come up with:

<input type="text" 
       onkeyup="this.value=this.value.replace(/[^\d]/,'')">

If you dislike the non-accepted character showing for a split-second before being erased, the method below is my solution. Note the numerous additional conditions, this is to avoid disabling all sorts of navigation and hotkeys. If anyone knows how to compactify this, let us know!

<input type="text" 
onkeydown="return ( event.ctrlKey || event.altKey 
                    || (47<event.keyCode && event.keyCode<58 && event.shiftKey==false) 
                    || (95<event.keyCode && event.keyCode<106)
                    || (event.keyCode==8) || (event.keyCode==9) 
                    || (event.keyCode>34 && event.keyCode<40) 
                    || (event.keyCode==46) )">

Here is a simple one which allows for exactly one decimal, but no more:

<input type="text" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');" />

And one more example, which works great for me:

function validateNumber(event) {
    var key = window.event ? event.keyCode : event.which;
    if (event.keyCode === 8 || event.keyCode === 46) {
        return true;
    } else if ( key < 48 || key > 57 ) {
        return false;
    } else {
        return true;
    }
};

Also attach to keypress event

$(document).ready(function(){
    $('[id^=edit]').keypress(validateNumber);
});

And HTML:

<input type="input" id="edit1" value="0" size="5" maxlength="5" />

Here is a jsFiddle example

HTML5 has <input type=number>, which sounds right for you. Currently, only Opera supports it natively, but there is a project that has a JavaScript implementation.

Most answers here all have the weakness of using key- events.

Many of the answers would limit your ability to do text selection with keyboard macros, copy+paste and more unwanted behavior, others seem to depend on specific jQuery plugins, which is killing flies with machineguns.

This simple solution seems to work best for me cross platform, regardless of input mechanism (keystroke, copy+paste, rightclick copy+paste, speech-to-text etc.). All text selection keyboard macros would still work, and it would even limit ones ability to set a non-numeric value by script.

function forceNumeric(){
    this.value(this.value.replace(/[^\d]+/g,''));
}
$('body').on('propertychange input', 'input.numeric-text', forceNumeric);

I opted to use a combination of the two answers mentioned here i.e.

<input type="number" />

and

function isNumberKey(evt){
    var charCode = (evt.which) ? evt.which : evt.keyCode
    return !(charCode > 31 && (charCode < 48 || charCode > 57));
}

<input type="text" onkeypress="return isNumberKey(event);">

HTML5 supports regexes, so you could use this:

<input id="numbersOnly" pattern="[0-9.]+" type="text">

Warning: Some browsers don't support this yet.

JavaScript

function validateNumber(evt) {
    var e = evt || window.event;
    var key = e.keyCode || e.which;

    if (!e.shiftKey && !e.altKey && !e.ctrlKey &&
    // numbers   
    key >= 48 && key <= 57 ||
    // Numeric keypad
    key >= 96 && key <= 105 ||
    // Backspace and Tab and Enter
    key == 8 || key == 9 || key == 13 ||
    // Home and End
    key == 35 || key == 36 ||
    // left and right arrows
    key == 37 || key == 39 ||
    // Del and Ins
    key == 46 || key == 45) {
        // input is VALID
    }
    else {
        // input is INVALID
        e.returnValue = false;
        if (e.preventDefault) e.preventDefault();
    }
}

additional you could add comma, period and minus (,.-)

  // comma, period and minus, . on keypad
  key == 190 || key == 188 || key == 109 || key == 110 ||

HTML

<input type="text" onkeydown="validateNumber(event);"/ >

2 solutions:

Use a form validator (for example with jQuery validation plugin)

Do a check during the onblur (i.e. when the user leaves the field) event of the input field, with the regular expression:

<script type="text/javascript">
function testField(field) {
    var regExpr = new RegExp("^\d*\.?\d*$");
    if (!regExpr.test(field.value)) {
      // Case of error
      field.value = "";
    }
}

</script>

<input type="text" ... onblur="testField(this);"/>

So simple....

// In a JavaScript function (can use HTML or PHP).

function isNumberKey(evt){
    var charCode = (evt.which) ? evt.which : evt.keyCode;
    if (charCode > 31 && (charCode < 48 || charCode > 57))
        return false;
    return true;
}

In your form input:

<input type=text name=form_number size=20 maxlength=12 onkeypress='return isNumberKey(event)'>

With input max. (These above allows for a 12-digit number)

A safer approach is checking the value of the input, instead of hijacking keypresses and trying to filter keyCodes.

This way the user is free to use keyboard arrows, modifier keys, backspace, delete, use non standard keyboars, use mouse to paste, use drag and drop text, even use accessibility inputs.

The below script allows positive and negative numbers

1
10
100.0
100.01
-1
-1.0
-10.00
1.0.0 //not allowed

var input = document.getElementById('number');
input.onkeyup = input.onchange = enforceFloat;

//enforce that only a float can be inputed
function enforceFloat() {
  var valid = /^\-?\d+\.\d*$|^\-?[\d]*$/;
  var number = /\-\d+\.\d*|\-[\d]*|[\d]+\.[\d]*|[\d]+/;
  if (!valid.test(this.value)) {
    var n = this.value.match(number);
    this.value = n ? n[0] : '';
  }
}
<input id="number" value="-3.1415" placeholder="Type a number" autofocus>

EDIT: I removed my old answer because I think it is antiquated now.

Please find below mentioned solution. In this user can be able to enter only numeric value, Also user can not be able to copy, paste, drag and drop in input.

Allowed Characters

0,1,2,3,4,5,6,7,8,9

Not allowed Characters and Characters through events

  • Alphabetic value
  • Special characters
  • Copy
  • Paste
  • Drag
  • Drop

$(document).ready(function() {
  $('#number').bind("cut copy paste drag drop", function(e) {
      e.preventDefault();
  });     
});
function isNumberKey(evt) {
    var charCode = (evt.which) ? evt.which : evt.keyCode;
    if (charCode > 31 && (charCode < 48 || charCode > 57))
        return false;
    return true;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" class="form-control" name="number" id="number" onkeypress="return isNumberKey(event)" placeholder="Enter Numeric value only">

Let me know if it not works.

You can use pattern for this:

<input id="numbers" pattern="[0-9.]+" type="number">

Here you can see the complete mobile website interface tips.

If you want to suggest to the device (maybe a mobile phone) between alpha or numeric you can use <input type="number">.

A short and sweet implementation using jQuery and replace() instead of looking at event.keyCode or event.which:

$('input.numeric').live('keyup', function(e) {
  $(this).val($(this).val().replace(/[^0-9]/g, ''));
});

Only small side effect that the typed letter appears momentarily and CTRL/CMD + A seems to behave a bit strange.

JavaScript code:

function validate(evt)
{
    if(evt.keyCode!=8)
    {
        var theEvent = evt || window.event;
        var key = theEvent.keyCode || theEvent.which;
        key = String.fromCharCode(key);
        var regex = /[0-9]|\./;
        if (!regex.test(key))
        {
            theEvent.returnValue = false;

            if (theEvent.preventDefault)
                theEvent.preventDefault();
            }
        }
    }

HTML code:

<input type='text' name='price' value='0' onkeypress='validate(event)'/>

works perfectly because the backspace keycode is 8 and a regex expression doesn't let it, so it's an easy way to bypass the bug :)

Just an other variant with jQuery using

$(".numeric").keypress(function() {
    return (/\d/.test(String.fromCharCode(event.which) ))
});

input type="number" is an HTML5 attribute.

In the other case this will help you:

function isNumberKey(evt){
    var charCode = (evt.which) ? evt.which : evt.keyCode
    if (charCode > 31 && (charCode < 48 || charCode > 57))
        return false;
    return true;
}

<input type="number" name="somecode" onkeypress="return isNumberKey(event)"/>

One more example where you can add only numbers in the input field, can not letters

<input type="text" class="form-control" id="phone" name="phone" placeholder="PHONE" spellcheck="false" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');">

just use type="number" now this attribute supporting in most of the browsers

<input type="number" maxlength="3" ng-bind="first">

You can also compare input value (which is treated as string by default) to itself forced as numeric, like:

if(event.target.value == event.target.value * 1) {
    // returns true if input value is numeric string
}

However, you need to bind that to event like keyup etc.

<input name="amount" type="text" value="Only number in here"/> 

<script>
    $('input[name=amount]').keyup(function(){
        $(this).val($(this).val().replace(/[^\d]/,''));
    });
</script>

Use this DOM:

<input type = "text" onkeydown = "validate(event)"/>

And this script:

validate = function(evt)
{
    if ([8, 46, 37, 39, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 35, 36].indexOf(evt.keyCode || evt.which) == -1)
    {
        evt.returnValue = false;
        if(evt.preventDefault){evt.preventDefault();}
    }
}

...OR this script, without indexOf, using two for's...

validate = function(evt)
{
    var CharValidate = new Array("08", "046", "039", "948", "235");
    var number_pressed = false;
    for (i = 0; i < 5; i++)
    {
        for (Ncount = 0; Ncount < parseInt(CharValidate[i].substring(0, 1)) + 1; Ncount++)
        {
            if ((evt.keyCode || evt.which) == parseInt(CharValidate[i].substring(1, CharValidate[i].lenght)) + Ncount)
            {
                number_pressed = true;
            }
        }
    }
    if (number_pressed == false)
    {
        evt.returnValue = false;
        if(evt.preventDefault){evt.preventDefault();}
    }
}

I used the onkeydown attribute instead of onkeypress, because the onkeydown attribute is checked before onkeypress attribute. The problem would be in the Google Chrome browser.

With the attribute "onkeypress", TAB would be uncontrollable with "preventDefault" on google chrome, however, with the attribute "onkeydown", TAB becomes controllable!

ASCII Code for TAB => 9

The first script have less code than the second, however, the array of ASCII characters must have all the keys.

The second script is much bigger than the first, but the array does not need all keys. The first digit in each position of the array is the number of times each position will be read. For each reading, will be incremented 1 to the next one. For example:




NCount = 0

48 + NCount = 48

NCount + +

48 + NCount = 49

NCount + +

...

48 + NCount = 57




In the case of numerical keys are only 10 (0 - 9), but if they were 1 million it would not make sense to create an array with all these keys.

ASCII codes:

  • 8 ==> (Backspace);
  • 46 => (Delete);
  • 37 => (left arrow);
  • 39 => (right arrow);
  • 48 - 57 => (numbers);
  • 36 => (home);
  • 35 => (end);

This is an improved function:

function validateNumber(evt) {
  var theEvent = evt || window.event;
  var key = theEvent.keyCode || theEvent.which;
  if ((key < 48 || key > 57) && !(key == 8 || key == 9 || key == 13 || key == 37 || key == 39 || key == 46) ){
    theEvent.returnValue = false;
    if (theEvent.preventDefault) theEvent.preventDefault();
  }
}

The best way (allow ALL type of numbers - real negative, real positive, iinteger negative, integer positive) is:

$(input).keypress(function (evt){
    var theEvent = evt || window.event;
    var key = theEvent.keyCode || theEvent.which;
    key = String.fromCharCode( key );
    var regex = /[-\d\.]/; // dowolna liczba (+- ,.) :)
    var objRegex = /^-?\d*[\.]?\d*$/;
    var val = $(evt.target).val();
    if(!regex.test(key) || !objRegex.test(val+key) || 
            !theEvent.keyCode == 46 || !theEvent.keyCode == 8) {
        theEvent.returnValue = false;
        if(theEvent.preventDefault) theEvent.preventDefault();
    };
}); 

This is the extended version of geowa4's solution. Supports min and max attributes. If the number is out of range, the previous value will be shown.

You can test it here.

Usage: <input type=text class='number' maxlength=3 min=1 max=500>

function number(e) {
var theEvent = e || window.event;
var key = theEvent.keyCode || theEvent.which;
if(key!=13&&key!=9){//allow enter and tab
  key = String.fromCharCode( key );
  var regex = /[0-9]|\./;
  if( !regex.test(key)) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
    }   
  }
}

$(document).ready(function(){
    $("input[type=text]").filter(".number,.NUMBER").on({
        "focus":function(e){
         $(e.target).data('oldValue',$(e.target).val());
            },
        "keypress":function(e){
                e.target.oldvalue = e.target.value;
                number(e);
            },
        "change":function(e){
            var t = e.target;
            var min = $(t).attr("min");
            var max = $(t).attr("max");
            var val = parseInt($(t).val(),10);          
            if( val<min || max<val)
                {
                    alert("Error!");
                    $(t).val($(t).data('oldValue'));
                }

            }       
    });     
});

If the inputs are dynamic use this:

$(document).ready(function(){
    $("body").on("focus","input[type=text].number,.NUMBER",function(e){
        $(e.target).data('oldValue',$(e.target).val());
    }); 
    $("body").on("keypress","input[type=text].number,.NUMBER",function(e){
        e.target.oldvalue = e.target.value;
        number(e);
    }); 
    $("body").on("change","input[type=text].number,.NUMBER",function(e){
        var t = e.target
        var min = $(t).attr("min");
        var max = $(t).attr("max");
        var val = parseInt($(t).val());         
        if( val<min || max<val)
            {
                alert("Error!");
                $(t).val($(t).data('oldValue'));
            }
    }); 
});

My solution for a better user experience:

HTML

<input type="tel">

jQuery

$('[type=tel]').on('change', function(e) {
  $(e.target).val($(e.target).val().replace(/[^\d\.]/g, ''))
})
$('[type=tel]').on('keypress', function(e) {
  keys = ['0','1','2','3','4','5','6','7','8','9','.']
  return keys.indexOf(event.key) > -1
})

Details:

First of all, input types:

number shows up/down arrows shrinking the actual input space, I find them ugly and are only useful if the number represents a quantity (things like phones, area codes, IDs... don't need them) tel provides similar browser validations of number without arrows

Using [number / tel] also helps showing numeric keyboard on mobile devices.

For the JS validation I ended up needing 2 functions, one for the normal user input (keypress) and the other for a copy+paste fix (change), other combinations would give me a terrible user experience.

I use the more reliable KeyboardEvent.key instead of the now deprecated KeyboardEvent.charCode

And depending of your browser support you can consider using Array.prototype.includes() instead of the poorly named Array.prototype.indexOf() (for true / false results)

A easy way to resolve this problem is implementing a jQuery function to validate with regex the charaters typed in the textbox for example:

Your html code:

<input class="integerInput" type="text">

And the js function using jQuery

$(function() {
    $('.integerInput').on('input', function() {
      this.value = this.value
        .replace(/[^\d]/g, '');// numbers and decimals only

    });
});

$(function() {
        $('.integerInput').on('input', function() {
          this.value = this.value
            .replace(/[^\d]/g, '');// numbers and decimals only
            
        });
    });
<script
			  src="https://code.jquery.com/jquery-2.2.4.min.js"
			  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
			  crossorigin="anonymous">
</script>

<input type="text" class="integerInput"/>


		

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top