Sunday, April 19, 2009

Inputting only numbers using Java Script and HTML

The basic input text field of HTML is very limited when it comes numeric data. There are times in which a better user experience is needed.
In order to generate a better user experience, 2 main features can be easily added to the input text field by using JavaScript:
  • Allow user to input only numeric data. That means that any character other than numbers dots or commas is not allowed. This feature prevents from the user to entering undesired data to the field.
  • Show data in a formatted manner when field is not edited. That means that when field lost focus, its contents are shown with commas or dots. That makes the numeric data on the text field to be more readable.
Note, that we also would like the text to be formatted according to a specific Locale. That means that we want to use decimal separator and grouping separator to be according to our demands. There are countries and cultures in which the decimal separator is comma and some other countries in which decimal separator is dot. The same applies to grouping separator.
In order to achieve our 2 goals we will build 3 java script functions. Each function will be assigned to a specific JavaScript event.
  • onkeypress: This event is activated whenever a key is being pressed when the cursor is in the text field. A function that returns "false" on this event cancels the event and thus prevent from the pressed character to be updated on the text field. We will assign to this even a function named: numbersOnly. This function receives 4 parameters:
    • field: The text field that called the function.
    • e: The onkeypress event.
    • isDec: Indicate that we would like the input to be decimal and not only integer.
    • decimalSeperator: The character used as a decimal separator (probably “.” or “,”).
    In return this function will return true whenever the pressed character is allowed to be inputted by the user or false if character is not allowed to be inputted.
  • onfocus: This event is activated when the text field receives focus. That means, when we are entering to the text field. This event will be assigned with a function named: plainNumber. This function takes the numeric data in the text field and converts it to a plain number, meaning, any numeric formatted data containing dots or command will be converted to a plain number ready to be edited. This function has 2 parameters:
    • field: The text field field that called the function.
    • decimalSeperator: The character used as a decimal separator (probably “.” or “,”).
  • onblur: This event is activated when the field loses focus. That means when we are entering the field by moving to another element on the page. This event will be assinged with a function named: formattedNumber. This function converts the plain numeric data on the text field to a formatted data containing grouping separators. This function has 3 parameters:
    • field: The text field field that called the function.
    • decimalSeperator: The character used as a decimal separator (probably “.” or “,”).
    • groupingSeperator: The character used as a grouping separator (probably “.” or “,”).

I made an example showing a text field utilizing the 3 events to create the described behavior. The example contains a simple HTML page containing the JavaScript methods and a simple text field. The JavaScript code used in this example is not state of the art, but working fine on both FireFox and Explorer. This code can be further refined by encapsulating all the behavior to a single static JavaScript class.

Here is the example code showing input numbers only of an Integer number:

<html>
 <head>
  <title> JavaScript Input Example </title>
 </head>
 <body>
<script>
function numbersOnly(field, e, isDec, decimalSeperator)
{
  var key;
  var keychar;
if (window.event)
   key = window.event.keyCode;
else if (e)
   key = e.which;
else
   return true;
  keychar = String.fromCharCode(key);
// control keys
  if ((key == null) || (key == 0) || (key == 8) ||
      (key == 9) || (key == 13) || (key == 27) || (key == 39) /*|| (key == 37)*/)
  {
    return true;
  }
  else if ((("0123456789").indexOf(keychar) > -1) ||
    (isDec && (keychar == decimalSeperator) && (field.value.indexOf(decimalSeperator) < 0)))
  {
    return true;
  }
 return false;
}
function formattedNumber(field, decimalSeperator, groupingSeperator)
{
    field.value = addGroupingSeperator(field.value, decimalSeperator, groupingSeperator);
}
function plainNumber(field, decimalSeperator)
{
    field.value = field.value.replace(
        new RegExp("[^0123456789" + decimalSeperator + "" + "]", 'g'), "");
}
function addGroupingSeperator(nStr, decimalSeperator, groupingSeperator)
{
    nStr += '';    
    x = nStr.split(decimalSeperator);
    x1 = x[0];
    x2 = x.length > 1 ? decimalSeperator + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + groupingSeperator + '$2');
    }
    return x1 + x2;
}
</script>
    <input id="inputInteger" name="inputInteger" maxLength="7"
       onfocus="plainNumber(this, '.');"
       onblur="formattedNumber(this, '.', ',')"
       onkeypress="return numbersOnly(this, event, false, '.')">
 </body>
</html>
Note that the data of the decimal and grouping separator can be taken from your programming language and assigned dynamically according to the specific user Locale information.

No comments:

Post a Comment