//http://webcloud.se/article/Form_validation_with_jQuery_from_scratch/?demo-field-1=s&demo-field-1=&demo-field-3=
(function($) {

    /*
    Validation Singleton
    */
    var Validation = function() {
        //debugger;
        var rules = {

            email: {
                check: function(value) {

                    if (value)
                        return testPattern(value);
                    return true;
                },
                msg: "enter a valid e-mail address."
            },
            email2: {
                check: function(value) {

                    if (value)
                        return testPattern(value);
                    return true;
                },
                msg: "invalid email."
            },
            url: {

                check: function(value) {

                    if (value)
                        return testPattern(value, "https?://(.+\.)+.{2,4}(/.*)?");
                    return true;
                },
                msg: "enter a valid URL."
            },
            required: {

                check: function(value) {

                    if (value)
                        return true;
                    else
                        return false;
                },
                msg: "this field is required."
            },
            epos: {
                check: function(value) {

                    if (value)
                        return testPattern(value);
                    return true;
                },
                msg: "voer 'n geldige e-pos adres."
            },
            vereis: {

                check: function(value) {

                    if (value)
                        return true;
                    else
                        return false;
                },
                msg: "hierdie veld is verpligtend."
            },
            dateformat: {
                check: function(value) {
                    if (value)
                        return checkDate(value);
                    return true;
                },
                msg: ""
            }
        }
        var testPattern = function(value) {
            var emailRegEx = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
            if (value.match(emailRegEx)) { return true; } else { return false; }
        }

        // Original JavaScript code by Chirp Internet: www.chirp.com.au
        // Please acknowledge use of this code by including this header.
        function checkDate(field) {
            var allowBlank = true;
            var minYear = 1902;
            var maxYear = (new Date()).getFullYear();

            var errorMsg = "";

            // regular expression to match required date format
            re = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;

            if (field != '') {
                if (regs = field.match(re)) {
                    if (regs[1] < 1 || regs[1] > 31) {
                        errorMsg = "Invalid value for day: " + regs[1];
                    } else if (regs[2] < 1 || regs[2] > 12) {
                        errorMsg = "Invalid value for month: " + regs[2];
                    } else if (regs[3] < minYear || regs[3] > maxYear) {
                        errorMsg = "Invalid value for year: " + regs[3] + " - must be between " + minYear + " and " + maxYear;
                    }
                } else {
                    errorMsg = "Invalid date format: " + field;
                }
            } else if (!allowBlank) {
                errorMsg = "Empty date not allowed!";
            }

            if (errorMsg != "") {
                return false;
            }

            return true;
        }

        return {

            addRule: function(name, rule) {

                rules[name] = rule;
            },
            getRule: function(name) {

                return rules[name];
            }
        }
    }

    /* 
    Form factory 
    */
    var Form = function(form) {

        var fields = [];
        form.find("input[validation], textarea[validation], select[validation]").each(function() {

            fields.push(new Field(this));
        });
        this.fields = fields;
    }
    Form.prototype = {
        validate: function() {

            for (field in this.fields) {

                this.fields[field].validate();
            }
        },
        isValid: function() {

            for (field in this.fields) {

                if (!this.fields[field].valid) {

                    //this.fields[field].field.focus();
                    return false;
                }
            }
            return true;
        }
    }

    /* 
    Field factory 
    */
    var Field = function(field) {

        this.field = $(field);
        this.valid = false;
        this.attach("change");
    }
    Field.prototype = {

        attach: function(event) {

            var obj = this;
            if (event == "change") {
                obj.field.bind("change", function() {
                    return obj.validate();
                });
            }
            if (event == "keyup") {
                obj.field.bind("keyup", function(e) {
                    return obj.validate();
                });
            }
        },
        validate: function() {

            var obj = this,
                field = obj.field,
                errorClass = "errorlist",
                errorlist = $(document.createElement("span")).addClass(errorClass),
                types = field.attr("validation").split(" "),
                container = field.parent(),
                errors = [];

            field.next(".errorlist").remove();
            for (var type in types) {

                var rule = $.Validation.getRule(types[type]);
                if (!rule.check(field.val())) {

                    container.addClass("error");
                    errors.push(rule.msg);
                }
            }
            if (errors.length) {

                obj.field.unbind("keyup")
                obj.attach("keyup");
                field.after(errorlist.empty());
                for (error in errors) {

                    errorlist.append("<span>" + errors[error] + "</span>");
                }
                obj.valid = false;
            }
            else {
                errorlist.remove();
                container.removeClass("error");
                obj.valid = true;
            }
        }
    }

    /* 
    Validation extends jQuery prototype
    */
    $.extend($.fn, {

        validation: function() {

            var validator = new Form($(this));
            $.data($(this)[0], 'validator', validator);

            //$(this).bind("click", function(e) {
            validator.validate();
            if (!validator.isValid()) { return false; } else { return true; }
            //});
        },
        validate: function() {

            var validator = $.data($(this)[0], 'validator');
            validator.validate();
            return validator.isValid();

        }
    });
    $.Validation = new Validation();
})(jQuery);

$.Validation.addRule("phonenumber", { check: function(value) { if (value.length != 10) { return false; } return true; }, msg: "please enter a 10 digit number" });
$.Validation.addRule("number", { check: function(value) { if (isNaN(value)) { return false; } else { return true; } }, msg: "please enter a number" });
$.Validation.addRule("required_eg", { check: function(value) { if ((value) && value.indexOf('e.g.') == -1) { return true; } else { return false; } }, msg: "" });
