search
Twitter Rss Feeds
MicrosoftArticlesForumsGroups
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml/Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

Web ProgrammingArticlesForumsGroups
JavaScript
ASP
ASP.NET
Web Services

Non-MicrosoftArticlesForumsGroups
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

DatabasesArticlesForumsGroups
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsGroups
Microsoft Excel
Microsoft Word
Microsoft Powerpoint
Publisher
Money

Operating SystemsArticlesForumsGroups
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsGroups
Share Point
BizTalk
Site Server
Exhange Server
IIS
Transaction Server

Graphic DesignArticlesForumsGroups
Macromedia Flash
Adobe PhotoShop
Microsoft Expression

OtherArticlesForumsGroups
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Reviews
Search Engines
Resumes

 
JavaScript, Excel, Auto Format Numbers and International Currency

By Robbe D. Morris

Printer Friendly Version


Robbe & Melisa Morris
Excel like auto formatting numbers in JavaScript such as currency, numbers with decimal points and places, and disabling decimal points is an important part of web based calculation data entry tables.  The code sample below demonstrates how to handle a wide variety of number formats.  It also lets you integrate internationalization as part of your formatting scheme.
 
 
I opted to approach this is in somewhat of a simplistic manner.  When processing the textbox onBlur(), the value would be stripped of all non-numeric characters, retrieve the country specific decimal and comma character, and apply the formatting.  FormatNumber() is the primary function.  GetDecimalDelimiter() and GetCommaDelimiter() contain characters for three separate countries (I just made up the symbols).  This will enable the developer to implement a wide variety of custom formats.  The developer can also implement custom rounding solutions should it be necessary.  Plus, I think that you'll find this approach makes it easier to convert seemingly improper numeric values during math functions and convert the values back after the math has been completed.
Implementing this in your own pages is easy.  Just put the JavaScript in a separate file and include it in your applicable pages.  Feel free to test out the various number formats below.

