// configurable options
var rowClassName       = 'formitem';
var rowHolderClassname = 'formitemholder';
var addressMarker      = 'address';
var pageClassName      = 'page';
var ttOnRequired       = false;
var validationCalledOnChange = false;

var classNames = new Array();
classNames['valid']    = '';
classNames['error']    = 'alert';
classNames['required'] = 'required';
classNames['required_one_of'] = 'required_one_of';

var imageNames = new Array();
imageNames['valid']    = '';
imageNames['error']    = '';
imageNames['required'] = '';
imageNames['required_one_of'] = '';

// general errormessages
var errorMessages = new Array();
errorMessages['char2']     = 'Er worden 1 of 2 (hoofd)letters verwacht.';
errorMessages['date']      = 'Ongeldige datum.';
errorMessages['year']      = 'Ongeldig jaartal.';
errorMessages['zipcode']   = 'Ongeldige postcode.';
errorMessages['telephone'] = 'Ongeldig telefoonnummer.';
errorMessages['float']     = 'Geen getal, getal verwacht.';
errorMessages['int']       = 'Geen heel getal, heel getal verwacht.';
errorMessages['intpos']    = 'Geen heel, positief getal, heel getal tussen 1 en 99 verwacht.';
errorMessages['email']     = 'Ongeldig e-mail adres.';
errorMessages['required']  = 'Dit is een verplicht veld.';
errorMessages['required_one_of']  = 'Vul minimaal 1 in.';
errorMessages['samevalue'] = 'De velden moeten dezelfde waarde hebben.';
errorMessages['beforetoday'] = 'Datum mag niet in de toekomst liggen.';
errorMessages['beforenextyear'] = 'Jaartal mag niet in de toekomst liggen.';

var unkownError = 'Er is een onbekende fout opgetreden.';
var unknownAddress = 'Het ingevoerde adres is niet geldig.';
var notEnoughAddressInfo = 'Vul alsjeblieft voldoende gegevens in.';

// check if the generalFunctions.js library is included
if (!getParentByTagName)
  alert('generalFunctions.js library is not included');

// init global vars
var pageIsValid     = true;
var addressValid    = true;
var addressChecked  = false;
var searchByzipcode = true; // search by zipcode or by steet/city
var submitting      = false; // is the submitt button clicked ?
var submitAfterCall = false;
var addressObj      = new Array();
var formName        = '';
var isInitForm      = false;
var currentItemRuleIndex = 0;

