

  var FormValidator = {

    fieldRequiredClassName: 'required',
    fieldEmailClassName: 'email',
    strictFormatClassName: 'strictFormat',
    strictExtensionsClassName: 'strictExtensions',
    fieldErrorClassName: 'fieldError',
    labelErrorClassName: 'labelError',
    fieldEmptyOnClickClassName: 'emptyOnClick',
    fieldCanBeDefaultClassName: 'canBeDefault',
    showNames: true,
    stripSuffixes: false, // strip the suffix that is  appended to the name with an underscore
    stripUnderscores: true, // strip the underscores of names

    initialize: function()
    {
      // set submit event of each form
      var form;
      for (var i = 0; form = document.getElementsByTagName('form')[i]; i++)
      {
        this.addEvent(form, 'submit', (function (scope, form) {
          return function(e)
          {
            (function(){
              this.submit(form);
            }).call(scope);
          };
        })(this, form));
      }


      // set form elements' click and blur events
      var element, elements = this.getElementsByClassName(this.fieldEmptyOnClickClassName, 'input');
      for (var i = 0; element = elements[i]; i++)
      {
        element.onclick = function(){if(this.defaultValue == this.value && this.type.toLowerCase() != 'submit'){this.value = ''}};
        element.onblur = function(){if(this.value.trim() == ''){this.value = this.defaultValue}};
      }
    },


    // submit form
    submit: function(form)
    {
      var errorMssg;

      if (errorMssg = this.check(form))
      {
        /* Email wordt E-mail, RP 2009-10-05 */
        alert(errorMssg.replace('Email', 'E-mail'));
        return false;
      }
      
      branche_selection = document.getElementById('cP_branche');
      
      if (typeof(branche_selection) != 'undefined' && branche_selection != null)
      {
        if (branche_selection.options[branche_selection.selectedIndex].value == "")
        {
          alert('U heeft nog geen branche gekozen.');
      
          return false
        }
      }
      return true;
    },


    // check whether the required fields have been filled in
    check: function(form)
    {
      var
        errorMssg,
        requiredInput, requiredInputs = this.getElementsByClassName(this.fieldRequiredClassName, 'input', form),
        inputCollection, collectionInput, inputLabel, alternatives, alternative, alternativeIsSet = false,
        names = '\n';

      for (i = 0; requiredInput = requiredInputs[i]; i++)
      {
        // no value in radio or checkbox collection selected
        // or no value filled in or value is the default value and this is not allowed
        if (
          ((requiredInput.type == 'radio' || requiredInput.type == 'checkbox') && !this.getInputCollectionValue(inputCollection = this.getInputCollection(requiredInput.name, requiredInput.type, form)))
          ||
          (requiredInput.type != 'radio' && requiredInput.type != 'checkbox' && (requiredInput.value.trim() == '' || (requiredInput.value == requiredInput.defaultValue && !this.hasClassName(requiredInput, this.fieldCanBeDefaultClassName))))
        )
        {
          if (requiredInput.type == 'radio' || requiredInput.type == 'checkbox')
          {
            for (j = 0; collectionInput = inputCollection[j]; j++)
            {
              if (inputLabel = this.getLabel(collectionInput.id)) this.addClassName(inputLabel, this.labelErrorClassName);
//              errorMssg = 'U heeft nog niet alle relevante velden ingevuld.';
              errorMssg = document.getElementById('fm_allFields').innerHTML;
            }
            for (j = 0; collectionInput = inputCollection[j]; j++)
            {
              if (collectionInput.name) names += '\n' + (this.stripSuffixes ? collectionInput.name.replace(/_[^_\s]*$/ ,'') : collectionInput.name);
              break;
            }
          }
          else
          {
            alternatives = requiredInput.className.match(/.*alternatives=\[([^\]]*)\].*/);
            if (alternatives)
            {
              alternatives = alternatives[1].split(',');

              for (j = 0; alternative = document.getElementById(alternatives[j]); j++)
              {
                if (!(alternative.value.trim() == '' || (alternative.value == alternative.defaultValue && !this.hasClassName(alternative, this.fieldCanBeDefaultClassName))))
                {
                  alternativeIsSet = true;
                }
              }

              if (alternativeIsSet)
              {
                this.removeClassName(requiredInput, this.fieldErrorClassName);
              }
              else
              {
                this.addClassName(requiredInput, this.fieldErrorClassName);
//              errorMssg = 'U heeft nog niet alle relevante velden ingevuld.';
                errorMssg = document.getElementById('fm_allFields').innerHTML;
                names += '\n' + (this.stripSuffixes ? requiredInput.name.replace(/_[^_\s]*$/ ,'') : requiredInput.name);
              }
            }
            else
            {
              this.addClassName(requiredInput, this.fieldErrorClassName);
//              errorMssg = 'U heeft nog niet alle relevante velden ingevuld.';
              errorMssg = document.getElementById('fm_allFields').innerHTML;
              names += '\n' + (this.stripSuffixes ? requiredInput.name.replace(/_[^_\s]*$/ ,'') : requiredInput.name);
            }
          }
        }
        else
        {
          if (requiredInput.type == 'radio' || requiredInput.type == 'checkbox')
          {
            for (j = 0; collectionInput = inputCollection[j]; j++)
            {
              if (inputLabel = this.getLabel(collectionInput.id)) this.removeClassName(inputLabel, this.labelErrorClassName);
            }
          }
          else
          {
            this.removeClassName(requiredInput, this.fieldErrorClassName);
          }
        }
      }

      if (!errorMssg)
      {
        var emailInput, emailInputs = this.getElementsByClassName(this.fieldEmailClassName, 'input', form);

        for (var i = 0; emailInput = emailInputs[i]; i++)
        {
          if (emailInput.value != "" && emailInput.value.search(/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/) == -1)
          {
            this.addClassName(emailInput, this.fieldErrorClassName);
//            errorMssg = 'Het opgegeven e-mail adres is ongeldig.';
            errorMssg = document.getElementById('fm_email').innerHTML;
            names += '\n' + (this.stripSuffixes ? emailInput.name.replace(/_[^_\s]*$/ ,'') : emailInput.name);
          }
          else
          {
            this.removeClassName(emailInput, this.fieldErrorClassName);
          }
        }
      }

      if (!errorMssg)
      {
        var format, strictFormatInput, strictFormatInputs = this.getElementsByClassName(this.strictFormatClassName, 'input', form);

        for (i = 0; strictFormatInput = strictFormatInputs[i]; i++)
        {
          if (strictFormatInput.value != '')
          {
            format = strictFormatInput.className.replace(/.*format=([^\s$]*).*/, '$1');
            if (new RegExp(format).test(strictFormatInput.value) == false)
            {
//              errorMssg = (strictFormatInput.type == 'file' ? 'Het bestandstype is niet juist.' : 'De notatie is niet correct.');
              errorMssg = (strictFormatInput.type == 'file' ? document.getElementById('fm_filetype').innerHTML : document.getElementById('fm_notation').innerHTML);
              this.addClassName(strictFormatInput, this.fieldErrorClassName);
              names += '\n' + (this.stripSuffixes ? strictFormatInput.name.replace(/_[^_\s]*$/ ,'') : strictFormatInput.name);
            }
            else
            {
              this.removeClassName(strictFormatInput, this.fieldErrorClassName);
            }
          }
        }
      }

      if (!errorMssg)
      {
        var extension, extensions, strictExtensionsInput, strictExtensionsInputs = this.getElementsByClassName(this.strictExtensionsClassName, 'input', form);

        for (i = 0; strictExtensionsInput = strictExtensionsInputs[i]; i++)
        {
          if (strictExtensionsInput.value != '')
          {
            eval(strictExtensionsInput.className.replace(/.*(extensions=\[[^\]]*\]).*/, '$1'));

            for (j = 0; extension = extensions[j]; j++)
            {
              if (strictExtensionsInput.value.replace(/.*\.([^\.]*)/, '$1').toLowerCase() == extension.toLowerCase())
              {
                this.removeClassName(strictExtensionsInput, this.fieldErrorClassName);
                break;
              }
            }
            if (j == extensions.length)
            {
//              errorMssg = 'Alleen bestanden met de extensie \'' + extensions.join('\', \'').replace(/,([^,]*$)/, ' of$1') + '\' zijn toegestaan.';
              errorMssg = document.getElementById('fm_extensions').innerHTML.replace('%s', extensions.join('\', \'').replace(/,([^,]*$)/, ' of$1'));
              this.addClassName(strictExtensionsInput, this.fieldErrorClassName);
              names +=  '\n' + (this.stripSuffixes ? strictExtensionsInput.name.replace(/_[^_\s]*$/ ,'') : strictExtensionsInput.name);
              break;
            }
          }
        }
      }

      return (errorMssg ? (this.showNames ? errorMssg + (this.stripUnderscores ? names.replace(/_/g, ' ') : names) : errorMssg) : false);
    },


    // get radio button or checkbox collection; optionally by name and in container
    // for checkboxes only the alphabetical start of the name is compared to include them in a collection (to exclude suffixed details in their name that make them unique)
    getInputCollection: function(name, type, container)
    {
      var
        input, allInputs = (container || document).getElementsByTagName('input'),
        collection = [];

      for (var i = 0; input = allInputs[i]; i++)
      {
        if ((name && (type == 'radio' ? input.name : input.name.replace(/(^[a-zA-Z]*).*/, '$1')) == name) || (!name && input.type == type))
        {
          collection.push(input);
        }
      }

      return collection;
    },


    // get radio button or checkbox collection value; optionally from input element collection, or collection by name whereby optionally the elements should be found in container
    // dependancies getInputCollection
    getInputCollectionValue: function(collection, type, container)
    {
      if (!collection || typeof(collection) == 'string') collection = getInputCollection(collection, type, container);

      for (var i = 0; i < collection.length; i++)
      {
        if (collection[i].checked)
        {
          return collection[i].value;
        }
      }
    },


    // get label by for value
    getLabel: function(forValue, container)
    {
      var labels = (container || document).getElementsByTagName('label');

      for (var i = 0; i < labels.length; i++)
      {
        if (labels[i].getAttribute('for') == forValue || (document.all && labels[i].getAttribute('htmlFor') == forValue))
        {
          return labels[i];
        }
      }
    },


    // standalone getElementsByClassName function from http://www.robertnyman.com/index.php?p=256
    getElementsByClassName: function(className, tag, container)
    {
      var
        testClass = new RegExp("(^|\\s)" + className + "(\\s|$)"),
        tag = tag || '*', container = container || document,
        elements = (tag == '*' && container.all)? container.all : container.getElementsByTagName(tag),
        returnElements = [], current, length = elements.length;

      for(var i=0; i<length; i++){
        current = elements[i];
        if(testClass.test(current.className)){
          returnElements.push(current);
        }
      }

      return returnElements;
    },


    // standalone addClassName from http://particletree.com/features/javascript-basics-for-prototyping/
    // dependancies: String.prototype.trim
    addClassName: function(element, className)
    {
      this.removeClassName(element, className);
      element.className = (element.className + " " + className).trim();
    },


    // standalone removeClassName from http://particletree.com/features/javascript-basics-for-prototyping/
    // dependancies: String.prototype.trim
    removeClassName: function(element, className)
    {
      element.className = element.className.replace(className, "").trim();
    },


    // check whether an element has a specific class
    hasClassName: function(element, name)
    {
      var i, list = element.className.split(" ");

      for(i = 0; i < list.length; i++)
        if(list[i] == name)
          return true;

      return false;
    },


    // better addEvent function from http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
    addEvent: function(element, type, fn)
    {
      if (element.addEventListener)
      {
        element.addEventListener(type, fn, false);
      }
      else if (element.attachEvent)
      {
        element['e' + type + fn] = fn;
        element[type + fn] = function() {
          element['e' + type + fn](window.event);
        };
        element.attachEvent('on' + type, element[type + fn]);
      }
    }


  };


  // string trim function from http://www.somacon.com/p355.php
  String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g,"");
  }

