function Validator(validationColor)
{
  this.validate = vdValidate;
  this.validationColor = validationColor;
  this.textColors = new Array();
  this.clearValidationError = vdClearValidationError;
  this.showValidationError = vdShowValidationError;
  this.validateAndSubmit = vdValidateAndSubmit;
  this.validateServerSide = vdValidateServerSide;
  this.serverSideErrors = new Array();
  this.addServerSideError = vdAddServerSideError;
  
  function vdAddServerSideError(error)
  {
    this.serverSideErrors[this.serverSideErrors.length]=error;
  }
  
  function vdValidateServerSide(command)
  {
    var form          = document.getElementById(command);
    
    for( var y = 0; y < this.serverSideErrors.length; y++ )
    {
      var error         = this.serverSideErrors[y];
      var inputElement  = document.getElementById(error.elementID);
      var input         = new Input(inputElement, form);
      this.showValidationError( command, input, error.message ); 
    }
  }
  
  function vdValidate(command)
  {
    var valid = true;
    var form  = document.getElementById(command);
    var serverSideValidators = Array();
    
    for( var y = 0; y < form.elements.length; y++ )
    {
      var input = new Input(form.elements[y], form);
      this.clearValidationError( command, input ); 
    }
    
    for( var y = 0; y < form.elements.length; y++ )
    {
      var input = new Input(form.elements[y], form);
      
      if( input.element.getAttribute("validate") )
      {
        var value     = input.element.getAttribute("validate");
        
        if( value.indexOf(";") >= 0 )
        {
          validators    = value.split(";");
        }
        else
        { 
          validators = new Array();
          validators[0] = value;
        }
        
        
        for( var validatorCounter = 0; validatorCounter < validators.length; validatorCounter++ )
        {
          var validatorString = validators[validatorCounter];
          var validator;
          if( validatorString != "" )
          {
            eval(" validator = new " + validatorString + ";" );
            if( validator )
            {
              if( !validator.validate(form.elements[y]) )
              {
                valid     = false;
                this.showValidationError( command, input, validator.message ); 
              }
            }
            // probably a server side validator
            else
            {
              this.serverSideValidators[serverSideValidators.length] == value;
            }
          }
        }
      }
    }
    
    return valid;
  }
  
  function vdValidateAndSubmit(command)
  {
    try
    {
      if( this.validate(command) )
      {
        var form  = document.getElementById(command);
        if( form )
          form.submit();
      }
      else
      {
        scroll(0,0);
      }
    }catch(e){}
  }
  
  function vdShowValidationError(command, input, message)
  {
    var domHelper = new DomHelper();
    if( input && input.label )
    {
      this.textColors[input.element.id] = domHelper.getComputedStyleElement(input.label, "color");
      input.label.style.color = this.validationColor;
    }
    
    var domHelper     = new DomHelper();
    // Each form element has own error, which goes into a common form error div
    if( message )
    {
      tags = domHelper.findTagsByAttribute("for", input.form.id, "error");
      if(tags[0])
      {
        tags[0].innerHTML += "<span class='validatorError'>" + message + "</span>";
      }
    }
    // One error message for entire form, which goes into a common error div, e.g. Please input all required fields
    else
    {
      tags = domHelper.findTagsByAttribute("for", input.form.id, "error");
      if( tags[0] && input.form.getAttribute("message") )
      {
        tags[0].innerHTML = input.form.getAttribute("message");
      }
    }
  }

  function vdClearValidationError( command, input )
  {
    tags = domHelper.findTagsByAttribute("for", input.form.id, "error");
    if( tags[0] )
    {
      tags[0].innerHTML = "";
    }
    
    if( input && input.label && this.textColors[input.element.id] )
    {
      input.label.style.color=this.textColors[input.element.id];
    }
  }
}

validator = new Validator('red', 'black');

// validators
function required(m)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    if( element.value == null || element.value == "" )
      return false;
    
    return true;
  }
}

function vLength(m,size)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    if( element.value == null || element.value == "" )
      return false;

    if( element.value.length < size )
      return false;

    return true;
  }
}

function vCannotContain(m,cantContain)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
  
    cantContainArray = new Array();
    
    if( cantContain.indexOf(',') >= 0 )
    {
      cantContainArray = cantContain.split(',');
    }
    else
    {
      cantContainArray = new Array();
      cantContainArray[0] = cantContain;
    }
    
    for( var y = 0; y < cantContainArray.length; y++ )
    {
      var toCheckFor = cantContainArray[y];
      
      if( toCheckFor != "" )
      {
        if( element.value.indexOf(toCheckFor) >= 0 )
        {
          return false;
        }
      }
      
    }

    return true;
  }
}

function vCannotBe(m,value)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    if( element.value == value )
    {
      return false;
    }

    return true;
  }
}

function email(m)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    if( element.value == null || element.value == "" )
      return false;
    
    var str = element.value;
    if( !(str.lastIndexOf(".") > 2  && str.indexOf("@") > 0) )  
      return false;
    
    return true;
  }
}

