    
(function($) {

    $.fn.validation = function(options) {
        // define defaults and override with options, if available
        // by extending the default settings, we don't modify the argument

        // do the rest of the plugin, using url and settings
        return this.each(function() {

            var settings = jQuery.extend({
                vg: "",
                vt: [],
                error: []
            }, options);

            if ($(this).is("input") || $(this).is("select") || $(this).is("textarea") || $(this).is("a")) {

                $(this).attr("vg", settings.vg);
                $(this).attr("vt", settings.vt);

                $(this).data("settings", settings);
                $(this).bind("isValid", IsValid);

                if ($(this).is(":submit") || $(this).is(":button") || $(this).is("a")) {
                    $(this).click(ValidationClick);                    
                    return;
                }

                $(this).focus(GetFocus);
                $(this).blur(RemoveFocus);
            };
        });

    };
})(jQuery);


function ValidationClick() {
    var _selector = "input[type='text'][vg='" + $(this).attr('vg') + "'],";
    _selector += "input[type='password'][vg='" + $(this).attr('vg') + "'],";
    _selector += "select[vg='" + $(this).attr('vg') + "'],";
    _selector += "textarea[vg='" + $(this).attr('vg') + "']";

    $(_selector).trigger("isValid");
    $(_selector).removeClass("error");
    $(_selector).removeClass("focus");

    var $invalid = $(_selector).filter(function(index) {
        // return all those that didn't validate        
        return !eval($(this).attr("valid"));
    });

    // so if all elements passed $inputs should be empty, and the form is valid            
    if ($invalid.length == 0 && ValidateCheckboxList()) {
        eval($(this).attr("OnValidated"));
        HideErrors();
    }
    else {
        // show the error messages
        if (DisplayErrors != null)
            DisplayErrors($invalid);

        return false;
    }
}

function IsValid(e) {

    var $element = $(this);

    var vts = $element.data("settings").vt;
    $element.attr("valid", "true"); // assume that its valid

    // only change the value of result if the validation fails
    for (ii = 0; ii < vts.length; ii++) {
        var isValid = true;
        // this will stop the code checking something that is already invalid
        if ($element.attr("valid") != "false") {

            switch (vts[ii]) {
                case "xreq":
                    if (!ValidateXReq($element))
                        isValid = false;                    
                    break;
                case "emailaddress":
                    if (!ValidateEmailAddress($element))
                        isValid = false;
                    break;
                case "username":
                    if (!ValidateUsername($element))
                        isValid = false;
                    break;
                case "req":
                    if (!ValidateReq($element))
                        isValid = false;
                    break;
                case "confirm":
                    if ($("#" + $element.attr("ac")).val() != $element.val())
                        isValid = false;                        
                    break;
            }

            if (!isValid) {
                $element.attr("valid", "false");
                $element.attr("error", $element.data("settings").error[ii]);                
            }
        }
    }
}

function ValidateReq($obj) {
    return ($obj.val() != "" &&
                $obj.val() != null &&
                $obj.val() != $obj.attr("iv")); // the initial value
}

function ValidateUsername($obj) {

    var filter = /^[A-Za-z0-9_.-]{5,}$/;
    if ($obj.val() != "")
        return filter.test($obj.val());
    else
        return true;
}

function ValidateEmailAddress($obj) {

    var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if ($obj.val() != "")
        return filter.test($obj.val());
    else
        return true;
}

function ValidateXReq($obj) {

    // we need to get all inputs with this validation group that have type xreq
    var $xreqs = $("input[vg='" + $obj.attr('vg') + "'][vt*='xreq'],select[vg='" + $obj.attr('vg') + "'][vt*='xreq']");

    // now filter this list to see which ones have a value
    var $result = $xreqs.filter(function(index) {        
        return ($(this).val() != "" &&
                $(this).val() != null &&
                $(this).val() != $(this).attr("iv")); // the initial value
    });
    // alert($result.length);
    // return if this list is great than 0 - return true if at least 1 element had a value    
    return $result.length > 0;
}


function ValidateCheckboxList() {
    // validate checkbox

    if ($('table .checkboxlist').length > 0) {
        if ($('.checkboxlist input[@type=checkbox]:checked').size() == 0) {
            return false;
        }
    }
    return true;
}


//
// the code below will then call this function if it is available with all the inputs that are not valid.
//

function HideErrors() {
    $(".validation-summary").css("display", "none");
    $(".validation-summary").empty();
    $(".error-required").remove();
}


var DisplayErrors = null;

function ShowMessage(message, bubbleId, obj) {

    $("#" + bubbleId).css("display", "none");
    $("#" + bubbleId).css("left", $(obj).position().left + $(obj).width());
    $("#" + bubbleId).css("top", $(obj).position().top + ($(obj).height() / 3));

    $("#" + bubbleId).empty();
    $("#" + bubbleId).append(GetMessage(message));
    $("#" + bubbleId).fadeIn("slow");
}

function GetFocus() {
    //    $("input.field").removeClass("focus");
    //    $("select.dropdown").removeClass("focus");

    $(".focus").removeClass("focus");

    if ($(this).is("select")) {
        $(this).parent().parent().removeClass("error");
        $(this).parent().parent().addClass("focus");
        return;
    }

    $(this).removeClass("error");
    $(this).addClass("focus");
}

function RemoveFocus() {

    if ($(this).is("select")) {
        $(this).parent().parent().removeClass("error");
        $(this).parent().parent().removeClass("focus");
        return;
    }

    $(this).removeClass("error");
    $(this).removeClass("focus");
}