/**********************/
/*  The validator class
/**********************/
function validator()
{
  validator.formObj = null;

  validator.InitForm = function()
  {
    isInitForm = true;
    var forms = new Array();
    forms[0] = document;

    var parameters = validator.InitForm.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var setListners = true;
    if (parameters[0])
    {
      forms = validator.searchForm(parameters[0], true) //  return array with form's

      if (forms)
        validator.formObj = forms[forms.length-1];
      else
        return false;
    }

    if (parameters[1])
      setListners = (parameters[1]) ? true : false;

    addressValid    = true;
    pageIsValid     = true;

    if (setListners) {
      for (currentForm in forms)
        validator.setEventListners(forms[currentForm]);
    }
    for (currentForm in forms)
      validator.setInitialRelevanceAndRules(forms[currentForm]);

    isInitForm = false;
    return true;
  }

  validator.searchForm = function(startPoint)
  {
    var object = false;
    var parameters = validator.searchForm.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var returnArray = new Array();

    if (typeof(startPoint) == 'string' || typeof(startPoint) == 'number')
    {
      form = document.forms[startPoint];
      if (form && typeof(form) == "object")
        return form;
      object = document.getElementById(startPoint);
    } else if (typeof(startPoint) == "object")
      object = startPoint;

    if (object && typeof(object) == "object")
    {
      if (object.tagName && object.tagName.toUpperCase() != 'FORM' && object.form) // its a forminput element
      {
        if (parameters[1] && parameters[1] === true)
        {
          returnArray[0] = object.form;
          return  returnArray;
        }
        else
          return object.form;
      }

      if (object.tagName && object.tagName.toUpperCase() == 'FORM') // it is a form
      {
        if (parameters[1] && parameters[1] === true)
        {
          returnArray[0] = object;
          return  returnArray;
        }
        else
          return object;
      }

      if (object && object.getElementsByTagName)
      {
        var forms = object.getElementsByTagName('FORM')
        if (forms.length > 0)
        {
          if (parameters[1] && parameters[1] === true)
            return forms;
          else
            return forms[0]; // always return the first found form
        }
        else if (form = getParentByTagName(startPoint, 'FORM'))
        {
          if (parameters[1] && parameters[1] === true)
          {
            returnArray[0] = form;
            return  returnArray;
          }
          else
            return form;
        }
      }
    }
    return false;
  }

  validator.setEventListners = function(formObject)
  {
    if (typeof(formObject) != "object")
      return false;

  	var formElements = new Array();
    var fieldTypes = new Array('INPUT', 'TEXTAREA', 'SELECT');
    for (fieldType in fieldTypes)
    {
		  var inputs = formObject.getElementsByTagName(fieldTypes[fieldType]);
      for (var no=0; no < inputs.length; no++)
      {
        itemObj = inputs[no];

        if (itemObj)
        {
          var noValidation = itemObj.getAttribute('novalid');
          if (!noValidation)
          {
            if (itemObj.type && (itemObj.type == 'radio' || itemObj.type == 'checkbox'))
            {
              itemObj.onclick = eval('validator.validate');
              //addEvent(itemObj, 'click', eval('validator.validate'))
            }
            else
            {
              if (trigger = itemObj.getAttribute('validateOn'))
                eval('itemObj.' + trigger + ' = validator.validate;');
              else
                itemObj.onchange = eval('validator.validate');
              //addEvent(itemObj, 'change', eval('validator.validate'))
            }
          }
        }
		  }
    }
    return true;
  }

  validator.setInitialRelevanceAndRules = function(formObject)
  {
    if (typeof(formObject) != "object")
      return false;

  	var formElements = new Array();
    var fieldTypes   = new Array('INPUT', 'TEXTAREA', 'SELECT');
    for (fieldType in fieldTypes)
    {
		  var inputs = document.getElementsByTagName(fieldTypes[fieldType]);
		  for (var no=0;no < inputs.length; no++){
        validator.validate(inputs[no], true);
		  }
    }
    return true;
  }

  validator.submit = function(formname_Or_Clicked_Object, submitAfter)
  {
    // If true is given in the 2nd var, the address callback function will eventually fire the submit after he is done
    submitAfterCall = submitAfter;

    isInitForm      = false;

    // Stores the formname in a variable to be used in the submitting in the address call-back
    formName        = formname_Or_Clicked_Object;

    submiting = true; // used in multiselect so it won't validate the multiselect (again) when the page is submitted
    if (form = validator.searchForm(formname_Or_Clicked_Object))
    {
      this.formObj = form;
	    if (pageIsValid = validator.validatePage())
        return pageIsValid;
    }
    pageIsValid = false;
    if (onErrorFunction = validator.formObj.getAttribute('onerror'))
      eval(onErrorFunction);
    sizeLightBox();
    return false;
  }

  validator.validatePage = function(pageId)
  {
    validator.returnValue = true;

    if (validator.formObj.elements.length>0)
    {
      var check = true;
      for (var enr=0; enr < validator.formObj.elements.length; enr++)
      {
        var elem = validator.formObj.elements[enr];

        if (elem && (elem.nodeName=='FIELDSET') && elem.style.display && (elem.style.display=='none'))
        {
          check = false;
        }
        else if (elem.nodeName=='FIELDSET')
        {
          if (elem.id && elem.id.match('add_address'))
          {
            var fieldPrefix = elem.id;
            fieldPrefix = fieldPrefix.replace('add_address', '');

            if (!validator.checkAddress(elem.id, fieldPrefix))
              validator.returnValue = false;
          }

          elemPage = getParentByClass(elem, pageClassName);
          check = ((!pageId || (elemPage && (elemPage.id==pageId))) ? true : false);
        }
        else if (check)
        {
          if (elem && elem.address && elem.address.fields && (elem.address.fields.indexOf(",")!=-1))
          {
            if (!validator.checkAddress(elem))
              validator.returnValue = false;
          }
          else // not address
          {
            if (!getHiddenParentTillTagName(elem, 'div', '*', 'fieldset'))
            {
              if (!validator.checkRules(elem, false, true))
                validator.returnValue = false;
            }
          }
        }
      }
    }

    return validator.returnValue;
  }

  validator.getRow = function(item)
  {
    var parentNode = getParentByClass(item, rowClassName);
    if (parentNode)
        return parentNode;
    return item;
  }

  /**************
  /* change icon
  /**************/
  validator.changeIcon = function(itemObj, type, validation)
  {
    var item = itemObj;
    if (item.length>1 && item.type == 'radio')
      item = item[0];

    var className = '';
    if (classNames[type])
      className = classNames[type];
    else
      className = false;

    var imageName = '';
    if (imageNames[type])
      imageName = imageNames[type];
    else
      imageName = false;

    item = validator.getRow(item);
    var iconDiv   = getChildByClass(item,'div','form-icon');

    // remove the old image/div
    if (iconDiv && iconDiv.childNodes && iconDiv.childNodes[0]) iconDiv.removeChild(iconDiv.childNodes[0]);

    // remove old error classes
    removeClass(item, classNames['error']);

    if (type === false && validation === false) return true;

    currentErrorMessage = false;

    // In case the item has a custom error message it wil extra this one,
    // multiple messages for each rule can be defined by seperating them whit a pipe |
    if (itemObj.getAttribute && itemObj.getAttribute('errorMessage') && itemObj.getAttribute('errorMessage').split) {
      var customErrorMessages = itemObj.getAttribute('errorMessage').split("|");
      var customErrorMessage = customErrorMessages[currentItemRuleIndex];
      if (customErrorMessage != '' && customErrorMessage != null)
        currentErrorMessage = customErrorMessages[currentItemRuleIndex];
    }
    else if (itemObj.parentNode && itemObj.parentNode.getAttribute && itemObj.parentNode.getAttribute('errorMessage'))
      currentErrorMessage = itemObj.parentNode.getAttribute('errorMessage');

    if (imageName !== false && imageName != '')
    {
      // place the new image
      var newImage = document.createElement('img');
      newImage.src = imageName;

      if (type == 'required')
      {
        if (ttOnRequired)
        {
          newImage.alt    = (errorMessages['required']) ? errorMessages['required'] : 'Dit is een verplicht veld';
          newImage.title  = newImage.alt
          newImage.setAttribute('tt', newImage.title);
        }
      }
      else if (type != 'valid')
      {
        if (type == 'error' && validation == 'required')
          newImage.alt    = (errorMessages[validation]) ? errorMessages[validation] :((currentErrorMessage) ? currentErrorMessage :unkownError);
        else
          newImage.alt    = (currentErrorMessage) ? currentErrorMessage :((errorMessages[validation]) ? errorMessages[validation] :unkownError);
        newImage.title  = newImage.alt;
        newImage.setAttribute('tt', newImage.title);
      }
      var imageRef = iconDiv.appendChild(newImage);
    }
    else // use a div instead
    {
     if (type == 'required' || type == 'required_one_of')
     {
      if (ttOnRequired)
      {
        var newDiv = document.createElement('div');
        newDiv.setAttribute('tt', (errorMessages['required']) ? errorMessages['required'] : 'Dit is een verplicht veld');
        newDiv.setAttribute('tt_class', 'tt_required');
        addTT(newDiv);
        newDiv.style.height = '100%';
        newDiv.style.width = '100%';
        var divRef = iconDiv.appendChild(newDiv);
      }
     }
     else if (type != 'valid')
     {
        var newDiv = document.createElement('div');
        if (type == 'error' && validation == 'required')
          newDiv.setAttribute('tt', (errorMessages[validation]) ? errorMessages[validation] :((currentErrorMessage) ? currentErrorMessage : 'Dit is een verplicht veld'));
        else
          newDiv.setAttribute('tt', (currentErrorMessage) ? currentErrorMessage :((errorMessages[validation]) ? errorMessages[validation] : unkownError));
        newDiv.setAttribute('tt_class', 'tt_alert');
        addTT(newDiv);
        newDiv.style.height = '100%';
        newDiv.style.width = '100%';
        var divRef = iconDiv.appendChild(newDiv);
     }
    }


    // set the right class on the row
    //error class was already removed
    removeClass(item, classNames['required']);
    removeClass(item, classNames['required_one_of']);
    if (className != false)
      addClass(item, className);
  }

  validator.checkValue = function(element, value)
  {
    var elValue = validator.getValue(element);

    if (typeof(elValue) == "object")
    { // its an array
      for (var index in elValue)
        if (elValue[index] == value)
          return true;
    }
    else
    {
      if (elValue == value)
        return true;
    }
    return false;
  }

  validator.getElementType = function(element)
  {
    if (!element) return false;
    if (!typeof(element) == "object") return false;

    else if ((element.length>1 && element.tagName.toUpperCase() != 'SELECT') || element.type == 'radio')
    {
      return "radio";
    }
    else if (element.type == 'checkbox')
    {
      return 'checkbox';
    }
    else if (element.type == 'select-one')
    {
      return 'select-one';
    }
    else if (element.type == 'select-multiple')
    {
      return 'select-multiple';
    }
    else if (element.tagName.toUpperCase() == 'SELECT') // this will not work for a multiselect !!!!
    {
      return 'select';
    }
    else
      return element.tagName;
  }

  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.setValue = function(element, value)
  {
    if (!element) return false;
    if (!value) return false;

    if (typeof(element) == 'object')
    {
      if (element.name)
          elementName = element.name;
      if (!validator.formObj)
        validator.formObj = element.form;
    }
    else if ((typeof(element) == 'string'))
    {
      if (elementobj = validator.formObj.elements[element])
      {
        elementName = element;
      }
      else if (element = document.getElementById(element))
      {
        if (element.name)
          elementName = element.name;
        if (!validator.formObj)
          validator.formObj = element.form;
      }
      else
      {
        elementName = ''; // no such element !!!
      }
    }

    if (elemObj = validator.formObj.elements[elementName])
    {
      if (elemObj.length > 1 && elemObj.tagName.toUpperCase() != 'SELECT') // it's a radio
      {
        var radioLength = elemObj.length;
	      for (var i = 0; i < radioLength; i++)
        {
		      if (elemObj[i].value == value)
            elemObj[i].checked = true;
          else
            elemObj[i].checked = false;
	      }
        return true;
      }
      else if (elemObj.type == 'checkbox')
      {
        if (elemObj.value == value)
          elemObj.checked = true;
        else
          elemObj.checked = false;
        return true;
      }
      else if (elemObj.tagName.toUpperCase() == 'SELECT') // this will not work for a multiselect !!!!
      {
        for (var index=0; index < elemObj.options.length; index++)
        {
          if (elemObj.options[index].value == value)
            elemObj.options[index].selected = true;
          else
            elemObj.options[index].selected = false;
        }
        return true;
      } else
      {
        elemObj.value = value;
        return true;
      }
    }
    return false;
  }

  validator.checkRules = function(e)
  {
    var returnValue = true;
    var ruleAttr    = false;
    var valInvisfields = false;
    var pageValidation = false;
    var parameters = validator.checkRules.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var valInvisfields = (parameters[1]) ? true : false;
    var pageValidation = (parameters[2]) ? true : false;

    // don't validate invisable fields
    var parent = false;
    parent = getParentByClass(e, rowHolderClassname);

    if (parent && valInvisfields === false)
    {
      if (parent.style && parent.style.display && parent.style.display == 'none')
      {
        return returnValue;
      }
      else
      {
        parent = parent.parentNode;
        if (parent && parent.style && parent.style.display && parent.style.display == 'none')
          return returnValue;
      }
    }

    if (e.getAttribute) ruleAttr = e.getAttribute('rule');
		if (ruleAttr)
    {
      if (ruleAttr.indexOf(" ")!=-1)
      {
        var ruleAttributes = ruleAttr.split(" ");
      }
      else
      {
        var ruleAttributes = new Array();
        ruleAttributes[0] = ruleAttr;
      }
    }

   if (ruleAttr && ruleAttributes.length > 0)
    {
      var value = validator.getValue(e);
      var isRequiredField = false;

      var itemObj = e;

      // check if we should initialize this field
      for (i=0; i<ruleAttributes.length; i++)
      {
        var type = ruleAttributes[i];
        if (type == 'noinit' && isInitForm)
          return true;
      }

      // remove old icon's
      validator.changeIcon(itemObj, false, false);

      // check the attributes
      for (i=0; i<ruleAttributes.length; i++)
      {
        // Keeps track of wich rule is handled for use in the error messages
        currentItemRuleIndex = i;

        //check if field validates by provided rule
        var type = ruleAttributes[i];

        if (type.indexOf("/^")!=-1 && type.indexOf("$/")!=-1) // een regex !!
        {
          try {
            var regEx = eval(type);
            var result = (validator.validation_regEx(regEx, value)) ? 'valid' : 'error';
            validator.changeIcon(((itemObj.length>1) ? itemObj[0] : itemObj), result, type);
            if (result == 'error')
              returnValue = false;
          } catch (err) {
            // geen geldige regex > doe niks
          }
        }
        else if (type.indexOf("|")==-1) // simple rules
        {
          if (value && value.length>0)
          {
            try{
              var isValid  = eval("validator.validation_" + type + "('" + escape(value) + "')")
              var result = (isValid) ? 'valid' : 'error';
            } catch (err){
              var result = 'valid';
            }
            validator.changeIcon(((itemObj.length>1) ? itemObj[0] : itemObj),result , type)
            if (isValid === false)
              returnValue = isValid;
          }
          else if (type=='required')
          {
            if (pageValidation)
              validator.changeIcon(((itemObj.length>1) ? itemObj[0] : itemObj),'error', type);
            else
              validator.changeIcon(((itemObj.length>1) ? itemObj[0] : itemObj),type, type);

            isRequiredField = true;
            returnValue = false;
            return returnValue;
          }
        }
        else // advanced checks
        {
          var callArguments = type.split("|");
          var value2 = (pageValidation) ? 'true' : false;
          value2 += ", '" + e.id + "'";

          for (index = 1; index < callArguments.length; index++)
            value2 += ", '" + callArguments[index] + "'";

          try
          {
            result = eval("validator.validation_" + callArguments[0] + "(" + value2 + ")");
          } catch (err){
            var result = true;
          }
          // the function has to set the icon's by itself !!!!
          if (result === false) returnValue = result;
        }
      }
    }

    return returnValue;
  }

  validator.setRelevances = function(e)
  {
    var releAttr = false;
    if (e.getAttribute) releAttr = e.getAttribute('relevance');

		if (releAttr)
    {
      if (releAttr.indexOf(" ")!=-1)
      {
        var releAttributes = releAttr.split(" ");
      }
      else
      {
        var releAttributes = new Array();
        releAttributes[0] = releAttr;
      }
    }

    if (releAttr && releAttributes.length > 0)
    {
      //var value = validator.getValue(e);

      for (i=0; i<releAttributes.length; i++)
      {
        //update relevant fields
        var relevance = releAttributes[i].split(",");
        if (elem=document.getElementById(relevance[1]))
        {

          if (validator.checkValue(e, relevance[0]))
          {
            elem.style.display = 'block';
            if (!elem.rel)
              elem.rel = new Array();
            elem.rel[relevance[0]] = 'block';
          } else
          {
            var hideElem = true;
            if (!elem.rel)
              elem.rel = new Array();
            elem.rel[relevance[0]] = null;
            for (rel in elem.rel)
              if (elem.rel[rel] == 'block') hideElem = false;
            if (hideElem)
              elem.style.display = 'none';
          }
          sizeLightBox();
        }
        else if (elems=document.getElementsByName(relevance[1]))
        {

          for (j=0; j<elems.length; j++)
          {
            elems[j].style.display = ((validator.checkValue(e, relevance[0])) ? 'block' : 'none');
          }
        }
      }
    }
  }

  validator.checkAddress = function(elemId, fieldPrefix)
  {
    if (!fieldPrefix)
      fieldPrefix = '';

    e = document.getElementById(elemId);

    if (e)
    {
      var fieldsAttr = e.getAttribute('fields');

      addressObj[fieldPrefix] = new Array();
      addressObj[fieldPrefix].responseField = e.getAttribute('responsefield');
      addressObj[fieldPrefix].fields        = addressObj[fieldPrefix].responseField + "," + fieldsAttr;
      addressObj[fieldPrefix].errorField    = e.getAttribute('error_field');
      addressObj[fieldPrefix].validateBy    = e.getAttribute('validate_by');
      addressObj[fieldPrefix].fieldPrefix   = fieldPrefix;

      var addressArray = addressObj[fieldPrefix].fields.split(",");

      if (addressObj[fieldPrefix].fields && (addressObj[fieldPrefix].fields.indexOf(",")!=-1))
      {
        validator.formObj = e.form;

        var zipcode     = validator.getValue(validator.formObj.elements[addressArray[1]]);
        var housenumber = validator.getValue(validator.formObj.elements[addressArray[2]]);
        var addition    = validator.getValue(validator.formObj.elements[addressArray[3]]);
        var street      = validator.getValue(validator.formObj.elements[addressArray[4]]);
        var city        = validator.getValue(validator.formObj.elements[addressArray[5]]);
        var country     = validator.getValue(validator.formObj.elements[addressArray[6]]);
        var parPrefix   = fieldPrefix + 'address_input_';

        var missingInfo = false;

        if (validateByField = document.getElementById(addressObj[fieldPrefix].validateBy))
          searchByzipcode = (validator.getValue(validateByField) == 'PC') ? true : false;

        var searchMode = validator.getValue(validateByField);

        if (country && country != 'NL')
        {
          var pars = parPrefix + "country=" + country +
                     "&" + parPrefix + "zipcode=" + zipcode +
                     "&" + parPrefix + "street=" + street +
                     "&" + parPrefix + "city=" + city +
                     "&" + parPrefix + "housenumber=" + housenumber +
                     "&" + parPrefix + "housenraddition=" + addition;
        }
        else if (searchByzipcode)
        {
          if (zipcode.trim() == '' || housenumber.trim() == '')
            missingInfo = true;
          var pars = parPrefix + "zipcode=" + zipcode +
                     "&" + parPrefix + "housenumber=" + housenumber +
                     "&" + parPrefix + "housenraddition=" + addition;
        }
        else if (!searchByzipcode)
        {
          if (street.trim() == '' || housenumber.trim() == '' || city.trim() == '')
            missingInfo = true;
          var pars = parPrefix + "street=" + street +
                     "&" + parPrefix + "city=" + city +
                     "&" + parPrefix + "housenumber=" + housenumber +
                     "&" + parPrefix + "housenraddition=" + addition;
        }

        pars += '&' + parPrefix + 'search=' + searchMode;
        pars += '&fieldPrefix=' + fieldPrefix;

        if (missingInfo)
        {
          d = document.getElementById(addressObj[fieldPrefix].errorField);

          if (d && addressObj[fieldPrefix].errorField)
          {
            d.innerHTML = '<p class="error">'+ notEnoughAddressInfo +'</p>';

            if (a = document.getElementById(fieldPrefix + 'addresserror'))
              a.style.display = 'block';
          }
          else
          {
            window.alert(notEnoughAddressInfo);
          }

          return false;
        }

        d = document.getElementById(addressObj[fieldPrefix].errorField);

        if (d && addressObj[fieldPrefix].errorField)
        {
          // Added so you want see a half error bar when he is processing.
          if (g = document.getElementById(fieldPrefix + 'addresserror'))
            g.style.display = 'none';

          d.innerHTML = '';
        }

        loadingLightBox(true);

        remoteRequest('remote/address_call.php', pars, 'validator.showAddressResponse', true); // synchronic call !!

        if (validator.returnValue === false)
          pageIsValid =false;

      }
    }

    return true;
  }

  // Address searcher callback function
  validator.showAddressResponse = function()
  {
    var fieldPrefix     = '';

    if (http_request.readyState == 4 && addressObj)
    {
      if (http_request.status == 200 && (http_request.responseText.indexOf('<address>')!=-1) && validator.formObj)
      {
        var responseText = http_request.responseText.replace("<address>","").replace("</address>","");
        var address = responseText.split("|");

        var responseAddress = address[0] + " " + address[1] + " " + address[2] + "<br />" +
                              address[3] + "<br />" +
                              address[4] + "<br /><br />" +
                              address[9] + "<br />" +
                              address[8] + "<br />" +
                              address[6];

        var fieldPrefix      = address[10];

        if (addressObj[fieldPrefix])
        {
          var addressFields = (addressObj[fieldPrefix].fields) ? addressObj[fieldPrefix].fields.split(",") : new Array();

          if (responseElem = document.getElementById(addressFields[0]))
          {
            responseElem.innerHTML      = responseAddress;
            responseElem.style.display  = 'block';

            if (responseElem.parentNode)
             responseElem.parentNode.parentNode.style.display = 'block';

            // Zipcode element
            var zipcodeElem             = validator.formObj.elements[addressFields[1]];
            zipcodeElem.value           = address[3];
            validator.validate(zipcodeElem, true);

            // Housenumber element
            var housenumberElem         = validator.formObj.elements[addressFields[2]];
            housenumberElem.value       = address[1];
            validator.validate(housenumberElem, true);

            // Housenumberaddition element
            var additionElem            = validator.formObj.elements[addressFields[3]];
            additionElem.value          = address[2];

            // Street element
            var streetElem              = validator.formObj.elements[addressFields[4]];

            if (streetElem)
              streetElem.value = address[0];

            validator.validate(streetElem, true);

            // City element
            var cityElem                = validator.formObj.elements[addressFields[5]];

            if (cityElem)
              cityElem.value = address[4];

            validator.validate(cityElem, true);

            validator.setValue(addressFields[6], address[7]);

            // Municipality element
            var muniElem = validator.formObj.elements[addressFields[7]];

            if (muniElem)
              muniElem.value = address[5];

            // State element
            var stateElem = validator.formObj.elements[addressFields[8]];

            if (stateElem)
              stateElem.value = address[6];

            var inputFields = document.getElementById(fieldPrefix + 'addr_fields');
            inputFields.style.display = 'none';

            var errorField = addressObj[fieldPrefix].errorField;

            if (d = document.getElementById(errorField))
              d.innerHTML = '';

            if (a = document.getElementById(fieldPrefix + 'addresserror'))
              a.style.display = 'none';

            addressValid = true;
          }
        }

      }
      else
      {
        validator.returnValue         = false;

        if (addressValid)
          addressValid = false;

        var errorField = addressObj[fieldPrefix].errorField;

        if (d = document.getElementById(errorField))
        {
          d.innerHTML       = '<p class="error">' + unknownAddress + '</p>';

          if (a = document.getElementById(fieldPrefix + 'addresserror'))
            a.style.display = 'block';

        }
        else
        {
          window.alert(unknownAddress);
        }
      }
    }

    loadingLightBox(false);

    // This is a workaround for the synchronious ajax call, wich doesn't work for FireFox
    if (submitAfterCall && addressValid && pageIsValid && formName != '')
    {
      submitAfterCall       = false;
      document.forms[formName].submit();
    }

  }

  validator.getHiddenAddressField = function()
  {
    var parameters = validator.getHiddenAddressField.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    if (parameters[0] && parameters[0].split)
    {
      var fieldParts      = parameters[0].split('_');
      var hiddenFieldName = false;

      if (fieldParts[0] && fieldParts[2])
        hiddenFieldName = fieldParts[0] + '_' + addressMarker + '[' + fieldParts[2] + ']';

      if (hiddenFieldName)
      {
        if (document.getElementById(hiddenFieldName))
          return document.getElementById(hiddenFieldName);
        if (validator.formObj.elements[hiddenFieldName])
          return validator.formObj.elements[hiddenFieldName];
      }
    }
    return false;
  }

  // possible parameters : validator.validate(elementID, validateInvisableFields)
  validator.validate = function(elemId)
  {
    validationCalledOnChange = false;
    if (typeof(elemId) == 'object' && elemId.getAttribute)
    {
      e = elemId;
    }
    else if (typeof(elemId) == 'string' && document.getElementById(elemId))
    {
      e = document.getElementById(elemId);
    }
    else
    {
      e = this;
      validationCalledOnChange = true;
    }

    if (e.tagName && e.tagName.toUpperCase() == 'OPTION')
      e = e.parentNode; // its a (multi)select object !!

    var parameters = validator.validate.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var valInvisfields = (parameters[1]) ? true : false;

    if (valInvisfields)
      validator.checkRules(e, true);
    else
      validator.checkRules(e);
    validator.setRelevances(e);
  }

  // ------------ validation functions ------------ //

  validator.validation_samevalue = function ()
  {
    var itemObj = new Array();
    var parameters = validator.validation_samevalue.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    if (parameters.length != 3)
      return false;

    var pageValidation = parameters[0];

    for (index = 1; index < parameters.length; index++)
    {
      if (typeof(parameters[index]) != "object")
      {
        itemObj[index] = document.getElementById(parameters[index]);
        if (typeof(itemObj[index]) != "object")
          return false;
      }
    }

    if (itemObj[1].value != '' && itemObj[2].value != '' && itemObj[1].value != itemObj[2].value)
    {
      validator.changeIcon(itemObj[1], 'error', 'samevalue');
      validator.changeIcon(itemObj[2], 'error', 'samevalue');
      return false;
    }
    else
    {
      if (itemObj[1].value == '')
        validator.changeIcon(itemObj[1], (pageValidation) ? 'error' : 'required', 'required');
      else
        validator.changeIcon(itemObj[1], 'valid', 'required');

      if (itemObj[2].value == '')
        validator.changeIcon(itemObj[2], (pageValidation) ? 'error' : 'required', 'required');
      else
        validator.changeIcon(itemObj[2], 'valid', 'required');
    }
    return true;
  }

  validator.validation_regEx = function (regex, value)
  {
    value = unescape(value);
    if (regex.test)
      return regex.test(value);
    else
      return false;
  }


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

  // this function can check if the value of the element is higer (or lower) then the value of another field
  validator.validation_higher_lower_then = function()
  {
    var valid          = false;
    var action         = false;
    var result         = true;
    var checkElValue   = 0;
    var otherElValue   = 0;
    var higherLower    = 'higher';
    var callBack       = null;
    var parameters     = validator.validation_higher_lower_then.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var pageValidation = parameters[0];
    var idFieldToCheck = parameters[1];
    var xtraParameters = parameters[2];

    if (xtraParameters.length > 0 && xtraParameters.split)
    {
      xtraParametersArr = xtraParameters.split(',');
      var idOtherField  = xtraParametersArr[0];
      if (xtraParametersArr[1])
        higherLower = xtraParametersArr[1];
      if (xtraParametersArr[2])
        callBack = xtraParametersArr[2];
    }

    if (checkEl = document.getElementById(idFieldToCheck))
      checkElValue   = validator.getValue(checkEl);
    if (otherEl = document.getElementById(idOtherField))
      otherElValue   = validator.getValue(otherEl);

    checkElValue = string_to_float(checkElValue);
    otherElValue = string_to_float(otherElValue);

    if (!isNaN(checkElValue) && !isNaN(otherElValue))
    {
      if (callBack)
      {
        var requestObject            = new Object();
        requestObject.pageValidation = pageValidation;
        requestObject.checkEl        = checkEl;
        requestObject.otherEl        = otherEl;
        requestObject.checkElValue   = checkElValue;
        requestObject.otherElValue   = otherElValue;
        requestObject.higherLower    = higherLower;
        requestObject.valid          = true;
      }

      if (higherLower == 'higher')
      {
        // checkElValue should be higher then otherElValue
        // if not, do the callback
        if (otherElValue >= checkElValue)
        {
          if (callBack)
          {
            requestObject.valid = false;
            action = callBack + '(requestObject);';
          }
          else
            result = false;
        }
      }
      else
      {
        // checkElValue should be lower then otherElValue
        // if not, do the callback
        if (otherElValue <= checkElValue)
        {
          if (callBack)
          {
            requestObject.valid = false;
            action = callBack + '(requestObject)';
          }
          else
            result = false;
        }
      }
    }

    // do we need to call the callback function
    if (callBack && action)
    {
      try
      {
        //  do the action, if the callback function exist
        eval('if (' + callBack + ') ' + action + ';');
      }
      catch (err)
      {
        // do nothing !!
      }
    }
    return result;
  }

  // This function allows you to put a required relevance on a group of items.
  // Sample rule: 'required_one_of|phonenr,mobilephonenr,workphonenr telephone'
  validator.validation_required_one_of = function()
  {
    var parameters     = validator.validation_required_one_of.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();
    var pageValidation = parameters[0];
    var idFieldToCheck = parameters[1];
    var checkFields    = parameters[2];
    var valid          = false;
    var i              = 0;
    var j              = 0;
    var elems          = new Array();
    var elem           = '';
    var valueFields    = new Array();

    if (checkFields == '' || !checkFields.split)
      return valid;

    valueFields        = checkFields.split(",");

    for (i = 0; i < valueFields.length; i++)
    {
      if (elem = document.getElementById(valueFields[i]))
      {
        elems[i]       = elem;

        if (validator.getValue(elems[i]) != '')
          valid        = true;
      }
    }


    for (j = 0; j < elems.length; j++)
    {
      if (pageValidation)
      {
        if (!valid) {
          validator.changeIcon(elems[j], 'error', 'required_one_of');
          elems[j].pageValError = true;
        }

      }
      else
      {
        if (!valid)
          validator.changeIcon(elems[j], 'required_one_of', 'required_one_of');
        else {
          // Set valid unless the item is invalid to other rule
          var item = validator.getRow(elems[j]);
          if (!hasClass(item, classNames['error']) || elems[j].pageValError) {
            elems[j].pageValError = false;
            validator.changeIcon(elems[j], 'valid', 'required_one_of');
          }
        }
      }
    }

    return valid;
  }

  // This function allows you to calculate 2 or more fields.
  // Sample rule: 'required int calculate_fields|livk_achtertuin_oppervlakte:*;livk_achtertuin_diepte,livk_achtertuin_breedte'
  validator.validation_calculate_fields = function()
  {
    var parameters     = validator.validation_calculate_fields.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();
    var pageValidation = parameters[0];
    var idFieldToCheck = parameters[1];
    var checkFields    = parameters[2];
    var valid          = true;

    // Make sure the calculation only takes place in case one of the input values is being changed.
    if (!pageValidation && !isInitForm)
    {
      var i               = 0;
      var j               = 0;
      var elems           = new Array();
      var valueFields     = new Array();
      var tempArray       = new Array();
      var elem            = '';
      var elemValue       = '';
      var calculatedValue = '';
      var outputFieldId   = '';
      var operator        = '';

      if (checkFields == '' || !checkFields.split)
        return valid;

      tempArray           = checkFields.split(":");
      outputFieldId       = tempArray[0];

      tempArray           = tempArray[1].split(";");
      operator            = tempArray[0];

      valueFields         = tempArray[1].split(",");


      if (outputFieldId == '' || operator == '' || valueFields == '')
        return valid;


      for (i = 0; i < valueFields.length; i++)
      {
        if (elem = document.getElementById(valueFields[i]))
        {
          elems[i]          = elem;
          elemValue         = validator.getValue(elems[i]);

          if (elemValue == '')
            return valid;
          else
          {
            if (!isNaN(elemValue))
            {
              elemValue     = parseFloat(elemValue);
              if (calculatedValue == '')
                calculatedValue = elemValue;
              else {
                switch (operator)
                {
                  case '+': calculatedValue += elemValue; break;
                  case '-': calculatedValue -= elemValue; break;
                  case '*': calculatedValue *= elemValue; break;
                  case '/': calculatedValue /= elemValue; break;
                  default: calculatedValue = 0; break;
                }
              }
            }
            else
              return valid;
          }
        }
      }

      if (calculatedValue > 0) {
        if (outputElem = document.getElementById(outputFieldId)) {
          outputElem.value  = calculatedValue;
        }
      }
    }

    return valid;
  }

  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) ? true : false);
    }
  }

  validator.validation_char2 = function(value)
  {
    value = unescape(value);
    if (value.length > 0)
    {
      var filter = /^[a-zA-Z]{1,2}$/;
      return filter.test(value);
    }
  }

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

  validator.validation_intpos = function(value)
  {
    value = unescape(value);
    if (value.length>0)
    {
      var filter = /^([1-9]\d*)$/;
      return filter.test(value);
    }
  }

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

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

  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);
    }
  }

  validator.validation_year = function(value)
  {
    value = unescape(value);
    if (value.length>0)
    {
	    var filter  = /^[12]{1}[0-9]{3}$/;
      return (filter.test(value) ? true : false);
    }
  }

  validator.validation_date = function(value)
  {
    value = unescape(value);
    if (value.length>0)
    {
	    var filter  = /^[0123]{1}[0-9]{1}[-/]{1}[01]?[0-9]{1}[-/]{1}[12]{1}[0-9]{3}$/;
      //return (filter.test(value) ? true : false); // also check if date exists !!!
      if (filter.test(value))
      {
        myRegExp = new RegExp("/", "g");
        value = value.replace(myRegExp, '-');
        if (Date.isValid(value, 'dd-MM-yyyy'))
          return true;
      }
      return false
    }
  }

  validator.validation_beforetoday = function(value)
  {
    if (validator.validation_date(value))
    {
      value = unescape(value);
      myRegExp = new RegExp("/", "g");
      value = value.replace(myRegExp, '-');
      if (new Date().isAfter(Date.parseString(value,'dd-MM-yyyy')))
        return true;
    }
    return false;
  }

  validator.validation_beforenextyear = function(value)
  {
    value = unescape(value);
    if (validator.validation_year(value))
    {
      if (new Date().isAfter(Date.parseString(value,'yyyy')))
        return true;
    }
    return false;
  }

  // general function to call extra functions on a onBlur (onChange??)
  // rule="call|functionToCall|xtraparameters"
  validator.validation_call = function()
  {

    var xtraParameters = '';
    var functionTocall = '';
    var parameters     = validator.validation_call.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();

    var pageValidation = parameters[0];
    var calledFrom     = parameters[1];
    if (parameters[2])
      functionTocall = parameters[2];
    if (parameters[3])
      xtraParameters   = parameters[3];

    if (functionTocall)
    {
      var requestObject            = new Object();
      requestObject.pageValidation = pageValidation;
      requestObject.calledFrom     = calledFrom;
      requestObject.xtraParameters = xtraParameters;
      var action                   = functionTocall + '(requestObject);';
      try
      {
        // do the action, if the function to call exist
        eval('if (' + functionTocall + ') ' + action + ';');
      }
      catch (err)
      {
        // do nothing !!
      }
    }
  }

  validator.validation_showwhenfilled = function()
  {
    var itemObjList    = new Array();
    var parameters     = validator.validation_showwhenfilled.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();
    var pageValidation = parameters[0];
    var idFieldToCheck = parameters[1];
    var newindex       = 0;

    for (index = 2; index < parameters.length; index++)
    {
      itemObjList[newindex] = parameters[index];
      newindex++
    }

    var elementFieldToCheck = document.getElementById(idFieldToCheck);
    var elementFieldToCheckRow = validator.getRow(elementFieldToCheck);
    var fieldInError = hasClass(elementFieldToCheckRow, classNames['error']);

    if (elementFieldToCheck)
      var value = validator.getValue(elementFieldToCheck);
    else
      var value = '';

    for (itemObjID in itemObjList)
    {
      elementToSet  = document.getElementById(itemObjList[itemObjID]);
      if (!(fieldInError) && elementToSet && value.length > 0)
        elementToSet.style.display = 'block';
      else if ((elementToSet && value.length < 1) || (fieldInError))
        elementToSet.style.display = 'none';
    }
    return true;
  }

