var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var blanks = " \t\n\r";  // aka whitespace chars

// decimal point character differs by language and culture
var decimalPointDelimiter = "."


// Returns true if string s is empty

function isEmpty(s)
  {
  return ((s == null) || (s.length == 0));
  }


// Returns true if string s is empty or all blank chars

function isBlank(s)
  {
  var i;

  // Is s empty?
  if (isEmpty(s))
    return true;

  // Search through string's chars one by one until we find first
  // non-blank char, then return false; if we don't, return true
  for (i=0; i<s.length; i++)
    {   
    // Check that current character isn't blank
    var c = s.charAt(i);
    if (blanks.indexOf(c) == -1) 
      return false;
    }
  // All characters are blank
  return true;
  }

// Removes all characters which appear in string bag from string s

function stripCharsInBag (s, bag)
  {
  var i;
  var returnString = "";

  // Search through string's characters one by one;
  // if character is not in bag, append to returnString
  for (i = 0; i < s.length; i++)
    {   
    // Check that current character isn't blank
    var c = s.charAt(i);
    if (bag.indexOf(c) == -1) 
      returnString += c;
    }
  return returnString;
  }


// Removes all characters which do NOT appear in string bag from string s

function stripCharsNotInBag (s, bag)
  {
  var i;
  var returnString = "";

  // Search through string's characters one by one;
  // if character is in bag, append to returnString
  for (i = 0; i < s.length; i++)
    {   
    // Check that current character isn't blank
    var c = s.charAt(i);
    if (bag.indexOf(c) != -1) 
      returnString += c;
    }
  return returnString;
  }


// Removes all blank chars (as defined by blanks) from s

function stripBlanks(s)
  {
  return stripCharsInBag(s, blanks)
  }


// Removes leading blank chars (as defined by blanks) from s

function stripLeadingBlanks(s)
  { 
  var i = 0;
  while ((i < s.length) && (blanks.indexOf(s.charAt(i)) != -1))
     i++;
  return s.substring(i, s.length);
  }


// Removes trailing blank chars (as defined by blanks) from s

function stripTrailingBlanks(s)
  { 
  var i = s.length - 1;
  while ((i >= 0) && (blanks.indexOf(s.charAt(i)) != -1))
     i--;
  return s.substring(0, i+1);
  }


// Removes leading+trailing blank chars (as defined by blanks) from s

function stripLeadingTrailingBlanks(s)
  { 
  s = stripLeadingBlanks(s);
  s = stripTrailingBlanks(s);
  return s;
  }


// Returns true if character c is an English letter (A .. Z, a..z)

