	/*
	file:		form_handler.js
	name:		UTA Form Handler Javascript
	version:	v0.4
	by:		Daniel Evilsizor
	date:		31 August 2007
	summary:	Easy to use Javascript Form validation and error reporting.
			meant to be used with UTA Form Handler PHP Class.
			The PHP class generates the configuration for this script,
			so to use the Javascript validation for your form, if you're using the Form Handler PHP Class,
			you simply need to include this file, eg
				<script src="form_handler/form_handler.js"></script>
			, and then generate the configuration for this script with
				<?php $form->makeJS(); ?>
			
	*/





	/* TODO:
	
		- make sure errdiv isn't called for hidden fields..?
		- documentation
		- do safety checks as appropriate (eg, if (document.getElementById(element)) { // do something with element... } )
		* finish group implementation
		- test group checking
		- allow custom error messages
		- allow fields to belong to multiple groups?
		* fix form.validate()
		* onmuoseout / onblur shuold turn off all validated group fields
		- can use checkboxes in groups? -> no, could only add the entire 'field' to a group
		- add 'tie' for required?
		- keep groups? they add 5k, not to much benefit, and they don't work with checkbox implementation.
			- tie() would be easier and cheaper to implement, and more useful, and would work for the architecture form
			- groups are already implemented
			- don't work with checkboxes
			- adds 5k to code (28%)
			- how useful?
				- min or max entered textboxes, textareas, password fields, radio fields
			- should i just make checkboxes work the same way?
				- would make most sense..?
				- would give checkboxes group features
				- somewhat significant development time...? not really
				- checkboxes should still be 1 field, with options. is most intuitive organization for them.
				- can i make options members of a group?
					- not in PHP, but yes in JS, b/c options are full-fledged fields
					- WRONG. options are not fields in the JS either.
					- how to check in JS?
					- new checkbox paradigm...
					- so can make these fields members of a group
				

		- validate JS && fix errors
		- test in differnt browsers - doesn't work in Safari 3 on windows
		- test on slow computers
		- test on low-bandwidth computers
		- test
		- optimize JS for speed
		- make sure form is still accessible to
			- non JS browsers
			- screen-readers

		
		Planned Version2 improvements
		- incorporate calendar picker
		- create option to display error message on right or left of field
		- set onfocus styles for form elements?
	*/

	
	// create empty rules class
	function Rule()
	{
	}
	
	
	// define a Field class
	function Field(n, nicename, is_required, t, err_class, parent)
	{
		var is_valid = false;
		var required = is_required;
		var type = t;
		var name = n;
		var nice_name = nicename;
		var is_empty = true;
		var is_errdiv_on = false;
		var error_class = err_class;
		var group = null;
		var group_nice_name = null;
		var my_parent_form = parent;
		var error_type = null;				// set to either 'field' or 'group'
		
		var rules = new Rule();
		//var grules = new Rule();
		var options = null;
		var error = "";
		
		this.validate = validate;
		this.checkRequired = checkRequired;
		this.checkRules = checkRules;
		this.checkEmpty = checkEmpty;
		this.isValid = isValid;
		this.getErrors = getErrors;
		this.getErrorType = getErrorType;
		this.colorValid = colorValid;
		this.colorInvalid = colorInvalid;
		this.setOptions = setOptions;
		this.addRule = addRule;
		this.showErrorDiv = showErrorDiv;
		this.hideErrorDiv = hideErrorDiv;
		this.updateErrorDiv = updateErrorDiv;
		this.getNiceName = getNiceName;
		this.getGroupNiceName = getGroupNiceName;
		this.getGroupName = getGroupName;
		this.setGroup = setGroup;
		this.getGroup = getGroup;
		this.checkGroupRules = checkGroupRules;
		this.getName = getName;
		this.getType = getType;
		this.getErrorClass = getErrorClass;
		
		function getName()			{ return name; }
		function getType()			{ return type; }
		function getErrorClass()	{ return error_class; }
		function getErrors()  		{ return error;	}
		function getNiceName() 		{ return nice_name; }
		function getGroupNiceName() { return group_nice_name; }
		function getGroupName() 	{ return group; }
		function isValid()  		{ return is_valid; }
		function getGroup() 		{ return group; }		
		function getErrorType()	 	{ return error_type; }
		
		
		function setGroup(group_name, group_nicename)
		{
			group = group_name;
			group_nice_name = group_nicename;
		}
		
		
		function showErrorDiv()
		{
			// if this option is set to 'false', don't do it
			if (my_parent_form.getOption('show-error-label') == false) return;
		
			// don't show error div if field is valid
			if (is_valid == true)
				return;
				
			// see if div already exists
			if (is_errdiv_on == true)
				return;
		 
		 	var err_str = getErrors();
			var theparent;
		 
			// if in a group, and the error type is 'group', and the group has a container, then show the label on that container
			if (error_type == "group" && group != null && document.getElementById(group + "_container")) {
				theparent = document.getElementById(group + "_container");
			} else {
				// otherwise, not in group, or no group container defined, so show label on the field.
				switch(type) {
					// if field is radio or checkbox, we still have to use a field container
					case "radio":
						theparent = document.getElementById(name + "_container");
						break;
					case "checkbox":
						if (document.getElementById(name + "_container"))
							theparent = document.getElementById(name + "_container");
						else
							theparent = document.getElementById(name);
						break;
					default:
						theparent = document.getElementById(name);
						break;
				}
			}
			
			if (theparent) {
				showhint(err_str, theparent, my_parent_form.getOption('error-label-side'));
				is_errdiv_on = true;
			}
		}
		

		function checkGroupRules()
		{
			var err = "";
			if (group != null)
				err = my_parent_form.checkGroupRules(group);
			if (err) {
				error = err;
				error_type = 'group';
			}
		}

		
		function addRule(rule_type, rule_parm)
		{
			rules[rule_type] = rule_parm;
		}
		
		
		function hideErrorDiv()
		{
			// if this option is set to 'false', don't bother with this
			if (my_parent_form.getOption('show-error-label') == false) return;
			
			hidetip();
			is_errdiv_on = false;
		}
		
		
		
		function updateErrorDiv()
		{
			// if this option is set to 'false', don't bother with this
			if (my_parent_form.getOption('show-error-label') == false) return;
			
			if (is_errdiv_on == true) {
			
				if (is_valid == true) {
					hideErrorDiv();
				} else {
					// update the error message in case it has changed
					dropmenuobj=document.getElementById("hintbox")
					if (dropmenuobj)
						dropmenuobj.innerHTML = error;
				}
					
				
			} else {
				if (is_valid == false)
					showErrorDiv();
			}
		} // end function
		
		
		
		function checkEmpty()
		{
			switch (type) {
				case "text":
				case "password":
				case "textarea":
					val = document.getElementById(name).value;
					if (val == '') {
						return true;
					}
					return false;
					break;
				case "radio":
					var checkmarks = 0;
					for (o in options) {
						if (document.getElementById(options[o]).checked == true) {
							checkmarks++;
						}
					}
					if (checkmarks == 0) {
						return true;
					}
					return false;
					break;
				case "checkbox":
					//alert("name is " + name);
					if (document.getElementById(name).checked == false) return true;
					return false;
					break;
				case "select":
					if (document.getElementById(name).value == '_NULL_option'){ 
						return true;
					}
					return false;
					break;
				default:
					return true;
					break;
			} // end switch
		}
		
		
		
		
		function validate()
		{
		
			//alert("validating field " + nice_name);
			// reset any previous errors for new checks
			is_valid = false
			error = "";
			
			//document.getElementById('errdump').value += "validate(): NAME: " + nice_name + "\n";
			
			is_empty = checkEmpty();
			checkRequired();
			if (is_empty == false)
				checkRules();
				
			//document.getElementById('errdump').value += "validate(): NAME: " + nice_name + "\n";

			// if everything is ok so far, check group rules
			if (error == "")
				checkGroupRules();

			//document.getElementById('errdump').value += "validate(): NAME: " + nice_name + "\n";
				
			if (error == "") {
				is_valid = true;
				colorValid();
			} else {
				is_valid = false;
				colorInvalid();
			}
			//document.getElementById('errdump').value += "validate(): NAME: " + nice_name + "\n";
		}
		
		
		function setOptions(opt)
		{
			options = opt;
			
			switch (type) {
				case "radio":
					// attach event handlers for each option
					for (o in opt) {
						x = document.getElementById( opt[o] );
						x.onblur = function() { hideErrorDiv(); };
						x.onfocus = function() { showErrorDiv(); };
						x.onclick = function() { validate(); updateErrorDiv(); };
						x.onkeyup = function() { validate(); updateErrorDiv(); };
					}
					break;
				default:
					// .. error?
					break;
			}
		}
		
		
		
		// change the style of a field to indicate that it is valid
		function colorValid()
		{
			// if this option is set to 'false', don't bother with this
			if (my_parent_form.getOption('show-error-class') == false) return;
			
			switch (type) {
				case "text":
				case "password":
				case "textarea":
					if (group) {
						my_parent_form.colorValidGroup(group);
					} else {
						if (document.getElementById(name))
							document.getElementById(name).className = "";
					}
					break;
				case "radio":
				case "select":
				case "checkbox":
					if (group) {
						my_parent_form.colorValidGroup(group);
					} else {
						if (document.getElementById(name + "_container"))
							document.getElementById(name + "_container").className = "";
					}
					break;
				default:
					// hm..
					break;
			}
		
		}
		
		
		// change the style of a field to indicate that it is valid
		function colorInvalid()
		{
			// if this option is set to 'false', don't bother with this
			if (my_parent_form.getOption('show-error-class') == false) return;
			
			switch (type) {
				case "text":
				case "password":
				case "textarea":
					if (group) {
						my_parent_form.colorInvalidGroup(group);
					} else {
						if (document.getElementById(name))
							document.getElementById(name).className = error_class;
					}
					break;
				case "radio":
				case "select":
				case "checkbox":
					if (group) {
						my_parent_form.colorInvalidGroup(group);
					} else {
						if (document.getElementById(name + "_container"))
							document.getElementById(name + "_container").className = error_class;
					}
					break;
				default:
					// hm..
					break;
			}
		}
		
		
		
		function checkRequired()
		{
			if (required == false) {
				return false;
			}

			if (is_empty) {
				error = "This is a Required Field";
				error_type = 'field';
			}
			
			return true;
		}
		
		
		function checkRules()
		{
			for (r in rules) {
				switch(r) {
				
					case "allowed_chars":
						if (type != 'text' && type != 'password' && type != 'hidden' && type != 'textarea') break;
						var val = document.getElementById(name).value;
						var re = new RegExp('^(\s*)[' + rules[r] + ']*(\s*)$');
						if (! val.match(re)) {
							if (rules['allowed_chars_nice'] != undefined)
								var errstr = rules['allowed_chars_nice'];
							else
								var errstr = rules[r];
							error = "Invalid characters in field. Allowed characters are:\n" + errstr;
							error_type = 'field';
						}
						break;
						
					case "allowed_values":
						if (type != 'text' && type != 'password' && type != 'hidden' && type != 'textarea') break;
						var val = document.getElementById(name).value;
						var re = new RegExp('^(' + rules[r] + ')$');
						if (! val.match(re)) {
							var nice_rule = rules[r].replace(/\|/g, ", ");
							error = "Invalid value. Allowed values are:<br />\n" + nice_rule;
							error_type = 'field';
						}
						break;						
						
					case "match":
						if (type != 'text' && type != 'password' && type != 'hidden' && type != 'textarea') break;
						var val = document.getElementById(name).value;
						var re = new RegExp(rules[r]);
						if (! val.match(re)) {
							error = "Field must match " + rules[r];
							// look for match_nice rule
							if (rules['match_nice'] != undefined) {
								error = "Field must be in format: " + rules['match_nice'];
								error_type = 'field';
							}
						}
						break;
						
					case "type":
						var val = document.getElementById(name).value;
						switch (rules[r]) {
							case "int":
								var re = new RegExp('^[\\d,]+$');
								if (! val.match(re)) {
									error = "Value must be an integer";
									error_type = 'field';
								}
								break;
								
							case "number":
								var re = new RegExp('^[\\d\\.,]+$');
								if (! val.match(re)) {
									error = "Value must be a number";
									error_type = 'field';
								}
								break;
								
							case "email":
								var re = new RegExp("^([-!#\$%&'*+.\\/0-9=?A-Z^_`a-z{|}])+@(([-!#\$%&'*+\\/0-9=?A-Z^_`a-z{|}]+\\.)+[a-zA-Z]{2,6}|\[[012]?[0-9]?[0-9]\.[012]?[0-9]?[0-9]\.[012]?[0-9]?[0-9]\.[012]?[0-9]?[0-9]\])\$");
								if (! val.match(re)) {
									error = "Value must be an email address";
									error_type = 'field';
								}
								break;
								
							default:
								// ....
								break;
							}
						
					default:
						// ...
						break;
				
				}
			}
		}
		
	} // end class 'Field'
	
	
	function FieldSet() { };
	
	
	function Form (fname)
	{
		var is_valid = false;
		var form_name = fname;
		var fields = new FieldSet();
		var groups = new FieldSet(); // semantics.. pretend it says GroupSet()...
		var form_errors = new Array();
		var errorstyles = new Array();
		var error_class = null;
		
		// set default values for some form options
		var show_error_label = true;
		var show_error_class = true;
		var error_label_side = 'right';
		var hintbox_width = 200;
		
		var grules = new Rule();
		var gerrors = new Array();
		
		this.addField = addField;
		this.addRule = addRule;
		this.validateForm = validateForm;
		this.resetForm = resetForm;
		this.getName = getName;
		this.setOptions = setOptions;
		this.setErrorClass = setErrorClass;
		this.setGroup = setGroup;
		this.addGroup = addGroup;
		this.addGroupRule = addGroupRule;
		this.checkGroupRules = checkGroupRules;
		this.colorValidGroup = colorValidGroup;
		this.colorInvalidGroup = colorInvalidGroup;
		this.setOption = setOption;
		this.getOption = getOption;
		this.dumpFields = dumpFields;

		this.createhintbox = createhintbox;
		this.showhint = showhint;
		this.hidetip = hidetip;
		this.getposOffset = getposOffset;
		this.clearbrowseredge = clearbrowseredge;
		this.iecompattest = iecompattest;
		
		
		var reset_button = document.getElementById(form_name + "_reset");
		if (reset_button) {
			reset_button.onmouseup = function() { setTimeout('globalResetForm("' + form_name + '")', 1000); };
			reset_button.onkeyup = function() { setTimeout('globalResetForm("' + form_name + '")', 1000); };
		}
		
		var form = document.getElementById(fname);
		if (form) {
			form.onsubmit = function() { return validateForm(); };
		} else {
			//debug
			alert("form " + fname + " not found on page");
			return;
		}

		
		function getName()
		{
			return form_name;
		}

		
		function setOption(opt_name, opt_value)
		{
			switch (opt_name) {
				case "show-error-label":
					show_error_label = opt_value;
					break;
				case "show-error-class":
					show_error_class = opt_value;
					break;
				case "error-label-side":
					error_label_side = opt_value;
					break;
				default:
					// invalid option.
					break;
			}
		}
		
		
		function getOption(opt_name)
		{
			switch (opt_name) {
				case "show-error-label":
					return show_error_label;
					break;
				case "show-error-class":
					return show_error_class;
					break;
				case "error-label-side":
					return error_label_side;
					break;
				default:
					// invalid option.
					break;
			}		
		}
		
		
		function addGroupRule(gname, rtype, rparm)
		{
			if (grules[gname] == undefined) 
				grules[gname] = new Rule();
			grules[gname].type = rtype;
			grules[gname].parm = rparm;
		}

		
		function colorValidGroup(groupname)
		{
			// if this option is set to 'false', don't bother with this
			if (show_error_class == false) return;
		
			// see if the group is already colored invalid
			if (groups[groupname + "_color"] == 'valid') return;
			
			// if there is a group container, color it invalid
			if (document.getElementById( groupname + "_container")) {
				document.getElementById( groupname + "_container").className = "";
			} else {		// otherwise, no group container, so color each field in the group invalid
				
				for (f in fields) {
					if (fields[f].getGroupName() == groupname) {

						switch (fields[f].getType()) {
							case "text":
							case "password":
							case "textarea":
								if (document.getElementById( fields[f].getName() ))
									document.getElementById( fields[f].getName() ).className = "";
								break;
							case "checkbox":
								if (document.getElementById( fields[f].getName() + "_container"))
									document.getElementById( fields[f].getName() + "_container").className = "";
								else
									document.getElementById( fields[f].getName() ).className = "";
								break;
							case "radio":
								if (document.getElementById( fields[f].getName() + "_container"))
									document.getElementById( fields[f].getName() + "_container").className = "";
								break;
							default: break;
						}
					
					}
				}
			}
			groups[groupname + "_color"] = 'valid';
		}
		
		
		function colorInvalidGroup(groupname)
		{
			// if this option is set to 'false', don't bother with this
			if (show_error_class == false) return;
			
			// see if the group is already colored invalid
			if (groups[groupname + "_color"] == 'invalid') return;

			// if there is a group container, color it invalid
			if (document.getElementById( groupname + "_container")) {
				document.getElementById( groupname + "_container").className = fields[f].getErrorClass();
			} else {		// otherwise, no group container, so color each field in the group invalid
				
				for (f in fields) {
					if (fields[f].getGroupName() == groupname) {

						switch (fields[f].getType()) {
							case "text":
							case "password":
							case "textarea":
								if (document.getElementById( fields[f].getName() ))
									document.getElementById( fields[f].getName() ).className = fields[f].getErrorClass();
								break;
							case "checkbox":
								if (document.getElementById( fields[f].getName() + "_container"))
									document.getElementById( fields[f].getName() + "_container").className = fields[f].getErrorClass();
								else
									document.getElementById( fields[f].getName() ).className = fields[f].getErrorClass();
								break;
							case "radio":
								if (document.getElementById( fields[f].getName() + "_container"))
									document.getElementById( fields[f].getName() + "_container").className = fields[f].getErrorClass();
								break;
							default: break;
						}
					
					}
				}
			}
			groups[groupname + "_color"] = 'invalid';
		}
		
		
		function addGroup(gname, gnice_name)
		{
			groups[gname] = gnice_name;
			groups[gname + "_color"] = "valid";
		}
		
		
		function setGroup(fname, gname)
		{
			if (groups[gname] != undefined)
				fields[fname].setGroup(gname, groups[gname]);
		}

		
		function setErrorClass(classname)
		{
			error_class = classname;
		}
		
		
		function checkGroupRules(grp)
		{
			// TODO:
			//    1) this is getting called with 'null' for every nongroup field
			
			//alert("checking grouprules for " + grp);
			if (groups[grp] != undefined && grules[grp] != undefined) {
			
				switch (grules[grp].type) {
					case 'min_required':
						// check that the min required # of fields have been entered
						// there's got to be a better way to do this...
						var empty = 0;
						var total = 0;
						for (f in fields) {
							if(fields[f].getGroupName() == grp) {
								total++;
								if (fields[f].checkEmpty()) {
									empty++;
								}
							}
						}
						if ( (total - empty) < grules[grp].parm) {
							//alert("you must enter at least " + grules[grp].parm);		// Works...
							return "You must enter at least " + grules[grp].parm + " values";
						}
						break;
					case "max_allowed":
						var empty = 0;
						var total = 0;
						for (f in fields) {
							if(fields[f].getGroupName() == grp) {
								total++;
								if (fields[f].checkEmpty()) {
									empty++;
								}
							}
						}
						if ( (total - empty) > grules[grp].parm) {
							//alert("you must enter at least " + grules[grp].parm);		// Works...
							return "You may enter at most " + grules[grp].parm + " values";
						}
						break;
					default:
						//...
						break;
				}
			
			}
			
			return;
		}
		
		
		function addRule(field_name, rule_type, rule_parm)
		{
			if (fields[field_name] != undefined) {
				fields[field_name].addRule(rule_type, rule_parm);
			} else if (groups[field_name] != undefined) {
				addGroupRule(field_name, rule_type, rule_parm);
			} else {
				// no field or group to attach rule to...
			}
		}
		
		
		// revalidate fields after reset button is pressed, or when script is first loaded
		function resetForm()
		{
			// debug
			//alert("in resetForm()");
			for (f in fields) {
				fields[f].validate();
			}
		}
		
		
		function addField(name, nice_name, is_required, type)
		{
			fields[name] = new Field(name, nice_name, is_required, type, error_class, this);

			switch (type) {
				case "text":
				case "textarea":
				case "password":
					x = document.getElementById(name);
					x.onblur = function() { fields[name].validate(); fields[name].hideErrorDiv(); };
					x.onfocus = function() { fields[name].showErrorDiv(); };
					x.onkeyup = function() { fields[name].validate(); fields[name].updateErrorDiv(); };
					x.onclick = function() { fields[name].validate(); fields[name].updateErrorDiv(); };
					break;
				//case "radio":
				case "checkbox":
				case "select":
					x = document.getElementById(name);
					x.onblur = function() { fields[name].hideErrorDiv(); };
					x.onfocus = function() { fields[name].validate(); fields[name].showErrorDiv(); };
					x.onclick = function() { fields[name].validate(); fields[name].updateErrorDiv(); };
					x.onkeyup = function() { fields[name].validate(); fields[name].updateErrorDiv(); };
					break;
				default:
					// hm....
					break;
			}
		}
		
		
		function setOptions(field, options)
		{
			fields[field].setOptions(options);
		}

		
		// debug function.. not sure why some fields are acting funny...
		function dumpFields()
		{
			var e = "========================================\n";
			for (f in fields) {
				e += fields[f].getName() + " (" + fields[f].getNiceName() + ")\n";
				e += " - TYPE:    " + fields[f].getType() + "\n";
				e += " - GROUP:   " + fields[f].getGroupName() + " (" + fields[f].getGroupNiceName() + ")\n";
				e += " - VALID:   " + fields[f].isValid() + "\n";
				e += " - ERRTYPE: " + fields[f].getErrorType() + "\n";
				e += " - ERROR:   " + fields[f].getErrors() + "\n";
			}
			if (document.getElementById('errdump'))
				document.getElementById('errdump').value += e + "\n";
		}
		
	
		function validateForm()
		{
			// need to reset errors for new checks
			is_valid = false;

			//dumpFields();
			
			// clear group errors
			for (x in gerrors) {
				gerrors[x] = false;
			}
			
			var err_str = "";
			var tmp_err = "";
		
			// validate each field in form. for some reason the for loop gives weird references on group elements
			// if we validate within the same loop that we do everything else in
			for (f in fields) {
				fields[f].validate();
			}
			
			for (f in fields) {
				if (! fields[f].isValid()) {
					if (fields[f].getErrorType() == 'field') {
						err_str += " - " + fields[f].getNiceName() + ": " + fields[f].getErrors() + " \n";
					} else {
						if (gerrors[ fields[f].getGroupName()] == undefined || gerrors[ fields[f].getGroupName() ] === false) {
							err_str += " - " + fields[f].getGroupNiceName() + ": " + fields[f].getErrors() + "\n";
							gerrors[ fields[f].getGroupName() ] = true;
						}
					}


					/* else {
						//debug
						//alert("validating group " + fields[f].getGroupName());
						// group error. check for preexisting
						if (gerrors[fields[f].getGroupName()] == false) {
							err_str += " - " + fields[f].getGroupNiceName() + ": " + fields[f].getErrors() + " \n";
							gerrors[fields[f].getGroupName()] = true;
						}
					} */
					
				} 
			}
			
			dumpFields();
			
			// check for errors
			if (err_str == "") {
				is_valid = true;
			}
			
			if (is_valid == true) {
				return true;	// TODO: Reset to 'true' upon completion
			} else {
				alert("Your form had the following errors:\n-----------------------------------------------------------\n\n" + err_str + "\n");
				return false;
			}
			
		}
	
	}
	
	
	
	

	
	function globalResetForm(form_name)
	{
		for (f in forms) {
			if (forms[f].getName() == form_name) {
				forms[f].resetForm();
			}
		}
	}
	
	
	
		

		/***********************************************
		* Show Hint script- © Dynamic Drive (www.dynamicdrive.com)
		* This notice MUST stay intact for legal use
		* Visit http://www.dynamicdrive.com/ for this script and 100s more.
		***********************************************/
				
		var horizontal_offset="15px" //horizontal offset of hint box from anchor link

		var vertical_offset="0" //horizontal offset of hint box from anchor link. No need to change.
		var ie=document.all
		var ns6=document.getElementById&&!document.all


		function getposOffset(what, offsettype){
			var totaloffset=(offsettype=="left")? what.offsetLeft : what.offsetTop;
			var parentEl=what.offsetParent;
			while (parentEl!=null){
				totaloffset=(offsettype=="left")? totaloffset+parentEl.offsetLeft : totaloffset+parentEl.offsetTop;
				parentEl=parentEl.offsetParent;
			}
			return totaloffset;
		}


		function iecompattest(){
			return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
		}


		function clearbrowseredge(obj, whichedge){
			var edgeoffset=(whichedge=="rightedge")? parseInt(horizontal_offset)*-1 : parseInt(vertical_offset)*-1
			if (whichedge=="rightedge"){
				var windowedge=ie && !window.opera? iecompattest().scrollLeft+iecompattest().clientWidth-30 : window.pageXOffset+window.innerWidth-40
				dropmenuobj.contentmeasure=dropmenuobj.offsetWidth
				if (windowedge-dropmenuobj.x < dropmenuobj.contentmeasure)
					edgeoffset=dropmenuobj.contentmeasure+obj.offsetWidth+parseInt(horizontal_offset)
			}
			else{
				var windowedge=ie && !window.opera? iecompattest().scrollTop+iecompattest().clientHeight-15 : window.pageYOffset+window.innerHeight-18
				dropmenuobj.contentmeasure=dropmenuobj.offsetHeight
				if (windowedge-dropmenuobj.y < dropmenuobj.contentmeasure)
				edgeoffset=dropmenuobj.contentmeasure-obj.offsetHeight
			}
			return edgeoffset
		}
		

		function showhint(menucontents, obj, error_label_side){
			if ((ie||ns6) && document.getElementById("hintbox")){

				dropmenuobj=document.getElementById("hintbox")
				arrow = document.getElementById("hintbox_arrow");
				dropmenuobj.innerHTML=menucontents;
				
				var arrow_dir = (error_label_side == "left") ? "right" : "left";
				arrow_img = document.getElementById('hintbox_arrow_img');
				if (arrow_img.getAttribute("src") != "form_handler/images/arrow_" + arrow_dir + ".gif")
					arrow_img.setAttribute("src", "form_handler/images/arrow_" + arrow_dir + ".gif");

				dropmenuobj.style.left=dropmenuobj.style.top=-500;
				arrow.style.left = arrow.style.top = -500;

				dropmenuobj.x=getposOffset(obj, "left")
				dropmenuobj.y=getposOffset(obj, "top")

				var other_edge = (error_label_side == "left") ? "rightedge" : "leftedge";
				var lr_adjust = (error_label_side == "right") ? (obj.offsetWidth + 15) : (-(dropmenuobj.offsetWidth + 30));
				
				x = dropmenuobj.x - clearbrowseredge(obj, other_edge) + lr_adjust;
				y = dropmenuobj.y - clearbrowseredge(obj, "bottomedge");
				dropmenuobj.style.left=x+"px"
				dropmenuobj.style.top=y+"px"
				if (error_label_side == "left") {
					arrow.style.left = x + dropmenuobj.offsetWidth + "px";
				} else  {
					arrow.style.left = x-6+"px";
				}
				arrow.style.top = y+7+"px";
				dropmenuobj.style.visibility="visible"
				arrow.style.visibility="visible";
			}
		}

		function hidetip() {
			dropmenuobj = document.getElementById("hintbox");
			dropmenuobj.style.visibility="hidden"
			dropmenuobj.style.left="-500px"
			arrow = document.getElementById("hintbox_arrow");
			arrow.style.visibility="hidden";
			arrow.style.left = "-500px";
		}

		function createhintbox() {
			var divblock=document.createElement("div")
			var divarrow = document.createElement("div");
			divarrow.setAttribute("id", "hintbox_arrow");
			divblock.setAttribute("id", "hintbox")
			document.body.appendChild(divblock)
			document.body.appendChild(divarrow);
			var arrowimg = document.createElement("img");
			arrowimg.setAttribute("src", "form_handler/images/arrow_left.gif");
			arrowimg.setAttribute("id", "hintbox_arrow_img");
			arrowimg.setAttribute("border", "0");
			arrowimg.setAttribute("width", "6");
			arrowimg.setAttribute("height", "11");
			document.getElementById('hintbox_arrow').appendChild(arrowimg);
		}

		/***********************************************
		* END Show Hint script- © Dynamic Drive (www.dynamicdrive.com)
		***********************************************/
	
	

	if (window.addEventListener)
		window.addEventListener("load", createhintbox, false)
	else if (window.attachEvent)
		window.attachEvent("onload", createhintbox)
	else if (document.getElementById)
		window.onload=createhintbox

	
