VALIDATE = {
    error_div: null,
    labels: null,
    missing: null,
    required_message:
        "<b>The following fields are required:</b>",
        
    match_message: function(field) { 
        return this.label_text(field) + " is in invalid format"
    },
    
    equals_message: function(field, other) { 
        return this.label_text(field) + " must equal " + this.label_text(other);
    },

    error_message: null,
    
    byid: function(id) {
        return document.getElementById(id);    
    },
    
    mark_invalid: function(id) {
        var el = this.byid(id);
        if (el) {
            el.className = el.className + " er";
            var l = this.label(el.id);
            if (l) l.className+=" er";
        }
    },
    
    mark_valid: function(id) {
        var el = this.byid(id);
        el.className = el.className.replace(/\s*er$/g, ''); 
        this.label(el.id).className =
            this.label(el.id).className.replace(/\s*er/g,'');        
    },
    
    
    
    label: function(id) {
        var myLabels = new Array();
        this.labels = this.labels || document.getElementsByTagName("LABEL");
        for (i in this.labels) {
            if (this.labels[i].htmlFor == id) {
                return this.labels[i];
            }
        }
        return null;
    },
    
    
    
    label_text: function(id) {
        return (this.label(id)) ? this.label(id).innerHTML.replace(/:\s*$/, '') : id;
    },
    
    has_data: function(form, id) {
        var el = form[id];
        return (el) ? el.value : false;
    },
    
    match: function(re, form, id) {
        var el = form[id];
        
        var matches = re.match(/^\/(.*?)\/(.*?)$/);
        var r = new RegExp(matches[1], matches[2]);
        return el.value.match(r);
    },
   
    required_if: function() {
    
    },
    
    assert: function(id) {
        if (this.byid(id) == null) {
            alert("Missing Element: " + id);
        }
    },

    validate_form: function(form, fields) {
        var is_valid = true;
        this.error_message = new Array();
        this.missing = new Array();
        
        // check fields
        for (field in fields) {
            for (val in fields[field]) {
                switch (val) {

                    case 'required':
                        if (!this.has_data(form, field)) {
                            is_valid = false;
                            this.mark_invalid(field);
                            this.missing.push(this.label_text(field));
                        }
                    break;
        
                    case 'required_if':
                        if (this.has_data(form, fields[field][val]) && !this.has_data(form, field)) {
                            is_valid = false;
                            this.mark_invalid(field);
                            this.missing.push(this.label_text(field));
                        }
                    break;

                    case 'match':
                        if (!this.match(fields[field][val], form, field)) {
                            is_valid = false;
                            this.mark_invalid(field);
                            var msg = fields[field][val + '_message'] || this.match_message(field);
                            this.error_message.push('<b>' + this.label_text(field) + ' error:</b><br/>' + msg);
                        }
                    break;

                    case 'equals':
                        var other = fields[field][val];
                        this.assert(other);
                        if ( form[field].value != form[other].value ) {
                            is_valid = false;
                            this.mark_invalid(field);
                            this.mark_invalid(other);
                            var msg = fields[field][val + '_message'] || this.equals_message(field, other);
                            var error = '<b>' + this.label_text(field) + ' error</b>:<br />' + msg;
                            this.error_message.push(error);
                        }
                    break;
                }
            }
        }
        
        // alert user if invalid
        if (!is_valid) {
            if (!this.error_div) {
                this.error_div = document.createElement('DIV')
                this.error_div.className = "error";
                form.parentNode.insertBefore(this.error_div, form)
            }
            if (this.missing.length) {
                var req_msg = this.required_message;
                for (i in this.missing) {
                    req_msg += '<br/>' + this.missing[i];
                }
                this.error_message.push(req_msg);
            }
            var msg = '<p>' + this.error_message.join('<br/><br/>') + '</p>';
            this.error_div.innerHTML = msg;
        }
        return is_valid;
    }
};