function vTwoDecimalPlaces(m)
{
  this.validate = rValidate;
  
  function rValidate(element)
  {
    numStr = element.value;
    if( numStr.indexOf(".") < 0 )
    {
      return false;
    }
    matches = numStr.match(/\$?[1-9]{1}[0-9]{0,99}(\.[0-9]{2})?/g);
    for(i in matches){
    if(matches[i] == numStr){
    return true;
    }
    }
    return false;
  }
}


function match(m,toMatchID)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    var toMatch = document.getElementById(toMatchID);
    if( element.value != toMatch.value )
      return false;
    
    return true;
  }
}



function time(m)
{
  this.validate = rValidate
  this.message  = m;
  function rValidate( element )
  {
    if( element.value == null || element.value == "" )
      return false;
    
    var str = element.value;
    var timePat = /^(\d{1,2}):(\d{2})(:(\d{2}))?(\s?(AM|am|PM|pm))?$/;

    var matchArray = str.match(timePat);
    if (matchArray == null) 
    {
      return false;
    }
    
    hour = matchArray[1];
    minute = matchArray[2];
    second = matchArray[4];
    ampm = matchArray[6];

    if (second=="") { second = null; }
    if (ampm=="") { ampm = null }

    if (hour < 0  || hour > 23) 
    {
      return false;
    }
    if (hour <= 12 && ampm == null) 
    {
      return false;
    }
    if  (hour > 12 && ampm != null) 
    {
      return false;
    }
    if (minute<0 || minute > 59) 
    {
      return false;
    }
    if (second != null && (second < 0 || second > 59)) 
    {
      return false;
    }
    
    return true;
  }
}

function vRequireOne(m,toMatchIDStub)
{
  this.validate = rValidate
  this.message  = m;
  
  function rValidate( element )
  {
    var form = element.form;
    
    for( var y = 0; y < form.elements.length; y++ )
    {
      
      var e = form.elements[y];
      if( e.getAttribute("name").indexOf(toMatchIDStub) > -1 ) 
      {
        if( e.getAttribute("type") == "checkbox" )
        {
          if( e.checked )
            return true;
        }
        else
        {
          if( e.value != null && e.value != "" )
            return true;
        }
      }
    }
    
    return false;
  }
}


function vCreditCard(m)
{
  this.validate = rValidate
  this.validateVisa = rValidateVisa;
  this.validateMasterCard = rValidateMasterCard;
  this.validateAmex = rValidateAmex;
  this.validateDiscover = rValidateDiscover;
  this.checkCard = rCheckCard;
  this.message  = m;
  
  function rValidateVisa(value)
  {
    var re = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
    return this.checkCard(re, value);
  }
  
  function rValidateMasterCard(value)
  {
    var re = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
    return this.checkCard(re, value);
  }
  
  function rValidateAmex(value)
  {
    //var re = /^3[4,7]\d{13}$/;
    var re = /^3[47][0-9]{13}$/;
    
    return this.checkCard(re, value);
  }
  
  function rValidateDiscover(value)
  {
    var re = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
    return this.checkCard(re, value);
  }
  
  function rCheckCard(re, ccnum)
  {
     if (!re.test(ccnum)) return false;
     // Remove all dashes for the checksum checks to eliminate negative numbers
     ccnum = ccnum.split("-").join("");
     // Checksum ("Mod 10")
     // Add even digits in even length strings or odd digits in odd length strings.
     var checksum = 0;
     for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
        checksum += parseInt(ccnum.charAt(i-1));
     }
     // Analyze odd digits in even length strings or even digits in odd length strings.
     for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
        var digit = parseInt(ccnum.charAt(i-1)) * 2;
        if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
     }
     if ((checksum % 10) == 0) return true; else return false;  
  }
  
  function rValidate(element)
  {
    
    var value = element.value;
    
    if( this.validateVisa(value)
    ||  this.validateAmex(value)
    ||  this.validateMasterCard(value)
    ||  this.validateDiscover(value))
    {
      return true;
    }
    return false;
    
  }
}
/*
function isValidCreditCard(type, ccnum) {
   if (type == "Visa") {
      // Visa: length 16, prefix 4, dashes optional.
      var re = /^4\d{3}-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "MC") {
      // Mastercard: length 16, prefix 51-55, dashes optional.
      var re = /^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "Disc") {
      // Discover: length 16, prefix 6011, dashes optional.
      var re = /^6011-?\d{4}-?\d{4}-?\d{4}$/;
   } else if (type == "AmEx") {
      // American Express: length 15, prefix 34 or 37.
      var re = /^3[4,7]\d{13}$/;
   } else if (type == "Diners") {
      // Diners: length 14, prefix 30, 36, or 38.
      var re = /^3[0,6,8]\d{12}$/;
   }
   if (!re.test(ccnum)) return false;
   // Remove all dashes for the checksum checks to eliminate negative numbers
   ccnum = ccnum.split("-").join("");
   // Checksum ("Mod 10")
   // Add even digits in even length strings or odd digits in odd length strings.
   var checksum = 0;
   for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
      checksum += parseInt(ccnum.charAt(i-1));
   }
   // Analyze odd digits in even length strings or even digits in odd length strings.
   for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
      var digit = parseInt(ccnum.charAt(i-1)) * 2;
      if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
   }
   if ((checksum % 10) == 0) return true; else return false;
}
*/

