37

I found the following JQuery function here which prevents a user from entering anything that's not a number or a single decimal. The function works well but I'd like to improve it to prevent the user from entering 3 or more decimal places i.e. disallow 99.999 and allow 99.99. Any ideas?

 function checkForInvalidCharacters(event, inputBox){                            
     if ((event.which != 46 || inputBox.val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) {          
                event.preventDefault();           
            }   
     };
Community
  • 1
  • 1
user676567
  • 1,119
  • 9
  • 20
  • 39
  • 1
    The function is not working well for me. I can enter 122.33.33.3343. – laaposto Feb 15 '14 at 11:29
  • Hi laaposto, Did you try calling it from a keypress function? $('#amount').keypress(function(event) { checkForInvalidCharacters(event, $(this)); }); – user676567 Feb 15 '14 at 11:33

7 Answers7

63

The logic is every time a user entering a number you have to check two things.

  1. Has the user entered decimal point?
  2. Are the decimal places more than two?

For the first one you can use $(this).val().indexOf('.') != -1

For the second one you can use $(this).val().substring($(this).val().indexOf('.'), $(this).val().indexOf('.').length).length > 2

EDIT-1
Also, you have to add event.which != 0 && event.which != 8 so that arrow keys and backspace work in Firefox (Manoj comment)

EDIT-2
Also, you have to add $(this)[0].selectionStart >= text.length - 2 so that you can add digits if the cursor is to the left of the decimal point (BIdesi comment)

EDIT-3
Also, you have to check if user deleted . and placed it somewhere else creating a value with more than 2 digits after the decimal. So you have to add $this.val($this.val().substring(0, $this.val().indexOf('.') + 3)); for cutting extra digits (Gilberto Sánchez comment)

EDIT-4
To handle pasted data, you must bind a paste event handler.Then you have to check if pasted data have . withtext.indexOf('.') > -1 and more than 2 digits after the decimal with text.substring(text.indexOf('.')).length > 3. If so, you have to cut extra digits. Also you have to check that user entered numeric input with $.isNumeric() (darasd comment).

Here is the code:

$('.number').keypress(function(event) {
    var $this = $(this);
    if ((event.which != 46 || $this.val().indexOf('.') != -1) &&
       ((event.which < 48 || event.which > 57) &&
       (event.which != 0 && event.which != 8))) {
           event.preventDefault();
    }

    var text = $(this).val();
    if ((event.which == 46) && (text.indexOf('.') == -1)) {
        setTimeout(function() {
            if ($this.val().substring($this.val().indexOf('.')).length > 3) {
                $this.val($this.val().substring(0, $this.val().indexOf('.') + 3));
            }
        }, 1);
    }

    if ((text.indexOf('.') != -1) &&
        (text.substring(text.indexOf('.')).length > 2) &&
        (event.which != 0 && event.which != 8) &&
        ($(this)[0].selectionStart >= text.length - 2)) {
            event.preventDefault();
    }      
});

$('.number').bind("paste", function(e) {
var text = e.originalEvent.clipboardData.getData('Text');
if ($.isNumeric(text)) {
    if ((text.substring(text.indexOf('.')).length > 3) && (text.indexOf('.') > -1)) {
        e.preventDefault();
        $(this).val(text.substring(0, text.indexOf('.') + 3));
   }
}
else {
        e.preventDefault();
     }
});
.number {
  padding: 5px 10px;
  font-size: 16px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="number" />
laaposto
  • 11,835
  • 15
  • 54
  • 71
  • @Manoj Can you point the exact problem as i see it is working..What are you trying to enter and doesnt work as expected? – laaposto Jul 01 '15 at 13:37
  • @Manoj I noticed that in firefox backspace didn't working. So i updated my answer. Thanks for pointing out – laaposto Jul 01 '15 at 13:54
  • not working for scenario, enter 12.34 then using arrow key come to place of '2' and delete it and replace it with some other number, you cant – BIdesi Jul 28 '15 at 09:33
  • @BIdesi Good catch! I updated the code so that now your scenario its woriking. – laaposto Jul 28 '15 at 10:13
  • Thank you, but what happened if I delete the `.` and then I put in another place? For example, if I have 22.45, then I remove the decimal point and put it like this: 2.245? – Gilberto Sánchez Dec 16 '15 at 20:10
  • it is preventing to type values when after decimal 2 digits are there, and am selecting those two digit and trying to enter new value without backspace or delete. – Surendar K Apr 04 '16 at 08:00
  • @GilbertoSánchez I updated the code so that your scenario is now working – laaposto Apr 26 '16 at 09:43
  • @Suren I don't think this is a scenario leading to a faulty code. User can still change value without highlighting the digits – laaposto Apr 26 '16 at 09:46
  • it doesn't cover pasting in values. – darasd May 04 '17 at 14:45
  • I can paste in 23.68 then 23.68 then 23.68 into the same html input area to get multiple decimal points. Just figured a heads up. Otherwise it's great! – MediaBlinkk May 20 '19 at 04:37
  • How would you allow commas in addition to the decimal, so that you can format the number? – JonnyPlow Apr 12 '20 at 06:18
  • I been trying to set the max length to 99999999.99 but it doesn't seem to work, can you please suggest how can I add this max length validation. – dawncode Oct 11 '20 at 17:55
5

It can also be done with a regular expression:

    $('.class').on('input', function () {
        this.value = this.value.match(/^\d+\.?\d{0,2}/);
    });

Name the css selector .class to whatever you like and put it on the input.

Tegge
  • 329
  • 3
  • 7
  • 1
    If we write only decimal before digit then it does remove entered value. It should not remove entered value but disallow to input decimal (.) at first position. – Rashid Khan May 14 '18 at 06:58
3

I've updated the function for a few extra cases.

  1. It will allow negative numbers
  2. It will allow you to edit the left of the decimal when there are already 2 digits to the right
  3. It allows you to use the arrow keys and backspace when you are in Firefox
  4. It also handles pasted data

/**
 * Given an input field, this function will only allow numbers with up to two decimal places to be input.
 * @param {object} element
 * @return {number}
 */
function forceNumber(element) {
  element
    .data("oldValue", '')
    .bind("paste", function(e) {
      var validNumber = /^[-]?\d+(\.\d{1,2})?$/;
      element.data('oldValue', element.val())
      setTimeout(function() {
        if (!validNumber.test(element.val()))
          element.val(element.data('oldValue'));
      }, 0);
    });
  element
    .keypress(function(event) {
      var text = $(this).val();
      if ((event.which != 46 || text.indexOf('.') != -1) && //if the keypress is not a . or there is already a decimal point
        ((event.which < 48 || event.which > 57) && //and you try to enter something that isn't a number
          (event.which != 45 || (element[0].selectionStart != 0 || text.indexOf('-') != -1)) && //and the keypress is not a -, or the cursor is not at the beginning, or there is already a -
          (event.which != 0 && event.which != 8))) { //and the keypress is not a backspace or arrow key (in FF)
        event.preventDefault(); //cancel the keypress
      }

      if ((text.indexOf('.') != -1) && (text.substring(text.indexOf('.')).length > 2) && //if there is a decimal point, and there are more than two digits after the decimal point
        ((element[0].selectionStart - element[0].selectionEnd) == 0) && //and no part of the input is selected
        (element[0].selectionStart >= element.val().length - 2) && //and the cursor is to the right of the decimal point
        (event.which != 45 || (element[0].selectionStart != 0 || text.indexOf('-') != -1)) && //and the keypress is not a -, or the cursor is not at the beginning, or there is already a -
        (event.which != 0 && event.which != 8)) { //and the keypress is not a backspace or arrow key (in FF)
        event.preventDefault(); //cancel the keypress
      }
    });
}

forceNumber($("#myInput"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="myInput" />
Mike
  • 555
  • 3
  • 14
2

thank you! I have added the possibility of deleting the numbers and '.' once typed:

The event.keyCode !== 8 does that action for backspace.

The event.keyCode !== 46 does that action for delete.

$( document ).ready(function() {

    $('#Ds_Merchant_Amount').keypress(function(event) {
    if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57) ) {
        if (event.keyCode !== 8 && event.keyCode !== 46 ){ //exception
            event.preventDefault();
        }
    }
    if(($(this).val().indexOf('.') != -1) && ($(this).val().substring($(this).val().indexOf('.'),$(this).val().indexOf('.').length).length>2 )){
        if (event.keyCode !== 8 && event.keyCode !== 46 ){ //exception
            event.preventDefault();
        }
    }
  });
});
maxhb
  • 8,554
  • 9
  • 29
  • 53
gtamborero
  • 2,898
  • 27
  • 28
2

Numeric values With Decimal Point up to 2 decimal point validation. Dependency jQuery.

HTML -

<span>Float</span>
<input type="text" name="numeric" class='allownumericwithdecimal'>
<div>Numeric values only allowed  (With Decimal Point) </div>

JQuery Code -

Method 1-

    $(".allownumericwithdecimal").on("keypress keyup blur", function (event) {
     var patt = new RegExp(/[0-9]*[.]{1}[0-9]{2}/i);
     var matchedString = $(this).val().match(patt);
     if (matchedString) {
         $(this).val(matchedString);
     }
     if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) {
         event.preventDefault();
     }
 });

Method 2 -

 $(".allownumericwithdecimal").on("keypress keyup blur", function (event) {
     var patt = new RegExp(/(?<=\.\d\d).+/i);
     $(this).val($(this).val().replace(patt, ''));

     if ((event.which != 46 || $(this).val().indexOf('.') != -1) && (event.which < 48 || event.which > 57)) {
         event.preventDefault();
     }
 });
Ravindra Vairagi
  • 1,055
  • 15
  • 22
  • I implemented Method 2 in a project but found that it only worked in Chrome. The positive look-behind does not work in other browsers (as I learned after several hours). Method 1 works in all four browsers I tested, though I used: var patt = new RegExp(/^\d+\.\d\d/i); – mrturtle Jun 13 '19 at 19:27
0

I have updated this routine to allow standard editing features as these were prevented in the above code. (This routine is just for processing a float but can be adapted to allow only 2 digits after the decimal)

var value = $(this).val().toString();

// Allowed Keys
if (event.which === 8 || event.which === 46 // Character delete
    || event.which === 16 || event.which === 17 // Modifier Key
    || event.which === 37 || event.which === 39  // Arrow Keys
    || (event.key.toLowerCase() === "a" && event.ctrlKey) // Select All
    || (event.key.toLowerCase() === "c" && event.ctrlKey) // Copy
    || (event.key.toLowerCase() === "x" && event.ctrlKey) // Cut
    || (event.key.toLowerCase() === "v" && event.ctrlKey) // Paste
    || (event.which === 45 && event.ctrlKey) // Old school copy (CTRL + INSERT)
    || (event.which === 46 && event.shiftKey) // Old school cut (SHIFT + DELETE)
    || (event.which === 45 && event.shiftKey) // Old school paste (SHIFT + INSERT)
    || (event.which === 35) // END
    || (event.which === 36) // HOME
    || (event.which === 35 && event.shiftKey) // SHIFT + END
    || (event.which === 36 && event.shiftKey) // SHIFT + HOME
    )
{
    return;
}
else if (event.which === 190) // Process decimal point
{
    if (value == "" || value.indexOf(".") > -1)
    {
        event.preventDefault();
    }
}
else if (event.which < 48 || event.which > 57 || event.ctrlKey || event.shiftKey) // Reject anything else that isn't a number
{
    event.preventDefault();
}
Dreamwalker
  • 3,032
  • 4
  • 30
  • 60
0

Try this

HTML

<input type="text" id="min_rent" name="min_rent" onkeypress="return isPrice(event,$('#min_rent').val())">

Jquery

function isPrice(evt,value) {
    var charCode = (evt.which) ? evt.which : event.keyCode;
    if((value.indexOf('.')!=-1) && (charCode != 45 && (charCode < 48 || charCode > 57)))
        return false;
    else if(charCode != 45 && (charCode != 46 || $(this).val().indexOf('.') != -1) && (charCode < 48 || charCode > 57))
        return false;
    return true;
}

Worked Link demo

Sakthi Karthik
  • 3,105
  • 4
  • 25
  • 29