


// Regular expressions for validation functions
var isNonblank_re    = /\S/;
var isWhole_re       = /^\s*\d+\s*$/;
var isInteger_re     = /^\s*(\+|-)?\d+\s*$/;
var isDecimal_re     = /^\s*(\+|-)?((\d+(\.\d+)?)|(\.\d+))\s*$/;
var isCurrency_re    = /^\s*(\+|-)?((\d+(\.\d\d)?)|(\.\d\d))\s*$/;
var isEmail_re       = /^\s*[\w\-\+_]+(\.[\w\-\+_]+)*\@[\w\-\+_]+\.[\w\-\+_]+(\.[\w\-\+_]+)*\s*$/;


var creditCardList = [
   //type      prefix   length
   ["amex",    "34",    15],
   ["amex",    "37",    15],
   ["disc",    "6011",  16],
   ["mc",      "51",    16],
   ["mc",      "52",    16],
   ["mc",      "53",    16],
   ["mc",      "54",    16],
   ["mc",      "55",    16],
   ["visa",    "4",     13],
   ["visa",    "4",     16]
];


////////////////////////////////////////////////////////////
// Helper functions


// Returns a string with all the non-digits removed
function getdigits (s) {
   return s.replace (/[^\d]/g, "");
}


// Luhn checksum algorithm
// This assumes that all characters of cc are digits
function luhn (cc) {
   var sum = 0;
   var i;

   for (i = cc.length - 2; i >= 0; i -= 2) {
      sum += Array (0, 2, 4, 6, 8, 1, 3, 5, 7, 9) [parseInt (cc.charAt (i), 10)];
   }
   for (i = cc.length - 1; i >= 0; i -= 2) {
      sum += parseInt (cc.charAt (i), 10);
   }
   return (sum % 10) == 0;
}


////////////////////////////////////////////////////////////
// Validation functions.  These all return true/false


// Check if string is non-blank
function isNonblank (s) {
   return String (s).search (isNonblank_re) != -1
}


// Check if string is a whole number
function isWhole (s) {
   return String(s).search (isWhole_re) != -1
}


// Check if string is an integer
function isInteger (s) {
   return String(s).search (isInteger_re) != -1
}


// Check if string is decimal number
function isDecimal (s) {
   return String(s).search (isDecimal_re) != -1
}


// Check if string is currency
function isCurrency (s) {
   return String(s).search (isCurrency_re) != -1
}


// Check if string is a valid email address
function isEmail (s) {
   return String(s).search (isEmail_re) != -1;
}


// Check for valid credit card type/number
function isValidCC (cctype, ccnumber) {
   var cc = getdigits (ccnumber);
   if (luhn (cc)) {
      for (var i in creditCardList) {
         if (creditCardList [i][0] == (cctype.toLowerCase ())) {
            if (cc.indexOf (creditCardList [i][1]) == 0) {
               if (creditCardList [i][2] == cc.length) {
                  return true;
               }
            }
         }
      }
   }
   return false;
}


// Check for valid ABA bank routing number
function isValidABA (routingNumber) {
   var n = getdigits (routingNumber);
   return (n.length == 9) && (
         (parseInt (n.charAt (0), 10) * 3) +
         (parseInt (n.charAt (1), 10) * 7) +
         (parseInt (n.charAt (2), 10) * 1) +
         (parseInt (n.charAt (3), 10) * 3) +
         (parseInt (n.charAt (4), 10) * 7) +
         (parseInt (n.charAt (5), 10) * 1) +
         (parseInt (n.charAt (6), 10) * 3) +
         (parseInt (n.charAt (7), 10) * 7) +
         (parseInt (n.charAt (8), 10) * 1)
      ) % 10 == 0;
}