// ---------------- BEGIN old functionality -------------------
  validator.moveNextPage = function(formname_Or_Clicked_Object)
  {
    var form = validator.searchForm(formname_Or_Clicked_Object);
    var pages = getElementsByClassName(form,'div','page' );

    for (var page=0; page < pages.length; page++)
    {
      if ((getCssStyle(pages[page],'display')=='block') && pages[page + 1])
      {
        if (validator.validatePage(pages[page].id))
        {
          pageIsValid = true;
          pages[page].style.display = 'none';
          pages[page + 1].style.display = 'block';
        } else pageIsValid = false;
        break;
      }
    }

  }

  validator.movePrevPage = function(formname_Or_Clicked_Object)
  {
    var form = validator.searchForm(formname_Or_Clicked_Object);
    var pages = getElementsByClassName(form,'div','page' );

    for (var page=0; page < pages.length; page++)
    {
      if ((getCssStyle(pages[page],'display')=='block') && pages[page - 1])
      {
        pageIsValid = true;
        pages[page].style.display = 'none';
        pages[page - 1].style.display = 'block';
        break;
      }
    }
  }

  validator.moveToPage = function(pageID)
  {
    var parameters = validator.moveToPage.arguments;
    if (!parameters || typeof(parameters) != "object")
      parameters = new Array();
    if (parameters[1])
       form = validator.searchForm(parameters[1]);
    if ((!form) || (!form.getElementsByTagName))
      form = validator.formObj;

    var pages = getElementsByClassName(form,'div','page' );
    var page  = document.getElementById(pageID);

    if (page)
    {
      // validate the current active page
      for (var pageNr=0; pageNr < pages.length; pageNr++)
      {
        if ((getCssStyle(pages[pageNr],'display')=='block'))
        {
          validator.formObj = getParentByTagName(pages[pageNr], 'FORM');
          if (validator.validatePage(pages[pageNr].id))
          {
            pageIsValid = true;
          }
          else
          {
            pageIsValid = false;
            return false;
          }
        }
      }

      for (var pageNr=0; pageNr < pages.length; pageNr++)
      {
        if (pages[pageNr].id == pageID)
          pages[pageNr].style.display = 'block';
        else
          pages[pageNr].style.display = 'none';
      }
    }
  }
  // END old functionality
}