/*
 A script to perform validation on HBS emailForms

 VERSION 1.0

 Documentation is available at
  http://webstage.hbs.edu/admin/forms/documentation.html

 Functions
  Validation.check(form) - Performs the validation

 Tested in
   - Firefox 1.0
   - Netscape 6.23
   - Netscape 7
   - IE 6
   - IE 5.5
   - IE 5
   - Opera 7.2
   - Safari 1.03
   - MAC IE 5.2

 Degrades in
   - Opera 6
   - NS 4.7

*/

Validation = new Object();

function Validation_get_required_fields(form) {
   required = form.r
   var req_fields = new Array();
   var c = 0;
   req_fields['e'] = c++;
   if (form.f) {req_fields['f'] = c++;}

   if (!required) {
	  // no required fields
   } else if (!required.value) { //(isNodeList(required)) {
      for (var x=0;x<required.length;x++) {
         req_fields[required[x].value] = c++;
      }
   } else {
      req_fields[required.value] = c++;
   }



   return req_fields;
}

function Validation_display_name(name,options) {
   if (options['labels'] && options['labels'][name]) return options['labels'][name]
   if (options['labels-function']) return options['labels-function'](name);
   switch(name) {
       case "e":
         return "To Email Address";
       case "f":
         return "From Email Address";
       default:
         return name
   }
}


function Validation_hide_valid(form) {

   if (document.all && !window.print) { return; } //removing mac ie support

   if (form.errors.length == 0) return
   trs = form.getElementsByTagName('tr')

   for (var x=0;x<trs.length;x++) {
      tr = trs[x];
      var hide = true;
      if (document.getElementsByTagName('*').length == 0) {
          // ie 5.5 doesn't support '*'
          // neither does safari 1.1 (but the later versions are fixed)
          if (tr.all) {
            siblings = tr.all;
          } else {
            siblings = new Array();
          }
      } else {
          siblings = tr.getElementsByTagName('*');
      }

      if (!siblings || siblings.length == 0) {siblings = new Array()}
      for(var s = 0; s < siblings.length; s++) {
          if (hide == true) {
              if (siblings[s].type == "submit") {hide = 'skip';}
              if (siblings[s].id == "validation_errors") {hide = 'skip';}
              for (var e = 0;e < form.errors.length;e++) {
                 ids = form.errors[e][0];
                 ids = ids.split(/\s*,\s*/);
                 for (j=0;j<ids.length;j++) {
                 	if (siblings[s].id == ids[j]) hide = false;
				 }
              }
          }
      }
      if (hide == 'skip') {}
      else if (hide) {trs[x].className = trs[x].className + " valid_container";}
      else {trs[x].className = trs[x].className + " error_container";}
   }
}

function Validation_unhide_valid(form) {
   trs = form.getElementsByTagName('tr')
   for (var x=0;x<trs.length;x++) {
      tr = trs[x];
      tr.className = tr.className.replace(/\berror_container\b/g,'');
      tr.className = tr.className.replace(/\bvalid_container\b/g,'');
   }
   return false;
}

function Validation_highlight_error(elementids) {
	ids = elementids.split(/\s*,\s*/);
	for (x=0;x<ids.length;x++){
		elementid = ids[x];
    	field = document.getElementById(elementid);
    	if (field) field.className = field.className + " error";
	}
}

function Validation_unhighlight_error(elementid) {
    field = document.getElementById(elementid);
    if (field) field.className = field.className.replace(/\berror\b/g,'');
}


