/*
 Nerv Validator jQuery Plugin
 Author Wojciech Jerczynski (vic@nerv.co.uk)
 Copyright(c) for ever and ever Wojciech Jerczynski;
 DO NOT EDIT, CHANGE OR ADAPT IN ANY WAY!
 IF YOU DONT LIKE WHAT IT DOES - WRITE YOUR OWN PLUGIN!
 */

/*
 HOW TO USE IT

  YOUR FORM

  Each of your inputs and textareas etc will require three additional HTML5 attributes

  data-default - holds default value of a field ("Please enter your email" for example)
  data-valid - hold rules that field needs to be check against
  data-prefix - holds the field name you want to appear in the error message.

  <input type="XX" data-default="Please enter something" data-valid="required email postcode checked min_x max_x numeric" data-prefix="Custom name of a field">

  Testing rules

    required - checks whether field is empty or default value
    email - checks if it is an email address
    postcode - checks if it is a valid UK post code
    checked - USE ONLY ON CHECKBOXES - checks if the checkbox was selected
    min_X - (X=number) checks if the value is at least X characters long
    max_X - checks if the value is not longer than X characters long
    numeric - checks if the value is a numeric value

 You can chain testing methods in data-valid attribute so
 data-valid="required min_6 max_20 email" - will check if field is not empty or default, if it is at least 6 characters long and not exceed 20 characters and if it is a valid email

 YOUR JS

  Attach plugin to the form element, id or a class.

  var config = {
      whileYouType: true or false,
      errorPerField: true or false
      formFieldWrapper: "#my_id" or ".my_class"
      formFieldErrorClass: "myErrorClass"

    }

  $("selector").nerValid(config);

 NerValid accepts these options:

    whileYouType: true/false,
    this true will validate entry as you type (not yet);

    errorPerField: true/false,
    this true will display errors under the field / false will create a box with errors on top of the form


    formFieldWrapper:"",
    accepts selectors in a jQuery class or id format so "#my_selector" or ".my_selector" - so formFieldWrapper:".my_selector"
    this is for the situation when you wrap your inputs in a <div> with a certain class attached to it and you want the
    error messages to style the wapping box rather than input. Can be left empty or;

    formFieldErrorClass:""

    for styling purpose you can pass your error class name to the plugin DON'T USE "." before the name so formFieldErrorClass:"my_error_class";
    this class will be applied to the input or wrapping box if the box selector is specified. When you dont specify your own class default
    error styles will be applied so 1px red border.

*/

