var fV = {
  init: function() {
	var j = 0;	  
    for (var i in validationSet) {
      if (document.getElementsByName(i)) {
        var formField = document.getElementsByName(i);
		for (var k = 0; k < formField.length; k++) {
		  if (typeof formField[k] != 'undefined') {
		    // if the form has an id already use it otherwise give it one
		    formField[k].form.id = (formField[k].form.id == null || formField[k].form.id == '') ? 'val_form_' + j++ : formField[k].form.id;
		    // user wants alert error message
		    if (!/\b ?noerrorspan\b/.test(formField[k].className)) {
		      // bind a span to each form field
		      var errorSpan = document.createElement('span');
		      errorSpan.className = 'errormessage';
		      // give it the id of 'error_' + the current field's name
		      errorSpan.id = formField[k].type.match(/radio|checkbox/) 
			  	? 'error_' + formField[k].name : 'error_' + formField[k].id;
			  // append the error span to the field's parent
		      formField[k].parentNode.appendChild(errorSpan);
		    }
			// add event handler
			addEvent(formField[k], 'blur', fV.checkValid, false);
            if (!formField[k].form.validateSubmit) {
              addEvent(formField[k].form, 'submit', fV.checkValidSubmit, false);
              formField[k].form.onsubmit = fV.checkSubmit; // Safari
              formField[k].form.validateSubmit = true;
            }
		  }
		}
      }
    }
  },

  checkValidSubmit: function(e) {
    var frm = window.event ? window.event.srcElement : e ? e.target : null;
    if (!frm) return;
    var errText = [];
	var fieldErr = [];
	var errsAdded = '';
	
    for (var i = 0; i < frm.elements.length; i++) {
      if (frm.elements[i].name && validationSet[frm.elements[i].name]) {

        var failedE = fV.handleValidity(frm.elements[i]);		
        var errDisplay = frm.elements[i].type.match(/radio|checkbox/) 
				? document.getElementById('error_' + frm.elements[i].name) : document.getElementById('error_' + frm.elements[i].id);
	
		if (failedE && errDisplay) {
		  errDisplay.innerHTML = validationSet[failedE.name]['error'];
		}
	
		if (!failedE && errDisplay) {
		  errDisplay.innerHTML = '';
		}

        if (failedE) {
		  var labels = document.getElementsByTagName('label');
          for (var j = 0; j < labels.length; j++) {
            if (labels[j].htmlFor == failedE.id) {
			  // if there is multiple of the current field
			  if (frm.elements[frm.elements[i].name].length > 1) {
				// if the current field's name has already been added and break
				if (errsAdded.indexOf(frm.elements[i].name) > -1) {
				  break;
				} else {
				  // get the field's name once
				  if (frm.elements[i].type.match(/radio|checkbox|select-one|select-multiple/)) {
		    		errText[errText.length] = frm.elements[i].name;
					errsAdded += frm.elements[i].name + '\n';
					break;
				  }		
				  if (frm.elements[i].type.match(/text|textarea|password|file/)) {
		    		// add the field's id so it can be focused
					fieldErr[fieldErr.length] = frm.elements[i].id;
					errsAdded += frm.elements[i].name + '\n';
				  }	
				  // get the field's corresponding label's value
				  errText[errText.length] = labels[j].firstChild.nodeValue.replace(/[:;-]/, '');
				  break;  
				}
			  } else {
				// there is only one of the current field
				if (frm.elements[i].type.match(/text|textarea|password|file/)) {
		    		// add the field's id so it can be focused
					fieldErr[fieldErr.length] = frm.elements[i].id;
				}
				// get the field's corresponding label's value
		    	errText[errText.length] = labels[j].firstChild.nodeValue.replace(/[:;-]/, '');
				break;
			  }
			// no label can be found matching the current id
            } else {
			    if (errsAdded.indexOf(frm.elements[i].name) > -1) {
				  break;
			    } else {
				  if (frm.elements[i].type.match(/text|textarea|password|file/)) {
		    		// add the field's id so it can be focused
					fieldErr[fieldErr.length] = frm.elements[i].id;
				  }					
				  errText[errText.length] = frm.elements[i].name;
				  errsAdded += frm.elements[i].name + '\n';
				  break;
			    }
			}
          }
        }
      }  // end 'if'
    } // end 'for'

    if (errText.length > 0) {
	  // get the current form's id + vm (validation message)
	  if (document.getElementById('vm' + frm.id)) {
		 frm.removeChild(document.getElementById('vm' + frm.id)); 
	  }
	  var fixMsg = 'The following fields contain errors or are ' +
	  			   'incomplete please fix these and resubmit:';
	  var wrap = document.createElement('div');
	  var ul = document.createElement('ul');
	  var span = document.createElement('span');
	  // set up the full message to display
  	  wrap.id = 'vm' + frm.id;
	  wrap.className = 'validationmessage';
	  wrap.style.display = 'block';
	  wrap.appendChild(span);
	  wrap.appendChild(ul);
	  frm.insertBefore(wrap,frm.firstChild);
	  span.appendChild(document.createTextNode(fixMsg));
	  // add each error bullet
	  for (var i=0; i<errText.length; i++) {
		  var li = document.createElement('li');
		  li.appendChild(document.createTextNode(errText[i]));
		  ul.appendChild(li);
	  }
	  // add focus to the first error field and cancel form submission
	  if (fieldErr.length) {
	    document.getElementById(fieldErr[0]).focus();
	  }
      frm.submitAllowed = false;
	  // prevent default actions
      if (e && e.stopPropagation && e.preventDefault) {
        e.stopPropagation();
        e.preventDefault();
      }
      if (window.event) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
        return false;
      }
    } else {
      frm.submitAllowed = true;
    }
  },

  checkSubmit: function() {
    if (this.attachEvent) {return true;}
    return this.submitAllowed;
  },
  
  checkValid: function(e) {
    var target = window.event ? window.event.srcElement : e ? e.target : null;
    if (!target) return;

    var failedE = fV.handleValidity(target);
    var errDisplay = target.type.match(/radio|checkbox/) 
			? document.getElementById('error_' + target.name) : document.getElementById('error_' + target.id);

    if (failedE && errDisplay) {
      errDisplay.innerHTML = validationSet[failedE.name]['error'];
    }
    if (failedE && !errDisplay) {
      alert(validationSet[failedE.name]['error']);
    }
    if (!failedE && errDisplay) {
      errDisplay.innerHTML = '';
    }
  },

  handleValidity: function(field) {
	var errorClass = field.className.replace(/\b ?field\b/, 'fielderror');
	var normalClass = field.className.replace(/\b ?fielderror\b/, 'field');
	switch (field.type) {
		case 'select-one':
			if (validationSet[field.name]['required'] != null && 
				validationSet[field.name]['required'] == false && field.value == '') {
			  field.className = normalClass;
			  return null;
			} else if (field.selectedIndex == -1 || field.options[field.selectedIndex].value == ''){
				field.className = errorClass;
				return field;
			} else {
			    field.className = normalClass;
			    return null;
			}
		case 'select-multiple':
			if (field.selectedIndex == -1){
				field.className = errorClass;
				return field;
			} else {
			    field.className = normalClass;
				return null;
			}			
		case 'text':
		case 'textarea':
		case 'password':
		case 'file':
			if (validationSet[field.name]['required'] != null && 
				validationSet[field.name]['required'] == false && field.value == '') {
			  field.className = normalClass;
			  return null;
			} else if (!field.value.match(validationSet[field.name]['regexp'])) {
			  field.className = errorClass;
			  return field;
			} else {
			  field.className = normalClass;
			  return null;
			}
		case 'radio':
		case 'checkbox':
			var checked = false;
			if (field.form.elements[field.name].length) {
				for (var j = 0; j < field.form.elements[field.name].length; j++) {
					if (field.form.elements[field.name][j].checked) {
						checked = true;
					}
				}
			} else {
				checked = field.checked;	
			}
			if (!checked){
				return field;
			} else {
			  	return null;
			}
		default:
			return null;
	}
  }
}

addLoadListener(fV.init);