function Validation_display_error(form,errors,required_fields,options) {

   function compare_errors (a,b) {
       ord_a = required_fields[a[1]] || 99;
       ord_b = required_fields[b[1]] || 99;
       return ord_a - ord_b
   }

   if (errors.length > 0) {

       errors.sort(compare_errors);

       box = document.getElementById('errors');
       var insertbox = false;
       if (!box) {
          box = document.createElement('div');
          box.id = "errors";
          insertbox = true;
       }
       var html = "<h3>This form has NOT been submitted</h3>";
       html += "<p>Please correct the following errors and try again</p>"
       html += "<ol>";

       for (e in errors) {
		   name = errors[e][1];
		   name = Validation_display_name(name,options);
		   ids = errors[e][0];
		   id = ids.split(/\s*,\s*/)[0];

		   Validation_highlight_error(ids);



		   if (errors[e][2] == "missing" ) {
			   html += "<li><a href=\"#"+id+"\" onclick=\"document.getElementById('"+id+"').focus();return false;\">"+name+"</a> is missing and is required</li>";
		   } else if (errors[e][2] == "email") {
			   html += "<li><a href=\"#"+id+"\" onclick=\"document.getElementById('"+id+"').focus();return false;\">"+name+"</a> is not a valid email address</li>";
		   } else if (errors[e][2] == "numeric") {
			   html += "<li><a href=\"#"+id+"\" onclick=\"document.getElementById('"+id+"').focus();return false;\">"+name+"</a> is not a valid number</li>";
		   } else if (errors[e][2] == "maxlength") {
			   html += "<li><a href=\"#"+id+"\" onclick=\"document.getElementById('"+id+"').focus();return false;\">"+name+"</a> is longer than "+errors[e][3]+" characters</li>";
		   } else {
			   html += "<li><a href=\"#"+id+"\" onclick=\"document.getElementById('"+id+"').focus();return false;\">"+name+"</a> "+errors[e][2]+"</li>";
		   }

       }

       html += "</ol>";

       Validation_hide_valid(form);

       box.innerHTML = html;
       if (insertbox) {
           anchor = document.createElement('a');
           anchor.id = "errmsg";
           anchor.name = "errmsg";

           if (document.getElementById('validation_errors')) {
               document.getElementById('validation_errors').appendChild(anchor);
               document.getElementById('validation_errors').appendChild(box);
           } else {
               //form.parentNode.insertBefore(box,form);
               form.insertBefore(box,form.firstChild)
               form.insertBefore(anchor,form.firstChild)
           }
       }

       //document.location = "#validation_errors";
       if (document.getElementById('errmsg')) {
           //document.getElementById('errmsg').focus();
           window.scroll(window.pageXOffset,document.getElementById('errmsg').offsetTop - 10)
           alert("Oops! Your form was not submitted. Please correct the above errors.");
       }
   }
}

function Validation_test_email(field,required_fields) {
    if (!required_fields[field.name] && field.value == '') return false;
    if (!(document.all && !window.print)) {   // removing support for mac ie -causes the fields to disappear
        field.value = field.value.replace(/^\s+/,'');
        field.value = field.value.replace(/\s+$/,'');
    }
    var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if (!filter.test(field.value)) {
        e = new Array(field.id,field.name,"email");
        return e;
    }
    return false;
}

function Validation_test_numeric(field,required_fields) {
    if (!required_fields[field.name] && field.value == '') return false;
    if (!(document.all && !window.print)) {   // removing support for mac ie -causes the fields to disappear
        field.value = field.value.replace(/^\s+/,'');
        field.value = field.value.replace(/\s+$/,'');
    }
    var filter  = /^[0-9]+$/;
    if (! filter.test(field.value)) {
        return new Array(field.id,field.name,"numeric");
    }
    return false;
}

function Validation_test_maxlength(field) {
    filter = /maxlength-(\d+)/;
    match = filter.exec(field.className);
    size = parseInt(match[1]) || 10000;
    if (field.value.length > size) {
        return new Array(field.id,field.name,"maxlength",size);
    }
    return false;
}


function Validation_test_type(field,required_fields) {
    var errors = new Array();
    if (field.className.indexOf('email') > -1) { e = Validation_test_email(field,required_fields); if (e) errors = errors.concat(new Array(e)); }
    if (field.className.indexOf('numeric') > -1) { e = Validation_test_numeric(field,required_fields); if (e) errors = errors.concat(new Array(e));  }
    if (field.className.indexOf('maxlength') > -1) { e = Validation_test_maxlength(field); if (e) errors = errors.concat(new Array(e));  }
    return errors
}

function Validation_ensure_id(field) {
    if (!Validation.count) { Validation.count = 0; }
    Validation.count ++
    if (!field.id || field.id.indexOf('validation_') > -1) {
        field.id = "validation_" + Validation.count;
    }
    return field.id
}

