function validator(formname)
{
  if(!document.forms[formname])
  {
    alert('form not found');
  }

  validator.formObj           = document.forms[formname];
  validator.validateAttribute = 'class';
  validator.formObj.onsubmit  = function() { return validator.validate(formname); };

  for(i=0; i < validator.formObj.elements.length; i++)
  {
    var element = validator.formObj.elements[i];
    if(element.getAttribute(validator.validateAttribute))
    {
      var attributes  = element.getAttribute(validator.validateAttribute).split(' ');
      var validate    = 'form-holder';
      for (var num in attributes)
      {
        switch(attributes[num])
        {
          case 'required':
          case 'email':
          case 'url':
          case 'date':
          case 'int':
          case 'float':
          case 'telephone':
          case 'zipcode':
          case 'jpg':
          case 'gif':
          case 'img':
            validate += ' ' +  attributes[num];
            break;
        }
      }
      element.parentNode.innerHTML = '<div class="' + validate + '">' + element.parentNode.innerHTML + '</div>';
    }
  }

  validator.getValue = function(element)
  {
    if(!element) return '';
    if((element.length>1 && element.tagName.toUpperCase() != 'SELECT') || element.type == 'radio')
    {
      if(!element.length) // it's an radio elem, get the ObjectNodeList of the radio elem
        element = element.form.elements[element.name];

      var radioLength = element.length;
	    for(var i = 0; i < radioLength; i++)
      {
		    if(element[i].checked)
        {
			    return element[i].value;
		    }
	    }
      return "";
    }
    else if (element.type == 'checkbox')
    {
      if (element.checked)
        return element.value;
      else
        return '';
    }
    else if (element.type == 'select-one')
    {
      if (-1 != element.selectedIndex)
        return element.options[element.selectedIndex].value;
    }
    else if (element.type == 'select-multiple')
    {
      var selectedoptions = new Array();
      for (var i = 0; i < element.options.length; i++)
        if (element.options[i].selected)
          selectedoptions.push([element.options[i].value]);

      if(selectedoptions.length > 0)
        return selectedoptions;
      else
        return '';
    }
    else if (element.tagName.toUpperCase() == 'SELECT') // this will not work for a multiselect !!!!
    {
      if (-1 != element.selectedIndex)
        return element.options[element.selectedIndex].value;
    }
    else
    {
      return element.value;
    }
  }

  validator.setState = function(element, state)
  {
    var classNames    = element.parentNode.className.split(' ');
    var newClassName  = '';
    for(var i=0; i < classNames.length; i++)
    {
      if(classNames[i].indexOf('state_')===-1)
      {
        newClassName += classNames[i] + ' ';
      }
    }
    newClassName += 'state_' + state;
    element.parentNode.className =  newClassName;
  }

  validator.validate = function(formname)
  {
    if(formname)
    {
      var elements = document.forms[formname];
    }
    else
    {
      var elements = validator.formObj.elements;
    }

    var returnValue = true;
    for(var i=0; i < elements.length; i++)
    {
      var element = elements[i];

      if(element.getAttribute(validator.validateAttribute))
      {
        var validate  = element.getAttribute(validator.validateAttribute).split(' ');
        var correct   = true;
        var value     = validator.getValue(element).trim();

        for(var v=0; v < validate.length; v++)
        {
          switch(validate[v])
          {
            case 'required':
              correct = validator.validation_required(value);
              break
            case 'email':
              correct = validator.validation_email(value);
              break;
            case 'url':
              correct = validator.validation_url(value);
              break;
            case 'date':
              correct = validator.validation_date(value);
              break;
            case 'int':
              correct = validator.validation_int(value);
              break;
            case 'float':
              correct = validator.validation_float(value);
              break;
            case 'telephone':
              correct = validator.validation_telephone(value);
              break;
            case 'zipcode':
              correct = validator.validation_zipcode(value);
              break;
            case 'jpg':
              correct = validator.validation_jpg(value);
              break;
            case 'gif':
              correct = validator.validation_gif(value);
              break;
            case 'img':
              correct = validator.validation_img(value);
              break;
          }

          if(!correct)
          {
            returnValue = false;
            break;
          }
        }

        validator.setState(element, ((correct) ? 'correct' : 'incorrect'));
      }
    }

    return returnValue;
  }

  /* rules */
  validator.validation_required = function(value)
  {
    value = unescape(value.trim());
    return (value.length<1) ? false : true;
  }

  validator.validation_email = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
	    var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.){1,2}[a-zA-Z]{2,4}$/;
      return filter.test(value);
    }
    return true;
  }

  validator.validation_url = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var v = new RegExp();
      v.compile("^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_%&\?\/.=]+$");
	    return v.test(value);
    }
    return true;
  }

  validator.validation_int = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var filter = /^\d+$/;
      return filter.test(value);
    }
    return true;
  }

  validator.validation_date = function(value)
  {
    value = unescape(value);
    if(value.length > 0)
    {
      var filterNl  = /^([0-9]{2})-([0-9]{2})-([0-9]{4})$/;
      var filterEng = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/;

      if (filterNl.test(value) == false && filterEng.test(value) == false)
        return false;
    }
    return true;
  }

  validator.validation_float = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var filter = /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
      return filter.test(value);
    }
    return true;
  }

  validator.validation_telephone = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var filter = /^([\+])?([0-9-]{8,20})$/;
      return filter.test(value);
    }
    return true;
  }

  validator.validation_zipcode = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
	    var filter  = /^[0-9]{4}[ ]?[a-zA-Z]{2}$/;
      return (filter.test(value) ? true : false);
    }
    return true;
  }

  validator.validation_jpg = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var filter = /^([a-zA-Z].*|[1-9].*)\.((j|J)(p|P)(e|E){0,1}(g|G))$/;
      return (filter.test(value) ? true : false);
    }
    return true;
  }

  validator.validation_gif = function(value)
  {
    value = unescape(value);
    if(value.length>0)
    {
      var filter = /^([a-zA-Z].*|[1-9].*)\.((g|G)(i|I)(f|F))$/;
      return (filter.test(value) ? true : false);
    }
    return true;
  }

  validator.validation_img = function(value)
  {
    if (validator.validation_jpg(value) || validator.validation_gif(value))
    {
      return true;
    }
    return false;
  }
}

