$.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);
          var lastinput = $(this);
          while (lastinput.next('select,input,textarea').length > 0)
            lastinput = lastinput.next('select,input,textarea');
          if (lastinput.next().text()=='')
            $(this).parent().append(msg);
          else
            msg.insertBefore(lastinput.next());
        }
      });
  }

  validate.call(this,
                'input.required',
                function(){ return (this.type == 'file' || this.type == 'text' || this.type == 'password') && this.value.replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'textarea.required',
                function(){ return this.value.replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'select.required',
                function(){ return this.value.replace(/[ ]+/,'') == ''; },
                "must be completed");

  validate.call(this,
                'input.postcode',
                function(){
                  if (this.value=='') return false;
                  else return !this.value.toUpperCase().match(/^[A-Z0-9 ]+$/); 
                },
                "must be a valid UK post code");

  validate.call(this,
                'input.email',
                function(){
                  if (this.value=='') return false;
                  else return !this.value.match(/^[^@]+@[^@\.]+\.[^@\.]+/); 
                },
                "must be a valid email");

  validate.call(this,
                'input.alphanum',
                function(){
                  if (this.value=='') return false;
                  else return !this.value.match(/^[a-zA-Z0-9]+$/); 
                },
                "must be letters or numbers");

  validate.call(this,
                'input.integer',
                function(){
                  if (this.value=='') return false;
                  else return !this.value.match(/^[-]{0,1}[0-9]+$/); 
                },
                "must be a valid integer number. E.g. 23, 1, 0, 36214, etc.");

  validate.call(this,
                'input.overzero',
                function(){
                  if (this.value=='') return false;
                  else if (!this.value.match(/^[-]{0,1}[0-9]+$/)) return false;
                  else return this.value < 1;
                },
                "must be over zero");

  validate.call(this,
                'input.telnumber',
                function(){
                  if (this.value=='') return false;
                  else return !this.value.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.value=='') return false;
                  else {
                    var n = this.value.replace(/[^0-9]/g,'');
                    return !n.match(/^[0-9]{16}[0-9]*$/); // || !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.value=='') return false;
                  else return !this.value.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();
            });
        });
    });

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);	 	
}
