$.fn.validate = function(input){
  var errclass = "input-error";
  var focused;
  var form = $(this);

  // Clear errors
  function clear() {
    $(this).parent().removeClass(errclass);
    $(this).parent().find('div.input-error').remove();
  }
  if (!input) {
    $(this).find('.error ul').empty();
    $(this).find('input').each(clear);
    $(this).find('textarea').each(clear);
    $(this).find('select').each(clear);
  } else $(input).each(clear);
    
  if (!input) $('div.input-error').remove();

  function validate(name,p,s){
    var inputs;
    if (input)
      inputs = $(input).parent().find(name);
    else
      inputs = $(this).find(name);
    // Here is where errors are inserted
    inputs.each(function(){
        // Don't bother validating an already invalid input
        if ($(this).parent().hasClass(errclass)) return true;
        if (p.call(this)) {
          $(this).parent().addClass(errclass);
          // Focus the input
          if (!focused && !input) {
            $(this).focus();
            focused = true;
          }
          //if (input) {
          var msg = $('<div class="input-error"></div>');
          msg.text(s);
          if ($(this).next().text()=='')
            $(this).parent().append(msg);
          else
            msg.insertBefore($(this).next());
        }
      });
  }

  validate.call(this,
                'input.required',
                function(){ return (this.type == 'file' || this.type == 'text' || this.type == 'password') && $(this).val().replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'textarea.required',
                function(){ return $(this).val().replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'select.required',
                function(){ return $(this).val().replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'input.postcode',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().toUpperCase().match(/^[A-Z0-9 ]+$/); 
                },
                "must be a valid UK post code");

  validate.call(this,
                'input.email',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[^@]+@[^@\.]+\.[^@\.]+/); 
                },
                "must be a valid email");

  validate.call(this,
                'input.date',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/); 
                },
                "must be a valid date");

  validate.call(this,
                'input.date-period',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}\-[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/); 
                },
                "must be a valid date period");

  validate.call(this,
                'input.time',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[0-9]{2}:[0-9]{2}$/); 
                },
                "must be a valid time");

  validate.call(this,
                'input.alphanum',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[a-zA-Z0-9]+$/); 
                },
                "must be letters or numbers");

  validate.call(this,
                'input.integer',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[-]{0,1}[0-9]+$/); 
                },
                "must be a valid integer number. E.g. 23, 1, 0, 36214, etc.");

  validate.call(this,
                'input.int',
                function(){
                  if ($(this).val()=='') return false;
                  else return (1*$(this).val()) > 1000000;
                },
                "number must be greater than zero");

  validate.call(this,
                'input.currency',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().match(/^[-]{0,1}[0-9][.]{0,1}[0-9]*$/); 
                },
                "must be a valid decimal number. E.g. 23.2, 1, 0, 36.24, etc.");

  validate.call(this,
                'input.overzero',
                function(){
                  if ($(this).val()=='') return false;
                  else if (!$(this).val().match(/^[-]{0,1}[0-9]+$/)) return false;
                  else return $(this).val() < 1;
                },
                "must be over zero");

  validate.call(this,
                'input.telnumber',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().toUpperCase().match(/^[0-9 -+]{6,25}$/); 
                },
                "must be a valid telephone number. Examples: 01234 123 456, 01234123123, +44 01421-234-234");

  validate.call(this,
                'input.cardnumber',
                function(){
                  if ($(this).val()=='') return false;
                  else {
                    var n = $(this).val().replace(/[^0-9]/g,'');
                      return !n.match(/^[0-9]{16,20}$/); // || !validCardDigits(n); 
                  }
                },
                "should be a valid credit card number in one of the following formats: 1111-2222-3333-4444 or 1111222233334444 or 1111 2222 3333 4444");

  validate.call(this,
                'input.password',
                function(){
                  if ($(this).val()=='') return false;
                  else return !$(this).val().toUpperCase().match(/[^0-9]*[0-9][^0-9]*[0-9][^0-9]*/); 
                },
                "should be at least six characters in length, and "+
                "include at least three numbers");

  var anyErrors = false;
  $(this).find('.input-error').each(function(){
      anyErrors = true;
      return false;
    });
  return !anyErrors;
}

  $(document).ready(function(){
      $('form').each(function(){
          var form = $(this);
          function val() {
            $(this).change(function(){ 
                form.validate(this);
              });
          }
          form.find('input').each(val);
          form.find('textarea').each(val);
          form.find('select').each(val);

          form.submit(function(){                       
              $(this).find('div.error').remove();
              return $(this).validate();
            });
        });
      $('.main-form input').each(function(){
          $(this).focus();
          return false;
        });
    });

jQuery.fn.extend({
  scrollTo : function(speed, done) {
      return this.each(function() {
          var targetOffset = $(this).offset().top;
          $('html,body').animate({scrollTop: targetOffset}, speed,"linear", done);
        });
    }
  }); 

function validCardDigits( cardNumber ) { // LUHN Formula for validation of credit card numbers.
  var ar = new Array( cardNumber.length );
  var i = 0,sum = 0;
  for( i = 0; i < cardNumber.length; ++i ) ar[i] = parseInt(cardNumber.charAt(i));
  for( i = ar.length -2; i >= 0; i-=2 ) { // you have to start from the right, and work back.
    ar[i] *= 2;				  // every second digit starting with the right most (check digit)
    if( ar[i] > 9 ) ar[i]-=9;		  // will be doubled, and summed with the skipped digits.
  }					  // if the double digit is > 9, add those individual digits together 
  for( i = 0; i < ar.length; ++i )
    sum += ar[i];			  // if the sum is divisible by 10 mod10 succeeds
  return (((sum%10)==0)?true:false);	 	
}