(function($) {

  var nerValidErrors = [];
  $.fn.nerValid = function(options) {

    $.fn.nerValid.opts = $.extend({}, $.fn.nerValid.defaults, options);

    var keypressTimer = null;
    var validatedElement = null;
    return this.each(function() {

      $this = $(this);

      $formfields = $this.find("input:not(':submit'),textarea");

//Uncomment this section if you want to validate the form on submit.

/*
      $this.submit(function(event){
          nerValidErrors = [];
          $.fn.nerValid.validateForm($formfields);
          if(nerValidErrors.length>0){
            $.fn.nerValid.displayErrors($.fn.nerValid.opts);
            event.preventDefault();
          }
      });
*/


      $(".reset").bind("click",function(e){
	e.preventDefault();
	$(".invalid,.valid").remove();
	
	$formfields.each(function(i,e){
	  if($(this).attr("data-default") != "" && $(this).attr("data-default") != undefined){
	    $(this).val($(this).attr("data-default"));
	    $(this).addClass("nerValidDefaultValue")
	  }
	});
	  
      });

      $formfields.each(function(i,e){

        if($(this).attr("data-default") != "" && $(this).attr("data-default") != undefined){
          $(this).val($(this).attr("data-default"));
          $(this).addClass("nerValidDefaultValue")
        }

        $(this).bind("focus",function(){
          if($(this).val() == $(this).attr("data-default")){
            $(this).val("");
            $(this).removeClass("nerValidDefaultValue");
          }

        });

        $(this).bind("blur",function(){
	  
	  $zis = $(this);
	  
	  if($(this).hasClass("dateEntry")){
	    setTimeout(function(){
	      $.fn.nerValid.validateElement($zis);
	      $.fn.nerValid.displayErrors( $.fn.nerValid.opts);    
	    },200);
	  }else{
	    $.fn.nerValid.validateElement($zis);
	    $.fn.nerValid.displayErrors( $.fn.nerValid.opts);  
	  }
          
        });

        if($.fn.nerValid.opts.whileYouType){

          

          $(this).bind("keyup",function(event){
            var tester = $(this);
            //when you tab between form elems it fires keyUp on the focused element
            //rather than the one that it left so run it when any other key is pressed.
            if(event.keyCode != 9){
              keypressTimer = setTimeout(function(){
                $.fn.nerValid.validateElement(tester);
                $.fn.nerValid.displayErrors( $.fn.nerValid.opts);
              },500);
            }


          });
	  
	  $(this).bind("keydown",function(event){
		      if((keypressTimer != null)){
			clearTimeout(keypressTimer);
			keypressTimer = null;
		      }
		    });
        }

      })

      $("body").append("<style>.nerValidErrorClass{border:1px solid #cc0000;} .nerValidDefaultValue{color:#cccccc !important;}</style>")

    });
  };

  $.fn.nerValid.validateForm = function(elements){

    $.each(elements,function(){
       $.fn.nerValid.validateElement($(this));
    });

    return false;
  };

  $.fn.nerValid.validateElement = function(element){
    validateElement = element;
    var tests = null;

    if(element.attr("data-validation") != "" && element.attr("data-validation") != undefined){
      tests = element.attr("data-validation").split(" ");
    }

    if(tests != null){

      for(i in tests){

      switch(tests[i]){
        case("required"):
          var notEmpty = $.fn.nerValid.isNotEmpty(element);
        if(!notEmpty){
            $.fn.nerValid.addToErrors(element,"field cannot be empty")
        }else{
            $.fn.nerValid.removeFromErrors(element,"field cannot be empty");
        }
        break;

        case("email"):
          var isValidEmail = $.fn.nerValid.isEmail(element.val());
          if(!isValidEmail){
            $.fn.nerValid.addToErrors(element,"is not a valid email")
          }else{
            $.fn.nerValid.removeFromErrors(element,"is not a valid email")
          }
        break;

        case("postcode"):
          var isValidPostcode = $.fn.nerValid.isUKPC(element.val());
          if(!isValidPostcode){
            $.fn.nerValid.addToErrors(element,"is not a valid postcode")
          }else{
            $.fn.nerValid.removeFromErrors(element,"is not a valid postcode")
          }
        break;

        case("checked"):
          var isChecked = $.fn.nerValid.isChecked(element);
          if(!isChecked){
            $.fn.nerValid.addToErrors(element,"is not selected")
          }else{
            $.fn.nerValid.removeFromErrors(element,"is not selected")
          }
        break;

        case("numeric"):
          var isNumeric = $.fn.nerValid.isNumeric(element);
          if(!isNumeric){
            $.fn.nerValid.addToErrors(element,"is not a numeric value")
          }else{
            $.fn.nerValid.removeFromErrors(element,"is not a numeric value")
          }
        break;
      }

      if(tests[i].indexOf("min_")!= -1){
        var testOf = tests[i].split("_");
        var hasMinLength = $.fn.nerValid.isMinCharLong(element,testOf[1]);

        if(!hasMinLength){
            $.fn.nerValid.addToErrors(element,"must be at least "+testOf[1]+" characters long")
        }else{
            $.fn.nerValid.removeFromErrors(element,"must be at least "+testOf[1]+" characters long")
        }

      }

      if(tests[i].indexOf("max_")!= -1){
        var testOf = tests[i].split("_");
        var hasMinLength = $.fn.nerValid.isMaxCharLong(element,testOf[1]);

        if(!hasMinLength){
            $.fn.nerValid.addToErrors(element,"must be maximum "+testOf[1]+" characters long")
        }else{
            $.fn.nerValid.removeFromErrors(element,"must be maximum "+testOf[1]+" characters long")
        }

      }


      }

      }
  };

  $.fn.nerValid.defaults = {
    whileYouType: false,
    errorPerField: false,
    formFieldWrapper:"",
    formFieldErrorClass:"",
    imageValidation:false
  };

  $.fn.nerValid.isMinCharLong = function(field,length){
    return (field.val().length >= length);
  }

  $.fn.nerValid.isMaxCharLong = function(field,length){
    return (field.val().length <= length);
  }

  $.fn.nerValid.addToErrors = function(field,errorMessage){

    var canAddError = true;

    $.each(nerValidErrors,function(i,e){

      if(field.attr("name") == e.elem.attr("name") && e.error == errorMessage){
                canAddError = false;
        }
    });

    if(canAddError){

      nerValidErrors.push({elem:field,error:errorMessage});

    }

  }

  $.fn.nerValid.removeFromErrors = function(field,errorMessage){
      for(var i=0; i<nerValidErrors.length;i++){
	  if(field.attr("name") == nerValidErrors[i].elem.attr("name") && nerValidErrors[i].error == errorMessage){

          if($.fn.nerValid.opts.formFieldWrapper != ""){
                if($.fn.nerValid.opts.formFieldErrorClass ==""){
                    nerValidErrors[i].elem.parents($.fn.nerValid.opts.formFieldWrapper).removeClass("nerValidErrorClass")
                }else{
                    nerValidErrors[i].elem.parents($.fn.nerValid.opts.formFieldWrapper).removeClass($.fn.nerValid.opts.formFieldErrorClass);
                }
          }else{
                if($.fn.nerValid.opts.formFieldErrorClass ==""){
                  nerValidErrors[i].elem.removeClass("nerValidErrorClass")
                }else{
                  nerValidErrors[i].elem.parents($.fn.nerValid.opts.formFieldWrapper).removeClass($.fn.nerValid.opts.formFieldErrorClass);
                }
          }
	  
	  if($.fn.nerValid.opts.imageValidation){
	    field.parent().find(".invalid").removeClass("invalid").addClass("valid");
	  }
	  
          nerValidErrors.splice(i,1);
          }
      }
  }


  $.fn.nerValid.displayErrors = function(options){
    
    if(!options.imageValidation){
      
	    if(options.errorPerField){
	      $("div.errors").empty();
	      if(nerValidErrors.length>0){
		$.each(nerValidErrors,function(i,e){
		  if($("#"+e.elem.attr("name")+"_error").length<1){
	
		    e.elem.after('<div id="'+e.elem.attr("name")+'_error" class="errors"></div>')
		  }
		  $("#"+e.elem.attr("name")+"_error").append("<p>"+e.elem.attr("data-prefix")+" "+e.error+"</p>");
	
		  if(options.formFieldWrapper != ""){
		    if(options.formFieldErrorClass ==""){
		      e.elem.parents(options.formFieldWrapper).addClass("nerValidErrorClass")
		    }else{
		      e.elem.parents(options.formFieldWrapper).addClass(options.formFieldErrorClass);
		    }
		  }else{
		    if(options.formFieldErrorClass ==""){
		      e.elem.addClass("nerValidErrorClass");
		    }else{
		      e.elem.addClass(options.formFieldErrorClass);
		    }
		  }
	
		});
	      }
	    }else{
	      if($("div.errors").length<1){
		$this.prepend('<div class="errors"></div>')
	      }
	      $("div.errors").empty();
	      if(nerValidErrors.length>0){
		$.each(nerValidErrors,function(i,e){
		$("div.errors").append("<p>"+e.elem.attr("data-prefix")+" "+e.error+"</p>");
		});
	      }else{
		$("div.errors").empty();
	      }
	    }
          
    }else{
	
	      if(nerValidErrors.length>0){
		$.each(nerValidErrors,function(i,e){
		  if($("#"+e.elem.attr("name")+"_error").length<1){
		    e.elem.after('<div id="'+e.elem.attr("name")+'_error" class="invalid"></div>')
		  }else{
		    $("#"+e.elem.attr("name")+"_error").removeClass("valid").addClass("invalid");
		  }
		});
	      }else{
		 if($("#"+validateElement.attr("name")+"_error").length<1){
		    validateElement.after('<div id="'+validateElement.attr("name")+'_error" class="valid"></div>');
		 }
	      }
    }
    
    $("div.errors>*").css({color:"#cc0000",margin:"0",fontSize:"0.76em"})
  }

  $.fn.nerValid.isNumeric = function(element){
    return (!isNaN(element.val()));
  }

  $.fn.nerValid.isChecked = function(element){
    return (element.attr("checked")) ;
  }

  $.fn.nerValid.isNotEmpty = function(element){
    return (element.val()!="" && element.val() != element.attr("data-default"));
  }

  $.fn.nerValid.isEmail = function(email){
    var regex = /^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i;
    return regex.test(email);
  };

  $.fn.nerValid.isUKPC = function(postcode){
    var regex = /[A-Z]{1,2}[A-Z0-9]{1,2} ?[0-9][A-Z]{2}/i;
    return regex.test(postcode);
  }

})(jQuery);
