/**
  * Validity - validate contact forms
  * Version: v.1.1.1
  * Project Page:  http://validity.thatscaptaintoyou.com/
  * Requirements:  jQuery
  * Usage Example: http://validity.thatscaptaintoyou.com/Demos/index.htm
  *
  * Author:  Wyatt Allen
  * 
  * License: MIT and GPL licenses
  *
 **/ 
(function ($) {
    var h = {
        outputMode: "label",
        cssClass: "error",
        scrollTo: false,
        modalErrorsClickable: true,
        defaultFieldName: "This field",
        elementSupport: ":text, :password, textarea, select, :radio, :checkbox",
        argToString: function (a) {
            return a.getDate ? (a.getMonth() + 1) + "/" + a.getDate() + "/" + a.getFullYear() : a
        }
    };
    $.validity = {
        settings: $.extend(h, {}),
        patterns: {
            integer: /^\d+$/,
            date: /^((0?\d)|(1[012]))\/([012]?\d|30|31)\/\d{1,4}$/,
            email: /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i,
            usd: /^\$?(\d{1,3},?(\d{3},?)*\d{3}(\.\d{0,2})?|\d{1,3}(\.\d{0,2})?|\.\d{1,2}?)$/,
            url: /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,
            number: /^[+-]?(\d+(\.\d*)?|\.\d+)([Ee]\d+)?$/,
            zip: /^\d{5}(-\d{4})?$/,
            phone: /^[2-9]\d{2}-\d{3}-\d{4}$/,
            guid: /^(\{?([0-9a-fA-F]){8}-(([0-9a-fA-F]){4}-){3}([0-9a-fA-F]){12}\}?)$/,
            time12: /^[01]?\d:[0-5]\d?\s?[aApP]\.?[mM]\.?$/,
            time24: /^(20|21|22|23|[01]\d|\d)(([:][0-5]\d){1,2})$/,
            nonHtml: /^[^<>]*$/
        },
        messages: {
            require: "#{field} is required.",
            match: "#{field} is in an invalid format.",
            integer: "#{field} must be a positive, whole number.",
            date: "#{field} must be formatted as a date.",
            email: "#{field} must be formatted as an email.",
            usd: "#{field} must be formatted as a US Dollar amount.",
            url: "#{field} must be formatted as a URL.",
            number: "#{field} must be formatted as a number.",
            zip: "#{field} must be formatted as a zipcode ##### or #####-####.",
            phone: "#{field} must be formatted as a phone number ###-###-####.",
            guid: "#{field} must be formatted as a guid like {3F2504E0-4F89-11D3-9A0C-0305E82C3301}.",
            time24: "#{field} must be formatted as a 24 hour time: 23:00.",
            time12: "#{field} must be formatted as a 12 hour time: 12:00 AM/PM",
            lessThan: "#{field} must be less than #{max}.",
            lessThanOrEqualTo: "#{field} must be less than or equal to #{max}.",
            greaterThan: "#{field} must be greater than #{min}.",
            greaterThanOrEqualTo: "#{field} must be greater than or equal to #{min}.",
            range: "#{field} must be between #{min} and #{max}.",
            tooLong: "#{field} cannot be longer than #{max} characters.",
            tooShort: "#{field} cannot be shorter than #{min} characters.",
            nonHtml: "#{field} cannot contain HTML characters.",
            alphabet: "#{field} contains disallowed characters.",
            minCharClass: "#{field} cannot have more than #{min} #{charClass} characters.",
            maxCharClass: "#{field} cannot have less than #{min} #{charClass} characters.",
            equal: "Values don't match.",
            distinct: "A value was repeated.",
            sum: "Values don't add to #{sum}.",
            sumMax: "The sum of the values must be less than #{max}.",
            sumMin: "The sum of the values must be greater than #{min}.",
            radioChecked: "The selected value is not valid.",
            generic: "Invalid."
        },
        charClasses: {
            alphabetical: /\w/g,
            numeric: /\d/g,
            alphanumeric: /[A-Za-z0-9]/g,
            symbol: /[^A-Za-z0-9]/g
        },
        outputs: {},
        setup: function (a) {
            this.settings = $.extend(this.settings, a)
        },
        report: null,
        isValidating: function () {
            return !!this.report
        },
        start: function () {
            if (this.outputs[this.settings.outputMode] && this.outputs[this.settings.outputMode].start) {
                this.outputs[this.settings.outputMode].start()
            }
            this.report = {
                errors: 0,
                valid: true
            }
        },
        end: function () {
            var a = this.report || {
                errors: 0,
                valid: true
            };
            this.report = null;
            if (this.outputs[this.settings.outputMode] && this.outputs[this.settings.outputMode].end) {
                this.outputs[this.settings.outputMode].end(a)
            }
            return a
        },
        clear: function () {
            this.start();
            this.end()
        }
    };
    $.fn.extend({
        validity: function (a) {
            return this.each(function () {
                if (this.tagName.toLowerCase() == "form") {
                    var f = null;
                    if (typeof (a) == "string") {
                        f = function () {
                            $(a).require()
                        }
                    } else if ($.isFunction(a)) {
                        f = a
                    }
                    if (a) {
                        $(this).bind("submit", function () {
                            $.validity.start();
                            f();
                            return $.validity.end().valid
                        })
                    }
                }
            })
        },
        require: function (d) {
            return validate(this, function (a) {
                var b = $(a).val();
                var c = b.length;
                return c
            }, d || $.validity.messages.require)
        },
        match: function (b, c) {
            if (!c) {
                c = $.validity.messages.match;
                if (typeof (b) === "string" && $.validity.messages[b]) {
                    c = $.validity.messages[b]
                }
            }
            if (typeof (b) == "string") {
                b = $.validity.patterns[b]
            }
            return validate(this, $.isFunction(b) ?
            function (a) {
                return !a.value.length || b(a.value)
            } : function (a) {
                if (b.global) {
                    b.lastIndex = 0
                }
                return !a.value.length || b.test(a.value)
            }, c)
        },
        range: function (b, c, e) {
            return validate(this, b.getTime && c.getTime ?
            function (a) {
                var d = new Date(a.value);
                return d >= new Date(b) && d <= new Date(c)
            } : b.substring && c.substring && Big ?
            function (a) {
                var n = new Big(a.value);
                return (n.greaterThanOrEqualTo(new Big(b)) && n.lessThanOrEqualTo(new Big(c)))
            } : function (a) {
                var f = parseFloat(a.value);
                return f >= b && f <= c
            }, e || format($.validity.messages.range, {
                min: $.validity.settings.argToString(b),
                max: $.validity.settings.argToString(c)
            }))
        },
        greaterThan: function (b, c) {
            return validate(this, b.getTime ?
            function (a) {
                return new Date(a.value) > b
            } : b.substring && Big ?
            function (a) {
                return new Big(a.value).greaterThan(new Big(b))
            } : function (a) {
                return parseFloat(a.value) > b
            }, c || format($.validity.messages.greaterThan, {
                min: $.validity.settings.argToString(b)
            }))
        },
        greaterThanOrEqualTo: function (b, c) {
            return validate(this, b.getTime ?
            function (a) {
                return new Date(a.value) >= b
            } : b.substring && Big ?
            function (a) {
                return new Big(a.value).greaterThanOrEqualTo(new Big(b))
            } : function (a) {
                return parseFloat(a.value) >= b
            }, c || format($.validity.messages.greaterThanOrEqualTo, {
                min: $.validity.settings.argToString(b)
            }))
        },
        lessThan: function (b, c) {
            return validate(this, b.getTime ?
            function (a) {
                return new Date(a.value) < b
            } : b.substring && Big ?
            function (a) {
                return new Big(a.value).lessThan(new Big(b))
            } : function (a) {
                return parseFloat(a.value) < b
            }, c || format($.validity.messages.lessThan, {
                max: $.validity.settings.argToString(b)
            }))
        },
        lessThanOrEqualTo: function (b, c) {
            return validate(this, b.getTime ?
            function (a) {
                return new Date(a.value) <= b
            } : b.substring && Big ?
            function (a) {
                return new Big(a.value).lessThanOrEqualTo(new Big(b))
            } : function (a) {
                return parseFloat(a.value) <= b
            }, c || format($.validity.messages.lessThanOrEqualTo, {
                max: $.validity.settings.argToString(b)
            }))
        },
        maxLength: function (b, c) {
            return validate(this, function (a) {
                return a.value.length <= b
            }, c || format($.validity.messages.tooLong, {
                max: b
            }))
        },
        minLength: function (b, c) {
            return validate(this, function (a) {
                return a.value.length >= b
            }, c || format($.validity.messages.tooShort, {
                min: b
            }))
        },
        alphabet: function (c, d) {
            var e = [];
            return validate(this, function (a) {
                for (var b = 0; b < a.value.length; ++b) {
                    if (c.indexOf(a.value.charAt(b)) == -1) {
                        e.push(a.value.charAt(b));
                        return false
                    }
                }
                return true
            }, d || format($.validity.messages.alphabet, {
                chars: e.join(", ")
            }))
        },
        minCharClass: function (b, c, d) {
            if (typeof (b) == "string") {
                b = b.toLowerCase();
                if ($.validity.charClasses[b]) {
                    b = $.validity.charClasses[b]
                }
            }
            return validate(this, function (a) {
                return (a.value.match(b) || []).length >= c
            }, d || format($.validity.messages.minCharClass, {
                min: c,
                charClass: b
            }))
        },
        maxCharClass: function (b, c, d) {
            if (typeof (b) == "string") {
                b = b.toLowerCase();
                if ($.validity.charClasses[b]) {
                    b = $.validity.charClasses[b]
                }
            }
            return validate(this, function (a) {
                return (a.value.match(b) || []).length <= c
            }, d || format($.validity.messages.maxCharClass, {
                max: c,
                charClass: b
            }))
        },
        password: function (a, b) {
            a = $.extend({
                alphabet: null,
                minLength: 0,
                maxLength: 0,
                minSymbol: 0,
                minAlphabetical: 0,
                minNumeric: 0,
                minAlphaNumeric: 0
            }, a);
            if (a.alphabet) {
                this.alphabet(a.alphabet)
            }
            if (a.minLength) {
                this.minLength(a.minLength)
            }
            if (a.maxLength) {
                this.maxLength(a.maxLength)
            }
            if (a.minSymbol) {
                this.minCharClass("symbol", a.minSymbol)
            }
            if (a.minAlphabetical) {
                this.minCharClass("alphabetical", a.minAlphabetical)
            }
            if (a.minNumeric) {
                this.minCharClass("numeric", a.minNumeric)
            }
            if (a.minAlphanumeric) {
                this.minCharClass("alphanumeric", a.minAlphanumeric)
            }
            return this
        },
        nonHtml: function (b) {
            return validate(this, function (a) {
                return $.validity.patterns.nonHtml.test(a.value)
            }, b || $.validity.messages.nonHtml)
        },
        equal: function (b, c) {
            var d = (this.reduction || this).filter($.validity.settings.elementSupport),
                transform = function (a) {
                    return a
                },
                msg = $.validity.messages.equal;
            if (d.length) {
                if ($.isFunction(b)) {
                    transform = b;
                    if (typeof (c) == "string") {
                        msg = c
                    }
                } else if (typeof (b) == "string") {
                    msg = b
                }
                var e = $.map(d, function (a) {
                    return transform(a.value)
                }),
                    first = e[0],
                    valid = true;
                for (var i in e) {
                    if (e[i] != first) {
                        valid = false
                    }
                }
                if (!valid) {
                    raiseAggregateError(d, msg);
                    this.reduction = $([])
                }
            }
            return this
        },
        distinct: function (b, c) {
            var d = (this.reduction || this).filter($.validity.settings.elementSupport),
                transform = function (a) {
                    return a
                },
                msg = $.validity.messages.distinct,
                subMap = [],
                valid = true;
            if (d.length) {
                if ($.isFunction(b)) {
                    transform = b;
                    if (typeof (c) == "string") {
                        msg = c
                    }
                } else if (typeof (b) == "string") {
                    msg = b
                }
                var e = $.map(d, function (a) {
                    return transform(a.value)
                });
                for (var f = 0; f < e.length; ++f) {
                    if (e[f].length) {
                        for (var g = 0; g < subMap.length; ++g) {
                            if (subMap[g] == e[f]) {
                                valid = false
                            }
                        }
                        subMap.push(e[f])
                    }
                }
                if (!valid) {
                    raiseAggregateError(d, msg);
                    this.reduction = $([])
                }
            }
            return this
        },
        sum: function (a, b) {
            var c = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (c.length && a != numericSum(c)) {
                raiseAggregateError(c, b || format($.validity.messages.sum, {
                    sum: a
                }));
                this.reduction = $([])
            }
            return this
        },
        sumMax: function (a, b) {
            var c = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (c.length && a < numericSum(c)) {
                raiseAggregateError(c, b || format($.validity.messages.sumMax, {
                    max: a
                }));
                this.reduction = $([])
            }
            return this
        },
        sumMin: function (a, b) {
            var c = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (c.length && a < numericSum(c)) {
                raiseAggregateError(c, b || format($.validity.messages.sumMin, {
                    min: a
                }));
                this.reduction = $([])
            }
            return this
        },
        radioChecked: function (a, b) {
            var c = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (c.is(":radio") && c.find(":checked").val() != a) {
                raiseAggregateError(c, b || $.validity.messages.radioChecked)
            }
        },
        radioNotChecked: function (a, b) {
            var c = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (c.is(":radio") && c.filter(":checked").val() == a) {
                raiseAggregateError(c, b || $.validity.messages.radioChecked)
            }
        },
        checkboxChecked: function (a) {
            var b = (this.reduction || this).filter($.validity.settings.elementSupport);
            if (b.is(":checkbox") && !b.is(":checked")) {
                raiseAggregateError(b, a || $.validity.messages.radioChecked)
            }
        },
        assert: function (a, b) {
            var c = this.reduction || this;
            if (c.length) {
                if ($.isFunction(a)) {
                    return validate(this, a, b || $.validity.messages.generic)
                } else if (!a) {
                    raiseAggregateError(c, b || $.validity.messages.generic);
                    this.reduction = $([])
                }
            }
            return this
        }
    });

    function validate(a, b, c) {
        var d = (a.reduction || a).filter($.validity.settings.elementSupport),
            elements = [];
        d.each(function () {
            if (b(this)) {
                elements.push(this)
            } else {
                raiseError(this, format(c, {
                    field: infer(this)
                }))
            }
        });
        a.reduction = $(elements);
        return a
    }
    function addToReport() {
        if ($.validity.isValidating()) {
            $.validity.report.errors++;
            $.validity.report.valid = false
        }
    }
    function raiseError(a, b) {
        addToReport();
        if ($.validity.outputs[$.validity.settings.outputMode] && $.validity.outputs[$.validity.settings.outputMode].raise) {
            $.validity.outputs[$.validity.settings.outputMode].raise($(a), b)
        }
    }
    function raiseAggregateError(a, b) {
        addToReport();
        if ($.validity.outputs[$.validity.settings.outputMode] && $.validity.outputs[$.validity.settings.outputMode].raiseAggregate) {
            $.validity.outputs[$.validity.settings.outputMode].raiseAggregate(a, b)
        }
    }
    function numericSum(a) {
        var b = 0;
        a.each(function () {
            var n = parseFloat(this.value);
            b += isNaN(n) ? 0 : n
        });
        return b
    }
    function format(a, b) {
        for (var p in b) {
            a = a.replace("#{" + p + "}", b[p])
        }
        return capitalize(a)
    }
    function infer(a) {
        var b = $(a),
            ret = $.validity.settings.defaultFieldName;
        if (b.attr("title").length) {
            ret = b.attr("title")
        } else if (/^([A-Z0-9][a-z]*)+$/.test(a.id)) {
            ret = a.id.replace(/([A-Z0-9])[a-z]*/g, " $&")
        } else if (/^[a-z0-9_]*$/.test(a.id)) {
            var c = a.id.split("_");
            for (var i = 0; i < c.length; ++i) {
                c[i] = capitalize(c[i])
            }
            ret = c.join(" ")
        }
        return ret
    }
    function capitalize(a) {
        return a.substring ? a.substring(0, 1).toUpperCase() + a.substring(1, a.length) : a
    }
})(jQuery);
(function ($) {
    function getIdentifier(a) {
        return a.attr('id').length ? a.attr('id') : a.attr('name')
    }
    $.validity.outputs.label = {
        start: function () {
            $("label." + $.validity.settings.cssClass).remove()
        },
        end: function (a) {
            if (!a.valid && $.validity.settings.scrollTo) {
                location.hash = $("label." + $.validity.settings.cssClass + ":eq(0)").attr('for')
            }
        },
        raise: function (a, b) {
            var c = "label." + $.validity.settings.cssClass + "[for='" + getIdentifier(a) + "']";
            if ($(c).length) {
                $(c).text(b)
            } else {
                $("<label/>").attr("for", getIdentifier(a)).addClass($.validity.settings.cssClass).text(b).click(function () {
                    if (a.length) {
                        a[0].select()
                    }
                }).insertAfter(a)
            }
        },
        raiseAggregate: function (a, b) {
            if (a.length) {
                this.raise($(a.get(a.length - 1)), b)
            }
        }
    }
})(jQuery);
(function ($) {
    var d = "validity-modal-msg",
        container = "body";
    $.validity.outputs.modal = {
        start: function () {
            $("." + d).remove()
        },
        end: function (a) {
            if (!a.valid && $.validity.settings.scrollTo) {
                location.hash = $("." + d + ":eq(0)").attr('id')
            }
        },
        raise: function (a, b) {
            if (a.length) {
                var c = a.offset(),
                    obj = a.get(0),
                    errorStyle = {
                        left: parseInt(c.left + a.width() + 4, 10) + "px",
                        top: parseInt(c.top - 10, 10) + "px"
                    };
                $("<div/>").addClass(d).css(errorStyle).text(b).click($.validity.settings.modalErrorsClickable ?
                function () {
                    $(this).remove()
                } : null).appendTo(container)
            }
        },
        raiseAggregate: function (a, b) {
            if (a.length) {
                this.raise($(a.get(a.length - 1)), b)
            }
        }
    }
})(jQuery);
(function ($) {
    var c = ".validity-summary-container",
        erroneous = "validity-erroneous",
        errors = "." + erroneous,
        wrapper = "<li/>",
        buffer = [];
    $.validity.outputs.summary = {
        start: function () {
            $(errors).removeClass(erroneous);
            buffer = []
        },
        end: function (a) {
            $(c).hide().find("ul").html('');
            if (buffer.length) {
                for (var i = 0; i < buffer.length; ++i) {
                    $(wrapper).text(buffer[i]).appendTo(c + " ul")
                }
                $(c).show();
                if ($.validity.settings.scrollTo) {
                    location.hash = $(errors + ":eq(0)").attr("id")
                }
            }
        },
        raise: function (a, b) {
            buffer.push(b);
            a.addClass(erroneous)
        },
        raiseAggregate: function (a, b) {
            this.raise(a, b)
        },
        container: function () {
            document.write("<div class=\"validity-summary-container\">" + "The form didn't submit for the following reason(s):" + "<ul></ul>" + "</div>")
        }
    }
})(jQuery);