function isLetter(c)
  {
  return (((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")));
  }


// Returns true if character c is a digit (0 .. 9)

function isDigit(c)
  {
  return ((c >= "0") && (c <= "9"));
  }


// Returns true if all chars in string s are numbers;
// first character is allowed to be + or -; does not 
// accept floating point, exponential notation, etc.

function isInteger(s)
  {
  if (isBlank(s))
    return false;

  // skip leading + or -
  if ((s.charAt(0) == "-") || (s.charAt(0) == "+"))
    var i = 1;
  else
    var i = 0;

  // Search through string's chars one by one until we find a 
  // non-numeric char, then return false; if we don't, return true
  for (i; i<s.length; i++)
    {   
    // Check that current character is number
    var c = s.charAt(i);
    if (!isDigit(c)) 
      return false;
    }
  // All characters are numbers
  return true;
  }


// True if string s is an unsigned floating point (real) number; 
// first character is allowed to be + or -; no exponential notation.

function isFloat(s)
  { 
  var seenDecimalPoint = false;

  if (isBlank(s)) 
    return false;
  if (s == decimalPointDelimiter) 
    return false;

  // skip leading + or -
  if ((s.charAt(0) == "-") || (s.charAt(0) == "+"))
    var i = 1;
  else
    var i = 0;

  // Search through string's chars one by one until we find a 
  // non-numeric char, then return false; if we don't, return true

  for (i; i<s.length; i++)
    {   
    // Check that current character is number
    var c = s.charAt(i);

    if ((c == decimalPointDelimiter) && !seenDecimalPoint) 
      seenDecimalPoint = true;
    else if (!isDigit(c)) 
      return false;
    }
  // All characters are numbers
  return seenDecimalPoint;
  }


// Returns true if string s is English letters (A .. Z, a..z) only

function isAlphabetic(s)
  {
  var i;

  if (isBlank(s)) 
     return false;

  // Search through string's chars one by one until we find a 
  // non-alphabetic char, then return false; if we don't, return true

  for (i = 0; i < s.length; i++)
  {   
  // Check that current character is letter
  var c = s.charAt(i);

  if (!isLetter(c))
    return false;
  }

  // All characters are letters
  return true;
  }


// Returns true if string s is English letters (A .. Z, a..z) and numbers only

function isAlphanumeric(s)
  {
  var i;

  if (isBlank(s)) 
     return false;

  // Search through string's chars one by one until we find a 
  // non-alphanumeric char, then return false; if we don't, return true

  for (i = 0; i < s.length; i++)
    {   
    // Check that current character is number or letter
    var c = s.charAt(i);

    if (! (isLetter(c) || isDigit(c) ) )
    return false;
    }

  // All characters are numbers or letters
  return true;
  }


// reformatString(targetStr [, str1, int1, str2, int2, ... strN, intN])       
//
// Handy function for arbitrarily inserting formatting characters
// or delimiters of various kinds within targetString.
//
// reformatString() takes one required string argument, targetStr, 
// and 0-N optional string/integer-pair arguments. These optional 
// arguments specify how targetStr is to be reformatted and how/where 
// other strings are to be inserted in it.
//
// EXAMPLES:
//
// * To reformat a 10-digit U.S. phone number from "1234567890"
//   to "(123)456-7890" make this function call:
//   reformatString("1234567890", "(", 3, ")", 3, "-", 4)

function reformatString(targetString)
  { 
  var arg;
  var sPos = 0;
  var resultString = "";

  for (var i=1; i<reformatString.arguments.length; i++)
    {
    arg = reformatString.arguments[i];
    if (i%2 == 1) 
      {
      resultString += arg;
      }
    else
      {
      resultString += targetString.substring(sPos, sPos + arg);
      sPos += arg;
      }
    }
  return resultString;
  }

// Returns true if string is a valid email address: @ and . required,
// at least one char before @, at least one char before and after .

function isEmail(s)
  { 
  if (isBlank(s)) 
    return false;
  
  // there must be >= 1 character before @, so we start
  // start looking at character position 1 (i.e. second character)
  var i = 1;
  var sLength = s.length;

  // look for @
  while ((i < sLength) && (s.charAt(i) != "@"))
    i++

  if ((i >= sLength) || (s.charAt(i) != "@")) 
    return false;
  else 
    i += 2;

  // look for .
  while ((i < sLength) && (s.charAt(i) != "."))
    i++

  // there must be at least one character after the .
  if ((i >= sLength - 1) || (s.charAt(i) != ".")) 
    return false;
  else 
    return true;
  }

// Returns true if string s is an integer such that a <= s <= b

function isIntegerInRange (s, a, b)
  { 
  if (isBlank(s)) 
    return false;
  if (!isInteger(s)) 
    return false;
  var num = parseInt(s);
  return ((num >= a) && (num <= b));
  }

// Returns index of checked radio button in radio set,
// or -1 if no radio buttons are checked

function getCheckedRadioButton(radioSet)
  { 
  for (var i=0; i<radioSet.length; i++)
    if (radioSet[i].checked)
      return i;
  return -1;
  }


// Returns array containing index(es) of checked checkbox(es) 
// in checkbox set, or -1 if no checkboxes are checked

function getCheckedCheckboxes(checkboxSet)
  {
  var arr = new Array();
  for (var i=0,j=0; i<checkboxSet.length; i++)
    if (checkboxSet[i].checked)
      arr[j++] = i;
  if (arr.length > 0)
    return arr;
  else
    return -1;
  }


// Returns array containing index(es) of checked option(s) 
// in select box, or -1 if no options are selected

function getCheckedSelectOptions(select)
  {
  var arr = new Array();
  for (var i=0,j=0; i<select.length; i++)
    if (select.options[i].selected)
      arr[j++] = i;
  if (arr.length > 0)
    return arr;
  else
    return -1;
  }