Sample Playground
Country 1 ( Comma= , Places = 6 )
Country 2 ( Comma= , Decimal= , Places = 1 )
Country 3 ( Comma= * Decimal= # Places = 2 )
Country 1 ( Comma= , Places = 3 )
Country 2 ( Comma= , Decimal= , Places = 4 )
Country 3 ( Comma= * Decimal=# Places = 5 )

Sample Code
  

<HTML>
<HEAD>

<script language=JavaScript>
  
 function GetDecimalDelimiter(countryCode)
{
 
  switch (countryCode)
  {
    case 3:   
           return '#';
    case 2:   
           return ',';
    default:
           return '.';
  }
}

function GetCommaDelimiter(countryCode)
{
 
  switch (countryCode)
  { 
    case 3:          
           return '*';
    case 2:   
           return ',';
    default:
           return ',';
  }
 
}

function FormatClean(num)
{
     var sVal='';
     var nVal = num.length;
     var sChar='';
     
   try
   {
      for(c=0;c<nVal;c++)
      {
         sChar = num.charAt(c);
         nChar = sChar.charCodeAt(0);
         if ((nChar >=48) && (nChar <=57))  { sVal += num.charAt(c);   }
      }
   }
    catch (exception) { AlertError("Format Clean",exception); }
    return sVal;
}
  

function FormatNumber(num,countryCode,decimalPlaces)
{       

  var minus='';
  var comma='';
  var dec='';
  var preDecimal='';
  var postDecimal='';
  
  try 
  {
   
    decimalPlaces = parseInt(decimalPlaces);
    comma = GetCommaDelimiter(countryCode);
    dec = GetDecimalDelimiter(countryCode);
    
    if (decimalPlaces < 1) { dec = ''; }
    if (num.lastIndexOf("-") == 0) { minus='-'; }
   
    preDecimal = FormatClean(num);
    
    // preDecimal doesn't contain a number at all.
    // Return formatted zero representation.
    
    if (preDecimal.length < 1)
    {
       return minus + FormatEmptyNumber(dec,decimalPlaces);
    }
    
    // preDecimal is 0 or a series of 0's.
    // Return formatted zero representation.
    
    if (parseInt(preDecimal) < 1)
    {
       return minus + FormatEmptyNumber(dec,decimalPlaces);
    }
    
    // predecimal has no numbers to the left.
    // Return formatted zero representation.
    
    if (preDecimal.length == decimalPlaces)
    {
      return minus + '0' + dec + preDecimal;
    }
    
    // predecimal has fewer characters than the
    // specified number of decimal places.
    // Return formatted leading zero representation.
    
    if (preDecimal.length < decimalPlaces)
    {
       if (decimalPlaces == 2)
       {
        return minus + FormatEmptyNumber(dec,decimalPlaces - 1) + preDecimal;
       }
       return minus + FormatEmptyNumber(dec,decimalPlaces - 2) + preDecimal;
    }
    
    // predecimal contains enough characters to
    // qualify to need decimal points rendered.
    // Parse out the pre and post decimal values
    // for future formatting.
    
    if (preDecimal.length > decimalPlaces)
    {
      postDecimal = dec + preDecimal.substring(preDecimal.length - decimalPlaces,
                                               preDecimal.length);
      preDecimal = preDecimal.substring(0,preDecimal.length - decimalPlaces);
    }

    // Place comma oriented delimiter every 3 characters
    // against the numeric represenation of the "left" side
    // of the decimal representation.  When finished, return
    // both the left side comma formatted value together with
    // the right side decimal formatted value.
    
    var regex  = new RegExp('(-?[0-9]+)([0-9]{3})');
 
    while(regex.test(preDecimal))
    {
       preDecimal = preDecimal.replace(regex, '$1' + comma + '$2');
    }
       
  }
  catch (exception) { AlertError("Format Number",exception); }
  return minus + preDecimal + postDecimal;
}

function FormatEmptyNumber(decimalDelimiter,decimalPlaces)
{
    var preDecimal = '0';
    var postDecimal = '';
 
    for(i=0;i<decimalPlaces;i++)
    {
      if (i==0) { postDecimal += decimalDelimiter; }
      postDecimal += '0';
    }
   return preDecimal + postDecimal;
}
  

 function AlertError(methodName,e)
 {
            if (e.description == null) { alert(methodName + " Exception: " + e.message); }
            else {  alert(methodName + " Exception: " + e.description); }
 }

 
 function SetDefaultFormValues()
 {
   document.getElementById('text1').value = FormatNumber(document.getElementById('text1').value,1,6);
   document.getElementById('text2').value = FormatNumber(document.getElementById('text2').value,2,1);
   document.getElementById('text3').value = FormatNumber(document.getElementById('text3').value,3,2);
   document.getElementById('text4').value = FormatNumber(document.getElementById('text4').value,1,3);
   document.getElementById('text5').value = FormatNumber(document.getElementById('text5').value,2,4);
   document.getElementById('text6').value = FormatNumber(document.getElementById('text6').value,3,5);
 }

</script>
 

  </HEAD>
<BODY onload="document.frmSubmit.text1.focus();SetDefaultFormValues();" >
 <form name=frmSubmit id=frmSubmit action="default.htm" method=post>

 <table border=0 align=center width="80%">

   <tr>
          <td align=left class=clsBodyText>Country 1 ( Comma= , Places = 6 )</td>
         <td align=left class=clsBodyText><input name=text1 type=text value='1019.71' 
              onblur="this.value=FormatNumber(this.value,1,6);" size=30 maxlength=30></td>
   </tr>
   <tr>
          <td align=left class=clsBodyText>Country 2 ( Comma= , Decimal= , Places = 1 )</td>
         <td align=left class=clsBodyText><input name=text2 type=text value='1019.71'
           onblur="this.value=FormatNumber(this.value,2,1);" size=30 maxlength=30></td>
   </tr>
   <tr>
          <td align=left class=clsBodyText>Country 3 ( Comma= * Decimal= # Places = 2 )</td>
         <td align=left class=clsBodyText><input name=text3 type=text value='1019.71' 
             onblur="this.value=FormatNumber(this.value,3,2);" size=30 maxlength=30></td>
   </tr>

   <tr>
          <td align=left class=clsBodyText>Country 1 ( Comma= , Places = 3 )</td>
         <td align=left class=clsBodyText><input name=text4 type=text value='1019.71'
              onblur="this.value=FormatNumber(this.value,1,3);" size=30 maxlength=30></td>
   </tr>
   <tr>
          <td align=left class=clsBodyText>Country 2 ( Comma= , Decimal= , Places = 4  )</td>
         <td align=left class=clsBodyText><input name=text5 type=text value='1019.71'
          onblur="this.value=FormatNumber(this.value,2,4);" size=30 maxlength=30></td>
   </tr>
   <tr>
          <td align=left class=clsBodyText>Country 3 ( Comma= * Decimal=# Places = 5 )</td>
         <td align=left class=clsBodyText><input name=text6 type=text value='1019.71' 
             onblur="this.value=FormatNumber(this.value,3,5);" size=30 maxlength=30></td>
   </tr>
 
 </table>
 
</form>
</BODY>
</HTML>

	    

Robbe has been a Microsoft MVP in C# since 2004.  He is also the co-founder of EggHeadCafe which provides .NET articles, book reviews, software reviews, and software download and purchase advice.


Pete's Blog   |    Pete's Resume   |    Robbe's Blog   |    Robbe's Resume   |    Archive #2   |    Archive #3   |    Dotnetslackers   |    XmlPitStop   |    Advertise   |   Contact Us   |   Privacy   |   Copyright (c) 2000 - 2009 eggheadcafe.com  All rights reserved.