﻿(function(jQuery) {

    jQuery.fn.simpleValidationEmpty = function(options) {
        if ($(".simpleValInlineError").length > 0)
            $(".simpleValInlineError").remove();
    };

    jQuery.fn.simpleValidation = function(options) {
        var error = 0;
        var validationResults = $(document.createElement("ul"));
        var validationContainer = $(document.createElement("div")).addClass("validationResults").append(validationResults);
        var defaults = {
            requiredMessage: "is required",
            notMatchingMessage: "doesn't match",
            valueMustChangeMessage: "must be changed",
            container: "",
            invalidMessage: "is invalid",
            containerTitle: "Please fix the following errors:",
            validationArea: "",
            showDetails: true,
            inlineErrorSymbol: "*",
            inlineErrorClass: "inlineErrorSymbol",
            inlineErrorSymbolRight: true,
            autoFocus: true,
            additionalErrors: {}
        }

        var options = $.extend(defaults, options);
        var inlineErrorClassFixed = "." + options.inlineErrorClass;

        if ($(inlineErrorClassFixed, this).length > 0) { $(inlineErrorClassFixed, this).remove(); }
        
        var validationContainerArea;

        if (options.validationArea == "" || options.validationArea == null || options.validationArea == undefined) {
            validationContainerArea = this;
        } else {
            validationContainerArea = options.validationArea;
        }
    
        required(validationContainerArea);
        matching(validationContainerArea);
        validate(validationContainerArea);
        dropDownRequired(validationContainerArea);
        numberBetween(validationContainerArea);
        dateGreaterThanOrEqualTo(validationContainerArea);
        valueMustChange(validationContainerArea);

        if (options.container != "")
            $("#" + options.container).empty();
            
        if (options.additionalErrors.length > 0) {
            $.each(options.additionalErrors, function(i, val) {
                error++;
                var name = $(val.element).attr("name");
                var id = $(val.element).attr("id");
                if (val.name != undefined && val.name.length > 0)
                    name = val.name;
                    
                showError($(val.element), name, id, val.message, null);
            });
        }

        if (error == 0)
            return true;
        else {
            if (options.container != "")
                $("#" + options.container).append('<div id="simpleValidationContainer" class="ui-widget simpleValInlineError"><a name="simpleValidationError"></a><div class="ui-state-error ui-corner-all" style="padding: 0.7em;"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: 0.3em;"></span>' + options.containerTitle + '<br /><br />' + $(validationContainer).html() + '</div></div>');

            if (options.autoFocus)
                window.location = "#simpleValidationError";

            return false;
        }

        function required(container) {
            $('.required-field', container).each(function() {
                var inlineContainer = this;
                var id = $(this).attr("id");
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var input = $.trim($(this).attr("value"));
                var isWatermarkOn = $(this).attr("class") == "watermarkOn";

                if ($(this).attr("inlineContainer") != undefined && $(this).attr("inlineContainer").length > 0)
                    inlineContainer = $(this).attr("inlineContainer");

                clearWidget();

                if ($.trim(input) == "" || isWatermarkOn) {
                    showError(inlineContainer, name, id, options.requiredMessage, null);
                    error++;

                    validateOnKeypress(this, id);
                    
                    if ($(this).attr("isSexyCombo"))
                        validateSexyCombo(this, id);
                }
            });
        }

        function valueMustChange(container) {
            $(".value-must-change", container).each(function() {
                var id = $(this).attr("id");
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var currentValue = $(this).attr("value");
                var originalValue = $(this).data("originalValue");

                if (originalValue == null || originalValue == undefined || originalValue == "" || currentValue == "")
                    return;

                if (originalValue == currentValue) {
                    showError(this, name, id, options.valueMustChangeMessage, null);
                    error++;

                    validateOnKeypress(this, id);
                }
            });
        }

        function dropDownRequired(container) {

            $('.dropdown-required-field', container).each(function() {
                var select = $("select", this);
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var id = $(this).attr("id");

                if ($(select).children(":first-child").attr("selected") == true) {
                    showError(select, name, id, options.requiredMessage, null);
                    error++;

                    $(select).change(function() { hideErrorAndClearContainer(id); });
                }
            });
        }
        
        function numberBetween(container) {
            $('.number-range-field', container).each(function() {
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var id = $(this).attr("id");
                var min = $(this).data("min") == undefined ? $(this).attr("min") : $(this).data("min");
                var max = $(this).data("max") == undefined ? $(this).attr("max") : $(this).data("max");
                var value = $(this).val();
                
                var intValue = 0;
                
                if (value == null || value == "") {
                    showError(this, name, id, options.requiredMessage, null);
                    error++;
                    validateOnKeypress(this, id);
                    return;
                }

                intValue = parseInt(value);
                
                if (isNaN(intValue)) {
                    showError(this, name, id, "must be a number", null);
                    error++;
                    validateOnKeypress(this, id);
                    return;
                }
                
                if (intValue < min || intValue > max) {
                    showError(this, name, id, "must be between " + min + " and " + max, null);
                    error++;
                    validateOnKeypress(this, id);
                    return;
                }
            });
        }

        function validate(container) {

            $("[validate]", container).each(function() {
                var value = $.trim($(this).val());
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var id = $(this).attr("id");
                var validateType = $(this).attr("validate");

                if (value == "")
                    return true;

                if (validateType == "email") {
                    // Refer to: http://www.regular-expressions.info/email.html
                    var emailRegex = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|coop|asia|cat|tel|travel)\b/i;
                
                    if (emailRegex.test(value)) {
                    } else {
                        showError(this, name, id, options.invalidMessage, null);
                        error++;
                        
                        $(this).unbind("keypress").bind("keypress", function(event) {
                            if (!emailRegex.test($(this).val()))
                                return;
                            $(this).unbind("keypress");
                            hideErrorAndClearContainer(id);
                        });
                    }
                }
            });
        }

        function dateGreaterThanOrEqualTo(container) {

            $("[greaterThanOrEqualTo]", container).each(function() {
                var value = $.trim($(this).val());
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var id = $(this).attr("id");
                var greaterThanId = $(this).attr("greaterThanOrEqualTo");
                var name2 = $(greaterThanId).attr("name");
                var id2 = $(greaterThanId).attr("id");
                var value2 = $(greaterThanId).val();

                if (value == "" || value2 == "")
                    return true;

                var date1 = new Date(value);
                var date2 = new Date(value2);

                if (date1 < date2) {
                    showError(this, name2, id2, "", "<li id='svError" + id + "'><strong>" + name + "</strong> must be on or after <strong>" + name2 + "</strong></li>");
                    error++;
                }
            });
        }

        function matching(container) {

            $(".matching-field", container).each(function() {
                var value1 = $.trim($(this).val());
                var name = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");
                var id = $(this).attr("id");

                var compareWith = $(this).attr("compareWith");
                if (compareWith == null || compareWith == undefined || compareWith == "") {
                    return true;
                }
                var field2 = $("#" + compareWith);
                if (field2 == null || field2 == undefined || field2 == "") {
                    return true;
                }

                if ($(this).parent().css("display") == "none") {
                    return true;
                }

                var value2 = $.trim($(field2).val());
                var name2 = $(this).data("name") == undefined ? $(this).attr("name") : $(this).data("name");

                if ($.trim(value1) == "" || $.trim(value2) == "") {
                    return true; // Don't check if either value is empty
                }

                $('.ui-widget', this).remove();

                if (value1 != value2) {

                    var field2Parent = $(field2).parent();
                    $('.ui-widget', field2Parent).remove();

                    if (name == "" || name == null || name2 == undefined || name2 == "" || name2 == null || name2 == undefined) {
                        alert("Error: Set name attribute of element with ID=" + $(':input', this).attr("id") + "</li>\n" +
                            "Error: Set name attribute of element with ID=" + $(field2).attr("id") + "</li>");
                    } else {
                        if (options.showDetails)
                            $(validationResults).append("<li id='svError" + id + "'><strong>" + name + "</strong> " + options.notMatchingMessage + " <strong>" + name2 + "</strong></li>");

                        var inlineError = $(document.createElement("span")).addClass("simpleValInlineError").addClass(options.inlineErrorClass).append(options.inlineErrorSymbol);

                        if ($(this).next(inlineErrorClassFixed).length == 0)
                            $(this).after(inlineError);

                        if ($(field2).next(inlineErrorClassFixed).length == 0)
                            $(field2).after(inlineError);
                    }
                    
                    error++;
                }
            });
        }

        function showError(inlineContainer, elementName, elementId, message, detailsOverride) {
            if (elementName == "" || elementName == null || elementName == undefined)
                alert("Error: Set name attribute of element with ID=" + elementId); // internal error
            else {
                if (options.showDetails) {
                    if (detailsOverride == null)
                        $(validationResults).append("<li id='svError" + elementId + "'><strong>" + elementName + "</strong> " + message + "</li>");
                    else
                        $(validationResults).append(detailsOverride);
                }

                var inlineError = $(document.createElement("span")).attr("id", "svInline" + elementId).addClass("simpleValInlineError").addClass(options.inlineErrorClass).append(options.inlineErrorSymbol);
                if ($(inlineContainer).next(inlineErrorClassFixed).length == 0) {
                    if (options.inlineErrorSymbolRight)
                        $(inlineContainer).after(inlineError);
                    else
                        $(inlineContainer).before(inlineError);
                }
            }
        }
        
        function validateOnKeypress(element, id) {
            $(element).unbind("keypress").bind("keypress", function(event) {
                if ($(this).length == 0)
                    return;
                $(this).unbind("keypress");
                hideErrorAndClearContainer(id);
            });
        }
        
        function validateSexyCombo(element, id) {
        
            $(element).parent().find("select").unbind("change").bind("change", function() {
                if ($(this).val().length == 0)
                    return;
                $(this).unbind("change");
                hideErrorAndClearContainer(id);                
            });
        }

        function hideErrorAndClearContainer(id) {
            $("#svError" + id).remove();
            $("#svInline" + id).remove();

            if ($(validationContainer + "li[id^='svError']").length == 0)
                $("#" + options.container).empty();
        }

        function clearWidget() {
            if ($('.ui-widget', this).length > 0)
                $('.ui-widget', this).remove();
        }
    };
})(jQuery);