var Validator={
    isEmail:function(s){
        return this.test(s,'^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$');
    },
    isAbsUrl:function(s){
        return this.test(s,'^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$');
    },
    isSize:function(s){
        return this.test(s,'^[0-9]+(px|%)?$');
    },
    isId:function(s){
    return this.test(s,'^[A-Za-z_]([A-Za-z0-9_])*$');
    },
    isEmpty:function(s){
        var nl,i;
        if(s.nodeName=='SELECT' && s.options[s.selectedIndex].value=='')
            return true;
        if(s.type=='checkbox' && !s.checked)
            return true;
        if(s.type=='radio'){
            for(i=0,nl=s.form.elements;i<nl.length;i++){
                if(nl[i].type=="radio" && nl[i].name==s.name && nl[i].checked)
                    return false;
            }
            return true;
        }
        return new RegExp('^\\s*$').test(s.nodeType==1?s.value:s);
    },
    isNumber:function(s,d){
        return !isNaN(s.nodeType==1?s.value:s) && (!d||!this.test(s,'^-?[0-9]*\\.[0-9]*$'));
    },
    isDateTime:function(s,f){
        var l=new Array(),m,i,v,c;
        if(this.isEmpty(s=s.nodeType==1?s.value:s))
            return true;
        f=f.replace(/[\.\*\?\-\[\]\{\}\/\\\x22\x27]/g,
            function(a,b){
                return'\\'+a;
            }
        );
        f=f.replace(/(YYYY|mm|dd|hh|ii|ss|HH|g|AA|aa)/g,
            function(a,b){
                l.push(a);
                if(a=='AA'||a=='aa')
                    return a=='AA'?'(AM|PM)':'(am|pm)';
                return'([0-9]{'+(a=='YYYY'?4:(a=='g'?'1,2':2))+'})';
            }
        );
        for(i=1,c=0,m=new RegExp('^'+f+'$').exec(s);m&&i<m.length;i++){
            r=l[i-1];
            v=parseInt(m[i]);
            c+=r=='mm'&&(v<1||v>12);
            c+=r=='dd'&&(v<1||v>31);
            c+=r=='HH'&&v>23;
            c+=(r=='hh'||r=='g')&&(v<1||v>12);
            c+=(r=='ii'||r=='ss')&&(v<0||v>59);
        }
        return m&&c<1;
    },
    test:function(s,p){
        s=s.nodeType==1?s.value:s;
        return s==''||new RegExp(p).test(s);
    }
};
var AutoValidator={
    customTypes:new Array(),
    settings:{
        id_cls:'id',
        int_cls:'int',
        url_cls:'url',
        number_cls:'number',
        email_cls:'email',
        size_cls:'size',
        required_cls:'required',
        invalid_cls:'invalid',
        min_cls:'min',
        max_cls:'max',
        confirm_cls:'confirm',
        confirmmsg_cls:'confirmmsg',
        notconfirmed_cls:'notconfirmed',
        date_cls:'date',
        time_cls:'time',
        datetime_cls:'datetime',
        date_format:'YYYY-mm-dd',
        time_format:'HH:ii',
        datetime_format:'YYYY-mm-dd HH:ii'
    },
    init:function(s){
        var n;
        for(n in s)
            this.settings[n]=s[n];
    },
    addCustomType:function(c,f){
        this.customTypes.push({cls:c,func:f});
    },
    validate:function(f){
        var i,nl,s=this.settings,c=0;
        nl=this.tags(f,'label');
        for(i=0;i<nl.length;i++)this.removeClass(nl[i],s.invalid_cls);
        c+=this.markGroups(f);
        c+=this.validateElms(f,'input');
        c+=this.validateElms(f,'select');
        c+=this.validateElms(f,'textarea');
        this.markLabels(f,f,c==3?'':s.invalid_cls);
        return c==3;
    },
    invalidate:function(n){
        this.mark(n.form,n);
    },
    reset:function(e){
        var t=new Array('label','input','select','textarea');
        var i,j,nl,s=this.settings;
        if(e==null)return;
        for(i=0;i<t.length;i++){
            nl=this.tags(e.form?e.form:e,t[i]);
            for(j=0;j<nl.length;j++){
                this.removeClass(nl[j],s.invalid_cls);
                this.removeClass(nl[j],s.notconfirmed_cls);
            }
        }
    },markGroups:function(f){
        var nl,i,x,nx,s=this.settings,st,os=0;
        nl=this.tags(f,'div');
        for(i=0;i<nl.length;i++){
            st=0;
            if(this.hasClass(nl[i],s.required_cls)){
                if(this.hasClass(nl[i],s.required_cls)){
                    nx=this.tags(nl[i],'input');
                    for(x=0;x<nx.length;x++){
                        if(nx[x].checked||!Validator.isEmpty(nx[x])){
                            st=1;
                            break;
                        }
                    }
                }
                if(!st)
                    os+=!this.mark(f,nl[i]);
            }
        }
        return os;
    },
    validateElms:function(f,e){
        var nl,i,n,s=this.settings,ct=this.customTypes,st=true,va=Validator,v,x;
        nl=this.tags(f,e);
        for(i=0;i<nl.length;i++){
            n=nl[i];this.removeClass(n,s.invalid_cls);
            if(this.hasClass(n,s.required_cls)&&va.isEmpty(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.notconfirmed_cls)){
                this.removeClass(n,s.confirm_cls);
                this.removeClass(n,s.notconfirmed_cls);
                this.markLabels(f,n,'',s.notconfirmed_cls);
            }
            if(this.hasClass(n,s.confirm_cls)&&va.isEmpty(n)){
                this.addClass(n,s.notconfirmed_cls);
                st=this.markLabels(f,n,s.notconfirmed_cls,0,s.confirmmsg_cls);
            }
            if(this.hasClass(n,s.number_cls)&&!va.isNumber(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.int_cls)&&!va.isNumber(n,true))
                st=this.mark(f,n);
            if(this.hasClass(n,s.url_cls)&&!va.isAbsUrl(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.email_cls)&&!va.isEmail(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.size_cls)&&!va.isSize(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.id_cls)&&!va.isId(n))
                st=this.mark(f,n);
            if(this.hasClass(n,s.min_cls,true)){
                v=this.getNum(n,s.min_cls);
                if(isNaN(v)||parseInt(n.value)<parseInt(v))
                    st=this.mark(f,n);
            }
            if(this.hasClass(n,s.max_cls,true)){
                v=this.getNum(n,s.max_cls);
                if(isNaN(v)||parseInt(n.value)>parseInt(v))
                    st=this.mark(f,n);
            }
            if(this.hasClass(n,s.date_cls)&&!va.isDateTime(n,s.date_format))
                st=this.mark(f,n);
            if(this.hasClass(n,s.time_cls)&&!va.isDateTime(n,s.time_format))
                st=this.mark(f,n);
            if(this.hasClass(n,s.datetime_cls)&&!va.isDateTime(n,s.datetime_format))
                st=this.mark(f,n);
            for(x=0;x<ct.length;x++){
                if(this.hasClass(n,ct[x].cls)&&!ct[x].func(n))
                    st=this.mark(f,n);
            }
        }
        return st;
    },
    hasClass:function(n,c,d){
        return new RegExp('\\b'+c+(d?'[\\-?0-9]+':'')+'\\b','g').test(n.className);
    },
    getNum:function(n,c){
        c=n.className.match(new RegExp('\\b'+c+'\\-?([0-9]+)\\b','g'))[0];
        c=c.replace(/[^0-9\-]/g,'');
        return c;
    },
    addClass:function(n,c,b){
        var o=this.removeClass(n,c);
        n.className=b?c+(o!=''?(' '+o):''):(o!=''?(o+' '):'')+c;
    },
    removeClass:function(n,c){
        c=n.className.replace(new RegExp("(^|\\s+)"+c+"(\\s+|$)"),' ');
        return n.className=c!=' '?c:'';
    },
    tags:function(f,s){
        return f.getElementsByTagName(s);
    },
    mark:function(f,n){
        var s=this.settings;
        this.addClass(n,s.invalid_cls);
        this.markLabels(f,n,s.invalid_cls);
        return false;
    },
    markLabels:function(f,n,ic,rc,hc){
        var nl,i;
        nl=this.tags(f,"label");
        for(i=0;i<nl.length;i++){
            if((nl[i].getAttribute("for")==n.id||nl[i].htmlFor==n.id)&&(!hc||this.hasClass(nl[i],hc))){
                !rc||this.removeClass(nl[i],rc);
                !ic||this.addClass(nl[i],ic);
            }
        }
        return false;
    }
};