var LiveValidation = function (b, a) {
    this.initialize(b, a)
};
LiveValidation.VERSION = "1.3 standalone";
LiveValidation.TEXTAREA = 1;
LiveValidation.TEXT = 2;
LiveValidation.PASSWORD = 3;
LiveValidation.CHECKBOX = 4;
LiveValidation.SELECT = 5;
LiveValidation.FILE = 6;
LiveValidation.massValidate = function (c) {
    var d = true;
    for (var b = 0, a = c.length; b < a; ++b) {
        var e = c[b].validate();
        if (d) {
            d = e
        }
    }
    return d
};
LiveValidation.prototype = {
    validClass: "LV_valid",
    invalidClass: "LV_invalid",
    messageClass: "LV_validation_message",
    validFieldClass: "LV_valid_field",
    invalidFieldClass: "LV_invalid_field",
    initialize: function (d, c) {
        var a = this;
        if (!d) {
            throw new Error("LiveValidation::initialize - No element reference or element id has been provided!")
        }
        this.element = d.nodeName ? d : document.getElementById(d);
        if (!this.element) {
            throw new Error("LiveValidation::initialize - No element with reference or id of '" + d + "' exists!")
        }
        this.validations = [];
        this.elementType = this.getElementType();
        this.form = this.element.form;
        var b = c || {};
        this.validMessage = b.validMessage || "Thankyou!";
        var e = b.insertAfterWhatNode || this.element;
        this.insertAfterWhatNode = e.nodeType ? e : document.getElementById(e);
        this.onValid = b.onValid ||
        function () {
            this.insertMessage(this.createMessageSpan());
            this.addFieldClass()
        };
        this.onInvalid = b.onInvalid ||
        function () {
            this.insertMessage(this.createMessageSpan());
            this.addFieldClass()
        };
        this.onlyOnBlur = b.onlyOnBlur || false;
        this.wait = b.wait || 0;
        this.onlyOnSubmit = b.onlyOnSubmit || false;
        if (this.form) {
            this.formObj = LiveValidationForm.getInstance(this.form);
            this.formObj.addField(this)
        }
        this.oldOnFocus = this.element.onfocus ||
        function () {};
        this.oldOnBlur = this.element.onblur ||
        function () {};
        this.oldOnClick = this.element.onclick ||
        function () {};
        this.oldOnChange = this.element.onchange ||
        function () {};
        this.oldOnKeyup = this.element.onkeyup ||
        function () {};
        this.element.onfocus = function (f) {
            a.doOnFocus(f);
            return a.oldOnFocus.call(this, f)
        };
        if (!this.onlyOnSubmit) {
            switch (this.elementType) {
            case LiveValidation.CHECKBOX:
                this.element.onclick = function (f) {
                    a.validate();
                    return a.oldOnClick.call(this, f)
                };
            case LiveValidation.SELECT:
            case LiveValidation.FILE:
                this.element.onchange = function (f) {
                    a.validate();
                    return a.oldOnChange.call(this, f)
                };
                break;
            default:
                if (!this.onlyOnBlur) {
                    this.element.onkeyup = function (f) {
                        a.deferValidation();
                        return a.oldOnKeyup.call(this, f)
                    }
                }
                this.element.onblur = function (f) {
                    a.doOnBlur(f);
                    return a.oldOnBlur.call(this, f)
                }
            }
        }
    },
    destroy: function () {
        if (this.formObj) {
            this.formObj.removeField(this);
            this.formObj.destroy()
        }
        this.element.onfocus = this.oldOnFocus;
        if (!this.onlyOnSubmit) {
            switch (this.elementType) {
            case LiveValidation.CHECKBOX:
                this.element.onclick = this.oldOnClick;
            case LiveValidation.SELECT:
            case LiveValidation.FILE:
                this.element.onchange = this.oldOnChange;
                break;
            default:
                if (!this.onlyOnBlur) {
                    this.element.onkeyup = this.oldOnKeyup
                }
                this.element.onblur = this.oldOnBlur
            }
        }
        this.validations = [];
        this.removeMessageAndFieldClass()
    },
    add: function (a, b) {
        this.validations.push({
            type: a,
            params: b || {}
        });
        return this
    },
    remove: function (b, d) {
        var e = false;
        for (var c = 0, a = this.validations.length; c < a; c++) {
            if (this.validations[c].type == b) {
                if (this.validations[c].params == d) {
                    e = true;
                    break
                }
            }
        }
        if (e) {
            this.validations.splice(c, 1)
        }
        return this
    },
    deferValidation: function (b) {
        if (this.wait >= 300) {
            this.removeMessageAndFieldClass()
        }
        var a = this;
        if (this.timeout) {
            clearTimeout(a.timeout)
        }
        this.timeout = setTimeout(function () {
            a.validate()
        }, a.wait)
    },
    doOnBlur: function (a) {
        this.focused = false;
        this.validate(a)
    },
    doOnFocus: function (a) {
        this.focused = true;
        this.removeMessageAndFieldClass()
    },
    getElementType: function () {
        switch (true) {
        case (this.element.nodeName.toUpperCase() == "TEXTAREA"):
            return LiveValidation.TEXTAREA;
        case (this.element.nodeName.toUpperCase() == "INPUT" && this.element.type.toUpperCase() == "TEXT"):
            return LiveValidation.TEXT;
        case (this.element.nodeName.toUpperCase() == "INPUT" && this.element.type.toUpperCase() == "PASSWORD"):
            return LiveValidation.PASSWORD;
        case (this.element.nodeName.toUpperCase() == "INPUT" && this.element.type.toUpperCase() == "CHECKBOX"):
            return LiveValidation.CHECKBOX;
        case (this.element.nodeName.toUpperCase() == "INPUT" && this.element.type.toUpperCase() == "FILE"):
            return LiveValidation.FILE;
        case (this.element.nodeName.toUpperCase() == "SELECT"):
            return LiveValidation.SELECT;
        case (this.element.nodeName.toUpperCase() == "INPUT"):
            throw new Error("LiveValidation::getElementType - Cannot use LiveValidation on an " + this.element.type + " input!");
        default:
            throw new Error("LiveValidation::getElementType - Element must be an input, select, or textarea!")
        }
    },
    doValidations: function () {
        this.validationFailed = false;
        for (var c = 0, a = this.validations.length; c < a; ++c) {
            var b = this.validations[c];
            switch (b.type) {
            case Validate.Presence:
            case Validate.Confirmation:
            case Validate.Acceptance:
                this.displayMessageWhenEmpty = true;
                this.validationFailed = !this.validateElement(b.type, b.params);
                break;
            default:
                this.validationFailed = !this.validateElement(b.type, b.params);
                break
            }
            if (this.validationFailed) {
                return false
            }
        }
        this.message = this.validMessage;
        return true
    },
    validateElement: function (a, c) {
        var d = (this.elementType == LiveValidation.SELECT) ? this.element.options[this.element.selectedIndex].value : this.element.value;
        if (a == Validate.Acceptance) {
            if (this.elementType != LiveValidation.CHECKBOX) {
                throw new Error("LiveValidation::validateElement - Element to validate acceptance must be a checkbox!")
            }
            d = this.element.checked
        }
        var e = true;
        try {
            a(d, c)
        } catch (b) {
            if (b instanceof Validate.Error) {
                if (d !== "" || (d === "" && this.displayMessageWhenEmpty)) {
                    this.validationFailed = true;
                    this.message = b.message;
                    e = false
                }
            } else {
                throw b
            }
        } finally {
            return e
        }
    },
    validate: function () {
        if (!this.element.disabled) {
            var a = this.doValidations();
            if (a) {
                this.onValid();
                return true
            } else {
                this.onInvalid();
                return false
            }
        } else {
            return true
        }
    },
    enable: function () {
        this.element.disabled = false;
        return this
    },
    disable: function () {
        this.element.disabled = true;
        this.removeMessageAndFieldClass();
        return this
    },
    createMessageSpan: function () {
        var a = document.createElement("span");
        var b = document.createTextNode(this.message);
        a.appendChild(b);
        return a
    },
    insertMessage: function (b) {
        this.removeMessage();
        if ((this.displayMessageWhenEmpty && (this.elementType == LiveValidation.CHECKBOX || this.element.value == "")) || this.element.value != "") {
            var a = this.validationFailed ? this.invalidClass : this.validClass;
            b.className += " " + this.messageClass + " " + a;
            if (this.insertAfterWhatNode.nextSibling) {
                this.insertAfterWhatNode.parentNode.insertBefore(b, this.insertAfterWhatNode.nextSibling)
            } else {
                this.insertAfterWhatNode.parentNode.appendChild(b)
            }
        }
    },
    addFieldClass: function () {
        this.removeFieldClass();
        if (!this.validationFailed) {
            if (this.displayMessageWhenEmpty || this.element.value != "") {
                if (this.element.className.indexOf(this.validFieldClass) == -1) {
                    this.element.className += " " + this.validFieldClass
                }
            }
        } else {
            if (this.element.className.indexOf(this.invalidFieldClass) == -1) {
                this.element.className += " " + this.invalidFieldClass
            }
        }
    },
    removeMessage: function () {
        var a;
        var b = this.insertAfterWhatNode;
        while (b.nextSibling) {
            if (b.nextSibling.nodeType === 1) {
                a = b.nextSibling;
                break
            }
            b = b.nextSibling
        }
        if (a && a.className.indexOf(this.messageClass) != -1) {
            this.insertAfterWhatNode.parentNode.removeChild(a)
        }
    },
    removeFieldClass: function () {
        if (this.element.className.indexOf(this.invalidFieldClass) != -1) {
            this.element.className = this.element.className.split(this.invalidFieldClass).join("")
        }
        if (this.element.className.indexOf(this.validFieldClass) != -1) {
            this.element.className = this.element.className.split(this.validFieldClass).join(" ")
        }
    },
    removeMessageAndFieldClass: function () {
        this.removeMessage();
        this.removeFieldClass()
    }
};
var LiveValidationForm = function (a) {
    this.initialize(a)
};
LiveValidationForm.instances = {};
LiveValidationForm.getInstance = function (a) {
    var b = Math.random() * Math.random();
    if (!a.id) {
        a.id = "formId_" + b.toString().replace(/\./, "") + new Date().valueOf()
    }
    if (!LiveValidationForm.instances[a.id]) {
        LiveValidationForm.instances[a.id] = new LiveValidationForm(a)
    }
    return LiveValidationForm.instances[a.id]
};
LiveValidationForm.prototype = {
    initialize: function (b) {
        this.name = b.id;
        this.element = b;
        this.fields = [];
        this.oldOnSubmit = this.element.onsubmit ||
        function () {};
        var a = this;
        this.element.onsubmit = function (c) {
            return (LiveValidation.massValidate(a.fields)) ? a.oldOnSubmit.call(this, c || window.event) !== false : false
        }
    },
    addField: function (a) {
        this.fields.push(a)
    },
    removeField: function (c) {
        var d = [];
        for (var b = 0, a = this.fields.length; b < a; b++) {
            if (this.fields[b] !== c) {
                d.push(this.fields[b])
            }
        }
        this.fields = d
    },
    destroy: function (a) {
        if (this.fields.length != 0 && !a) {
            return false
        }
        this.element.onsubmit = this.oldOnSubmit;
        LiveValidationForm.instances[this.name] = null;
        return true
    }
};
var Validate = {
    Presence: function (b, c) {
        var c = c || {};
        var a = c.failureMessage || "Can't be empty!";
        if (b === "" || b === null || b === undefined) {
            Validate.fail(a)
        }
        return true
    },
    Numericality: function (k, e) {
        var a = k;
        var k = Number(k);
        var e = e || {};
        var f = ((e.minimum) || (e.minimum == 0)) ? e.minimum : null;
        var c = ((e.maximum) || (e.maximum == 0)) ? e.maximum : null;
        var d = ((e.is) || (e.is == 0)) ? e.is : null;
        var g = e.notANumberMessage || "Numbers only";
        var h = e.notAnIntegerMessage || "Must be an integer!";
        var j = e.wrongNumberMessage || "Must be " + d + "!";
        var b = e.tooLowMessage || "Must not be less than " + f + "!";
        var l = e.tooHighMessage || "Must not be more than " + c + "!";
        if (!isFinite(k)) {
            Validate.fail(g)
        }
        if (e.onlyInteger && (/\.0+$|\.$/.test(String(a)) || k != parseInt(k))) {
            Validate.fail(h)
        }
        switch (true) {
        case (d !== null):
            if (k != Number(d)) {
                Validate.fail(j)
            }
            break;
        case (f !== null && c !== null):
            Validate.Numericality(k, {
                tooLowMessage: b,
                minimum: f
            });
            Validate.Numericality(k, {
                tooHighMessage: l,
                maximum: c
            });
            break;
        case (f !== null):
            if (k < Number(f)) {
                Validate.fail(b)
            }
            break;
        case (c !== null):
            if (k > Number(c)) {
                Validate.fail(l)
            }
            break
        }
        return true
    },
    Format: function (c, e) {
        var c = String(c);
        var e = e || {};
        var a = e.failureMessage || "Not valid!";
        var b = e.pattern || /./;
        var d = e.negate || false;
        if (!d && !b.test(c)) {
            Validate.fail(a)
        }
        if (d && b.test(c)) {
            Validate.fail(a)
        }
        return true
    },
    Email: function (b, c) {
        var c = c || {};
        var a = c.failureMessage || "Invalid email!";
        Validate.Format(b, {
            failureMessage: a,
            pattern: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
        });
        return true
    },
    Length: function (f, g) {
        var f = String(f);
        var g = g || {};
        var e = ((g.minimum) || (g.minimum == 0)) ? g.minimum : null;
        var h = ((g.maximum) || (g.maximum == 0)) ? g.maximum : null;
        var c = ((g.is) || (g.is == 0)) ? g.is : null;
        var a = g.wrongLengthMessage || "Must be " + c + " characters long!";
        var b = g.tooShortMessage || "Too short";
        var d = g.tooLongMessage || "Too long";
        switch (true) {
        case (c !== null):
            if (f.length != Number(c)) {
                Validate.fail(a)
            }
            break;
        case (e !== null && h !== null):
            Validate.Length(f, {
                tooShortMessage: b,
                minimum: e
            });
            Validate.Length(f, {
                tooLongMessage: d,
                maximum: h
            });
            break;
        case (e !== null):
            if (f.length < Number(e)) {
                Validate.fail(b)
            }
            break;
        case (h !== null):
            if (f.length > Number(h)) {
                Validate.fail(d)
            }
            break;
        default:
            throw new Error("Validate::Length - Length(s) to validate against must be provided!")
        }
        return true
    },
    Inclusion: function (h, f) {
        var f = f || {};
        var m = f.failureMessage || "Must be included in the list!";
        var g = (f.caseSensitive === false) ? false : true;
        if (f.allowNull && h == null) {
            return true
        }
        if (!f.allowNull && h == null) {
            Validate.fail(m)
        }
        var d = f.within || [];
        if (!g) {
            var a = [];
            for (var c = 0, b = d.length; c < b; ++c) {
                var k = d[c];
                if (typeof k == "string") {
                    k = k.toLowerCase()
                }
                a.push(k)
            }
            d = a;
            if (typeof h == "string") {
                h = h.toLowerCase()
            }
        }
        var l = false;
        for (var e = 0, b = d.length; e < b; ++e) {
            if (d[e] == h) {
                l = true
            }
            if (f.partialMatch) {
                if (h.indexOf(d[e]) != -1) {
                    l = true
                }
            }
        }
        if ((!f.negate && !l) || (f.negate && l)) {
            Validate.fail(m)
        }
        return true
    },
    Exclusion: function (a, b) {
        var b = b || {};
        b.failureMessage = b.failureMessage || "Must not be included in the list!";
        b.negate = true;
        Validate.Inclusion(a, b);
        return true
    },
    Confirmation: function (c, d) {
        if (!d.match) {
            throw new Error("Validate::Confirmation - Error validating confirmation: Id of element to match must be provided!")
        }
        var d = d || {};
        var b = d.failureMessage || "Does not match!";
        var a = d.match.nodeName ? d.match : document.getElementById(d.match);
        if (!a) {
            throw new Error("Validate::Confirmation - There is no reference with name of, or element with id of '" + d.match + "'!")
        }
        if (c != a.value) {
            Validate.fail(b)
        }
        return true
    },
    Acceptance: function (b, c) {
        var c = c || {};
        var a = c.failureMessage || "Must be accepted!";
        if (!b) {
            Validate.fail(a)
        }
        return true
    },
    Custom: function (d, e) {
        var e = e || {};
        var b = e.against ||
        function () {
            return true
        };
        var a = e.args || {};
        var c = e.failureMessage || "Not valid!";
        if (!b(d, a)) {
            Validate.fail(c)
        }
        return true
    },
    now: function (a, d, c) {
        if (!a) {
            throw new Error("Validate::now - Validation function must be provided!")
        }
        var e = true;
        try {
            a(d, c || {})
        } catch (b) {
            if (b instanceof Validate.Error) {
                e = false
            } else {
                throw b
            }
        } finally {
            return e
        }
    },
    fail: function (a) {
        throw new Validate.Error(a)
    },
    Error: function (a) {
        this.message = a;
        this.name = "ValidationError"
    }
};
