    var Formcheck = new Class({
        
        options: $H({
            addAsterisk: true,
            submitTrigger: false,
            errorClasses: {
                input: '.fieldError',
                label: '.labelError'
            },
            onError: $empty,
            onSuccess: $empty
        }),
        
        initialize: function(form,options)
        {
            this.error = 0;
            this.errors = [];
            this.msg = '';            
            this.seperator = '|';
            
            this.options.extend(options || $H());
            this.form = $(form);
            this.validationClasses = ['required','email','url'];
            this.elements = this.getFormElements();

            this.addAsterisk();
            this.addListener();
        },
        
        /**
         * GETTER
         */
        getFormElements: function()
        {
            var es = [];
            var c = this.form.getChildren();
            c.each(function(el, i){
                el.get('class').split(' ').each(function(item){
                    if(this.validationClasses.contains(item))
                    {
                        es.push(c[i]);
                    }
                },this);
            }, this);
            return es;
        },
        getLabelFor: function(el)
        {
            return el.getPrevious('label') != null ? el.getPrevious('label') : el.parentNode.getPrevious('label');
        },
        getFieldType: function(el)
        {
            var disabled = false;
            var fieldType = '';

            var fieldtypes = [];

            el.get('class').split(' ').each(function(item){
                if(this.validationClasses.contains(item))
                {
                    fieldtypes.push(item);
                }
            },this);
            
            return fieldtypes;
        },
        getParameter: function(el)
        {
            fieldType = el.split(this.seperator)[1];
            return str_replace(['[',']'],'',fieldType.substr(fieldType.lastIndexOf('[')+1));    
        },
        getElementType: function(el)
        {
            return el.type || el.tagName.toLowerCase();
        },
        isOptional: function(el)
        {
            return el.hasClass('optional');
        },
        addAsterisk: function()
        {
            if(this.options.get('addAsterisk'))
            {
                var es = this.getFormElements();
                es.each(function(el){
                    if(!this.isOptional(el))
                    {
                        var label = this.getLabelFor(el);
                        if(!label.getElement('span'))
                        {
                            label.adopt(new Element('span', {
                                text: '*'  
                            }));
                        }
                    }
                }, this);
            }
        },        
        validateField: function(key)
        {
            var el = this.elements[key];
            var optional = this.isOptional(el);
            var fieldType = this.getFieldType(el)[0];

            // TODO getValue method
            var value = el.get('value').stripScripts().trim();

            this.errors.erase(el);

            switch(fieldType)
            {
                case 'required':
                    if(value == '')
                    {
                        this.errors.push(el);
                    }
                    break;
                case 'checkbox':
                    if(!field.checked)
                    {
                        this.errors.push(field);    
                    }
                    break;
                default:
                    this.check(fieldType,el,key,optional);
                    break;
            }
            this.highlightLabels();
            this.highlightFields();
        },
        validateAll: function()
        {
            this.clearErrors();
            this.elements.each(function(el, i)
            {
                this.validateField(i);
            }, this);
            if(this.errors.length == 0)
            {
                this.options.onSuccess();
            }
            else
            {
                this.highlightLabels();
                this.highlightFields();
            }
        },
        check: function(fieldType,field,cnt, optional)
        {
            var val = field.value.stripScripts().trim();
            var valid = false;

            if(val != '')
            {
                switch(fieldType)
                {
                    case 'minlength':
                        var param = this.getParameter(this.elements[cnt]).toInt();
                        valid = val.length >= param ? true : false;
                        break;
                    case 'email':
                        reg = new RegExp('^([a-zA-Z0-9\\-\\.\\_]+)(\\@)([a-zA-Z0-9\\-\\.]+)(\\.)([a-zA-Z]{2,4})$');
                        valid = reg.test(val);
                        break;
                    case 'phone':
                        reg = new RegExp('^([+])?(0)+([0-9]{2,})(\/)([0-9]{3,})$');
                        valid = reg.test(val);
                        break;
                    case 'url':
                        reg = new RegExp(/^(?:http:\/\/)?(?:[\w-]+\.)+[a-z]{2,6}(?:\/)?$/i);
                        valid = reg.test(val);
                        break;
                    case 'zipcode':
                        reg = new RegExp('^([0-9]{5})$');
                        valid = reg.test(val);
                        break;
                    case'date':
                        reg1 = new RegExp('^([0-9]{2}(.)([0-9]{2})(.)([0-9]{4}))$');
                        reg2 = new RegExp('^([0-9]{4}(-)([0-9]{2})(-)([0-9]{2}))$');
                        valid = reg1.test(val) || reg2.test(val);
                        break;
                    default:
                        break;
                }
            }
            if(optional)
            {
                valid = true;
            }

            if(!valid && !optional)
            {
                this.errors.push(field);
            }
        },
        highlightLabels: function()
        {
            this.elements.each(function(el)
            {
                var label = this.getLabelFor(el);

                var myEffect = new Fx.Morph(label, {duration: 1000, transition: Fx.Transitions.Sine.easeOut});
                
                if(this.errors.contains(el))
                {
                    myEffect.start(this.options.errorClasses.label);
                    //label.addClass(this.errorClassName);
                }
                else
                {
                    myEffect.start('.label');                    
                    //label.removeClass();
                }
            }, this);
        },
        highlightFields: function()
        {
            this.elements.each(function(el)
            {

                var myEffect = new Fx.Morph(el, {duration: 1000, transition: Fx.Transitions.Sine.easeOut});
                
                if(this.errors.contains(el))
                {
                    myEffect.start(this.options.errorClasses.input);
                }
                else
                {
                    myEffect.start('.field');
                }
            },this);   
        },
        clearErrors: function()
        {
            this.errors.empty();
        },
        getSubmitTrigger: function()
        {
            return this.options.submitTrigger ? this.options.submitTrigger : this.form.getElement('input[type=submit]');
        },
        addListener: function()
        {
            var trigger = this.getSubmitTrigger();
            if(trigger.tagName.toLowerCase() == 'a')
            {
                trigger.addEvent('click', function(e){
                    e.stop();
                    this.validateAll();
                }.bind(this));
            }
            else
            {
                this.form.addEvent('submit', function(e){
                    e.stop();
                    this.validateAll();
                }.bind(this));
            }
            this.elements.each(function(el, i)
            {
                var element = this.elements[i];
                element.addEvent('blur', this.validateField.bind(this,[i]));    
            }, this);
        }
  });