jQuery.fn.think_validation = function(vOptions) {
    //validation
    function isValid(fieldToValidate) {
        var postData = $(vOptions.formId).serialize() + "&validate_json_request=true&validate_json_field=" + fieldToValidate; //live data
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            url: vOptions.urlString,
            data: postData,
            dataType: "json",
            contentType: "application/x-www-form-urlencoded",
            error: function(errorData, errorData1) {
                //document.forms[0].submit(); //do a postback here
            },
            success: function(returnedData) {
                //loop JSON
                var i = returnedData.validation.field.length;
                while (i--) {
                    var mainMessage = returnedData.validation.error_message_info;
                    var fieldId = returnedData.validation.field[i].field_id;
                    var inlineMess = returnedData.validation.field[i].message;
                    var success = returnedData.validation.field[i].sucess;
                    if (success) {
                    }
                    if (!success && $("#" + fieldId).val()) {
                        addInlineMessage(fieldId, inlineMess);
                        addMainError(fieldId, mainMessage);
                    }
                    else if(success){
                        clearErrors($("#" + fieldId))
                    }
                }
            }
        });
    };

    //display inline message next to field
    function addInlineMessage(fieldId, inlineMess) {
        //check for existing message
        
        if ($("#" + fieldId).parents(".frmRow:first").hasClass("error")) {
            //replace existing message with new message if its different   
            if ($("#" + fieldId).parents(".frmRow:first").find(".errorMessage label").html() != $(inlineMess).html()) {
                $("#" + fieldId).parents(".frmRow:first").find(".errorMessage").replaceWith($(inlineMess));
            }
        }
        //check if parent has server error class
        else if ($("#" + fieldId).parents(".frmRow:first").hasClass("servererror")) {
            $("#" + fieldId).parents(".frmRow:first").find(".errorMessage").removeClass("js-hide");
            $("#" + fieldId).parents(".frmRow:first").addClass("error");

        }
        //check if grandparent has server error class
        else if ($("#" + fieldId).parent(".frmElement").parents(".frmRow:first").hasClass("servererror")) {
            $("#" + fieldId).parent(".frmElement").parents(".frmRow:first").find(".errorMessage").removeClass("js-hide");
            $("#" + fieldId).parent(".frmElement").parents(".frmRow:first").addClass("error");
        }
        else {
            //no message exists, so add it
            if ($("#" + fieldId).parent().hasClass("frmElement")){
	            $("#" + fieldId).parents(".frmRow:first").addClass("error").append(" " + inlineMess);
            }
            $("#" + fieldId).parent(".frmRow").addClass("error").append(" " + inlineMess);
        }
    };

    function clearErrors(field) {
        //remove error assoc with field id
        if ($(field).parents(".frmRow:first").hasClass("servererror")) {
            $(field).parents(".frmRow:first").removeClass("error").find(".errorMessage").addClass("js-hide");
        }
        //check if grandparent has server error class
        else if ($(field).parent(".frmElement").parents(".frmRow:first").hasClass("servererror")) {
            $(field).parent(".frmElement").parents(".frmRow:first").removeClass("error").find(".errorMessage").addClass("js-hide");
        }
        //check if parent has server error class
        else if ($(field).parents(".frmRow:first").hasClass("error")) {
            $(field).parents(".frmRow:first").removeClass("error").find(".errorMessage").remove();
        }
        //check if grandparent has error class
        else if ($(field).parent(".frmElement").parents(".frmRow:first").hasClass("error")) {
            $(field).parent(".frmElement").parents(".frmRow:first").removeClass("error").find(".errorMessage").remove();
        }
        //check if other errors exist on page, true: update main error message at top of page
        if ($("#iError").length && $(".frmRow").hasClass(".error") == false) {
            $("#iError").remove(); //remove if main message exists and no inline errors exist
        }
        else if ($("#iError").length && $(".frmRow").hasClass(".error") == true) {
            //validate all fields
            isValid();
        }
    };

    function addMainError(fieldId, mainMessage) {
        //check if main message exists
        if ($("#iError").length) {
            //check if main message has changed
            if ($("#iError").html() !== $(mainMessage).html()) {
                $("#iError").replaceWith(mainMessage); //if changed replace
            }
        }
        else //append message
        {
            $("#" + fieldId).parents("div.form").prepend(mainMessage);
        }
        $("#iError").roundedCorners(true);
    };

    //set event on fields
    $(this).blur(function() {
        //check if field is null or empty
        if (!($(this).val())) {
            if ($(this).parent().hasClass("frmElement")) {
                if (!$(this).parent(".frmElement").parent(".frmRow").hasClass("servererror")) {
                    //unless current field is the forename field
                    if (!$(this).parent(".frmElement").prev().hasClass("title")){
	                    //remove associated inline error message and parent class
	                  	clearErrors($(this));
                    }
                    
                }
                else {
                    $(this).parent(".frmElement").parent(".frmRow").addClass("error")
                    $(this).parent(".frmElement").parent(".frmRow").find(".errorMessage").removeClass("js-hide");
                }
            }
            if ($(this).parent().hasClass("frmRow")) {
                if (!$(this).parent(".frmRow").hasClass("servererror")) {
                    //remove associated inline error message and parent class
                    clearErrors($(this));
                }
                else {
                    $(this).parent(".frmRow").addClass("error");
                    $(this).parent(".frmRow").find(".errorMessage").removeClass("js-hide");
                }
            }
        }
        else //if field contains data validate it
        {
            isValid(escape(this.name)); //validate passing in id of field
        }
    });

    /*
    end validation
    */
};