function Validation_disable_submit(form,options) {
	var input_element_list = form.getElementsByTagName("input");
    for (var x=0; x < input_element_list.length; x++) {
        field = input_element_list.item(x);
        if (field.type == 'submit') {
			field.value = "Please wait...";
			field.disabled = true;
		}
	}
}

function Validation_get_errors(form,required_fields) {
   var errors = new Array();
   var count = 0;

   // Testing Inputs

   var input_element_list = form.getElementsByTagName("input");

   var radios = new Array();
   var radios_ids = new Array();

   for (var x=0; x < input_element_list.length; x++) {
      field = input_element_list.item(x);
      var has_error = false;
      Validation_ensure_id(field);
      Validation_unhighlight_error(field.id);

      if (required_fields[field.name]) {
         if (field.type == 'radio') {

            radios[field.name] = radios[field.name] || field.checked;
            if (!radios_ids[field.name]) {radios_ids[field.name] = field.id;}
            else {radios_ids[field.name] += ','+field.id;}
         } else if (field.type == 'checkbox' && field.checked == false) {
            e = new Array(field.id,field.name,"missing");
            errors = errors.concat(new Array(e))
            has_error = true;
         } else if (field.value == '') {
            e = new Array(field.id,field.name,"missing");
            errors = errors.concat(new Array(e))
            has_error = true;
         }
      }

      if (!has_error) {
         errors = errors.concat(Validation_test_type(field,required_fields));
      }
   }

   for (x in radios) {
       if (!radios[x]) {
          e = new Array(radios_ids[x],x,"missing")
          errors = errors.concat(new Array(e))
       }
   }
   // Testing Textareas

   textarea_element_list = form.getElementsByTagName("textarea");
   for (x =0; x < textarea_element_list.length; x++) {
      field = textarea_element_list.item(x);
      var has_error = false;
      Validation_ensure_id(field);
      Validation_unhighlight_error(field.id);
      if (required_fields[field.name]) {
         if (field.value == '') {
            e = new Array(field.id,field.name,"missing");
            errors = errors.concat(new Array(e))
            has_error = true;
         }
      }
      if (!has_error) {
         errors = errors.concat(Validation_test_type(field,required_fields));
      }
   }

   // Testing Select Boxes

   select_element_list = form.getElementsByTagName("select");
   for (x =0; x < select_element_list.length; x++) {
      field = select_element_list.item(x);
      Validation_ensure_id(field);
      Validation_unhighlight_error(field.id);
      if (required_fields[field.name]) {
          if (field.selectedIndex == -1 || field.options[field.selectedIndex].text == '') {
              e = new Array(field.id,field.name,"missing");
              errors = errors.concat(new Array(e))
          }
      }
   }

   return errors
}

function Validation_get_conditional_errors(form,options) {
	var errors = new Array();
	if (options['custom-conditions']) {
		for(x=0;x<options['custom-conditions'].length;x++) {
			e = options['custom-conditions'][x](form);
			if (e) {
				errors = errors.concat(Array(e));
			}
		}

		return errors;
	}
	return new Array();
}


function Validation_check(form,options) {
	trace('doing validation');
   try {
       if (!options) options = new Array();
       form.options = options;

       Validation_ensure_id(form);
       Validation_unhide_valid(form);

       var required_fields = Validation_get_required_fields(form);
       form.required_fields = required_fields;

       var errors = Validation_get_errors(form,required_fields);
       var custom_errors = Validation_get_conditional_errors(form,options);
       errors = errors.concat(custom_errors);
       form.errors = errors;

       Validation_display_error(form,errors,required_fields,options);

       if (errors.length > 0) {
           return false;
       } else {
		   //Validation_disable_submit(form,options);
           return true;
       }

       return false;
   } catch (e) {
     alert('ERROR ' + e + " " + e.message);
     throw e;
     return false;
   }
}

Validation.check = Validation_check;

function isNodeList(a) {return isObject(a) && a.constructor == NodeList;}
function isArray(a) {return isObject(a) && a.constructor == Array;}
function isObject(a) {return (a && typeof a == 'object') || isFunction(a);}
function isFunction(a) {return typeof a == 'function';}