// Array for storing Form objects
var forms = new Array();

var states = new Array("Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", 
					   "Delaware", "D.C.", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", 
					   "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Main", "Maryland", 
					   "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri",
					   "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
					   "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon",
					   "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
					   "Texas", "Utah", "Vermont", "Virginia", "Washington", "Wisonsin", "Wyoming"); 

/**
 * Will find all forms and create new Form objects, placing
 * them, by name, in the forms array.
 */
function initForms() {
	for(var i = 0; i < document.forms.length; i++) {
		forms[i] = new Form(document.forms[i].id);			
	}	
}

function submitForm(name) {
	if(document.forms[name]) {
		document.forms[name].submit();
	}
}

/**
 * Gets a form from the forms Array
 */
function getForm(id) {
	for(var i = 0; i < forms.length; i++) {
		if(forms[i].getName().toUpperCase() == id.toUpperCase()) {
			return forms[i];
		}		
	}
}

/**
 * Form object represents an encapsulated HTML form. Invoking
 * a new Form object will cause parsing of all inputs.
 */
function Form(id) {	
	this.id = id;
	this.obj = getObject(id);
	this.elements = new Array();
	
	this.getObject = function() {
		return this.obj;
	}
	
	for(var i = 0; i < this.obj.length; i++) {
		var element = this.obj[i];
		var type = element.type.toLowerCase();
		var newElement = false;
		if(type == "text" || type == "password") {			
			newElement = new TextField(element);						
		} else if(type == "textarea") {
			newElement = new TextArea(element);		
		} else if(type == "password") {
			newElement = new Password(element);		
		} else if(type == "checkbox") {
			newElement = new Checkbox(element);		
		} else if(type == "radio") {
			newElement = new RadioButton(element);		
		} else if(type == "hidden") {
			newElement = new Hidden(element);		
		} else if(type.indexOf("select") > -1) {
			newElement = new Select(element);		
		} else if(type == "file") {
			newElement = new File(element);		
		}		
		else {
			newElement = false;			
		}
		
		if(newElement) {
			this.elements[this.elements.length] = newElement;		
		}
	}
	
	this.getName = function() {
		return this.id;
	}
	
	this.getElement = function(name) {
		for(var i = 0; i < this.elements.length; i++) {
			if(this.elements[i].getName().toLowerCase() == name.toLowerCase()) {
				return this.elements[i];
			}
		}		
	}	
	
	/**
	 * Gets a group of elements with the same name in the form of an Array.
	 */
	this.getGroup = function(name) {
		var group = new Array();	
		for(var i = 0; i < this.elements.length; i++) {
			if(this.elements[i].getName().toLowerCase() == name.toLowerCase()) {
				group[group.length] = this.elements[i];
			}
		}	
		
		return group;
	}
	
	/**
	 * Gets an element from a group of elements at specified index.
	 */
	this.getGroupElement = function(name, index) {
		var group = this.getGroup(name);
		return index >= group.length ? false : group[index];
	}
	
	this.setAction = function(action) {
		this.obj.action = action;
	}
	
	this.getAction = function() {
		return this.obj.action;
	}
	
	this.getEncoding = function() {
		return this.obj.encoding;
	}
	this.setEncoding = function(encoding) {
		this.obj.encoding = encoding;
	}
	
	this.getMethod = function() {
		return this.obj.method;
	}
	
	this.setMethod = function(method) {
		this.obj.method = method;
	}	
	
	this.doSubmit = function() {
		this.obj.submit();
	}
}

/**
 * This is our super class for a form element with commonly
 * needed function
 */
function Element() {	
	this.setObject = function(obj) {
		this.obj = obj;
	}	
	this.getObject = function() {
		return this.obj;
	}
	this.getName = function() {
		return this.obj.name;
	}
	
	this.getValue = function() {
		return this.obj.value;
	}
	
	this.setValue = function(value) {
		this.obj.value = value;
	}
	
	this.clear = function() {
		this.obj.value = "";
	}
	
	this.setEnabled = function(doEnable) {
		this.obj.disabled = !doEnable;
	}
	
	this.toggleEnabled = function() {
		this.obj.disabled = !this.obj.disabled;
	}
	
	this.setClass = function(className) {
		this.obj.className = className;
	}
	this.setSize = function(size) {
		this.obj.size = size;
	}
	this.getSize = function() {
		return this.obj.size;
	}
	this.setMaxLength = function(maxLength) {
		this.obj.maxLength = maxLength;
	}
	this.getMaxLength = function() {
		return this.obj.maxLength;
	}
	this.setFocus = function() {
		this.obj.focus();
	}
	this.getLength = function() {
		return this.obj.value.length;
	}
}


/**
 * TextField object represents HTML textfield input and inherits from 
 * Element. There are no additional functions added.
 */
function TextField(obj) {
	this.setObject(obj);
	
	this.setNumericOnly = function() {
		this.obj.onkeypress = blockAlpha;
	}
	
	this.obj.onkeypress = blockRestricted;
	
	this.isEmpty = function() {
		return this.getValue() == "";
	}
	
	this.isValidEmail = function validateEmail() {
		var addr = this.getValue();
		
		if (addr == '') 
   			return false;		
		
		var invalidChars = '\/\'\\ ";:?!()[]\{\}^|';
		
		for(i = 0; i < invalidChars.length; i++) 
   			if(addr.indexOf(invalidChars.charAt(i), 0) > -1)
 				return false;     			
   							
		for(i = 0; i < addr.length; i++) 
   			if(addr.charCodeAt(i)>127)  
      				return false;
   						
		var atPos = addr.indexOf('@',0);	   		
		if (atPos == 0)    			
			return false;		
		
		if (addr.indexOf('@', atPos + 1) > - 1)    	
   			return false;		
		
		if (addr.indexOf('.', atPos) == -1) 
		   return false;
		
		if (addr.indexOf('@.',0) != -1) 
   			return false;

		if (addr.indexOf('.@',0) != -1)
   			return false;

		if (addr.indexOf('..',0) != -1) 
   			return false;

		var suffix = addr.substring(addr.lastIndexOf('.') + 1);
		if (suffix.length != 2 && suffix != 'com' && suffix != 'net' && suffix != 'org' && suffix != 'edu' && suffix != 'int' && suffix != 'mil' && suffix != 'gov' & suffix != 'arpa' && suffix != 'biz' && suffix != 'aero' && suffix != 'name' && suffix != 'coop' && suffix != 'info' && suffix != 'pro' && suffix != 'museum') 
  			return false;

		return true;
	}	
}

/**
 * TextArea object represents HTML textarea input and inherits from 
 * Element. There are no additional functions added.
 */
function TextArea(obj) {
	this.setObject(obj);
	
	this.setNumericOnly = function() {
		this.obj.onkeypress = blockAlpha;
	}
	
	this.obj.onkeypress = blockRestricted;
	
	this.isEmpty = function() {
		return this.getValue() == "";
	}
}


function Password(obj) {
	this.setObject(obj);
	
	this.setNumericOnly = function() {
		this.obj.onkeypress = blockAlpha;
	}
	
	this.obj.onkeypress = blockRestricted;
	
	this.isEmpty = function() {
		return this.getValue() == "";
	}
	
	this.isValidEmail = function validateEmail() {
		var addr = this.getValue();
		
		if (addr == '') 
   			return false;		
		
		var invalidChars = '\/\'\\ ";:?!()[]\{\}^|';
		
		for(i = 0; i < invalidChars.length; i++) 
   			if(addr.indexOf(invalidChars.charAt(i), 0) > -1)
 				return false;     			
   							
		for(i = 0; i < addr.length; i++) 
   			if(addr.charCodeAt(i)>127)  
      				return false;
   						
		var atPos = addr.indexOf('@',0);	   		
		if (atPos == 0)    			
			return false;		
		
		if (addr.indexOf('@', atPos + 1) > - 1)    	
   			return false;		
		
		if (addr.indexOf('.', atPos) == -1) 
		   return false;
		
		if (addr.indexOf('@.',0) != -1) 
   			return false;

		if (addr.indexOf('.@',0) != -1)
   			return false;

		if (addr.indexOf('..',0) != -1) 
   			return false;

		var suffix = addr.substring(addr.lastIndexOf('.') + 1);
		if (suffix.length != 2 && suffix != 'com' && suffix != 'net' && suffix != 'org' && suffix != 'edu' && suffix != 'int' && suffix != 'mil' && suffix != 'gov' & suffix != 'arpa' && suffix != 'biz' && suffix != 'aero' && suffix != 'name' && suffix != 'coop' && suffix != 'info' && suffix != 'pro' && suffix != 'museum') 
  			return false;

		return true;
	}	
}


/**
 * Select object represents an HTML select element.
 */
function Select(obj) {
	this.setObject(obj);	
	this.allowDuplicates = false;
	
	/**
	 * Checks length of options.
	 */
	this.getLength = function() {
		return this.obj.options.length;
	}
	
	/**
	 * Get soptions Array from select element
	 */
	this.getOptions = function() {
		return this.obj.options;
	}
	
	/**
	 * Checks if duplicate list values are allowed. Default
	 * is false.
	 */
	this.isAllowDuplicates = function() {
		return this.allowDuplicates;
	}
	
	/**
	 * Sets property allowing duplicate values for list
	 * options
	 */
	this.setAllowDuplicates = function(allowDuplicates) {
		this.allowDuplicates = allowDuplicates;
	}

	/**
	 * Checks if multiple selection are allowed
	 */
	this.isMultiple = function() {
		return this.obj.multiple;
	}
	
	/**
	 * Sets property allowing multiple selections.
	 */
	this.setMultiple = function(allowMultiple) {
		this.obj.multiple = allowMultiple;
	}
	
	/**
	 * Adds an option to a list. If list does not allow duplicates
	 * containsOption() will be invoked to verify.
	 */
	this.addOption = function(value, option) {		
		if(!this.isAllowDuplicates && this.containsOption(value)) {
			return false;
		}	
		
		this.obj.options[this.getLength()] = new Option(option, value);	
		
		return true;
	}
	
	/**
	 * Invokes indexOf() and removeOptionByIndex() to remove
	 * option.
	 */
	this.removeOption = function(value) {
		alert(this.indexOf(value));
		this.removeOptionByIndex(this.indexOf(value));
	}
		
	/**
	 * Will remove option at specified index.
	 */
	this.removeOptionByIndex = function(index) {			
		var temp = new Array();
		
		for(var i = 0, j = 0; i < this.obj.options.length; i++) 			
			if(i != index) 				
				temp[temp.length] = new Option(this.obj.options[i].text, this.obj.options[i].value);		
						
		this.obj.options.length = temp.length;
		var box = this.obj.options;
	
		for(var i = 0; i < temp.length; i++) 
			box[i] = temp[i];					
	}
	
	/**
	 * Finds index of option in list.
	 */
	this.indexOf = function(option) {
		for(var i = 0; i < this.obj.options.length; i++) 		
			if(this.obj.options[i].value.toUpperCase() == option.toUpperCase()) 
				return i;
					
		return -1;
	}
	
	/**
	 * Checks if this list contains specified option. 
	 * This is case-insensitive
	 */
	this.containsOption = function(option) {
		for(var i = 0; i < this.length; i++) 		
			if(this.obj.options[i].value.toUpperCase() == option.toUpperCase()) 
				return true;
					
		return false;
	}	
	
	/**
	 * Gets the first selected option
	 */
	this.getSelectedOption = function() {
		for(var i = 0; i < this.obj.length; i++) 		
			if(this.obj.options[i].selected) 
				return this.obj.options[i].value;
					
		return false;
	}
	
	this.getSelectedIndex = function() {
		for(var i = 0; i < this.obj.length; i++) 		
			if(this.obj.options[i].selected) 
				return i;
					
		return -1;
	}
	
	/**
	 * For lists with multiple selections allowed,
	 * gets Array of all selected option values
	 */
	this.getSelectedOptions = function() {
		var selectedOptions = new Array();
		for(var i = 0; i < this.obj.length; i++) 		
			if(this.obj.options[i].selected) 
				selectedOptions[selectedOptions.length] = this.obj.options[i].value;
					
		return selectedOptions;
	}
	
	this.setSelectedOption = function(value) {
		for(var i = 0; i < this.obj.length; i++) 		
			if(this.obj.options[i].value == value) 
				this.obj.options[i].selected = true;
			else
				this.obj.options[i].selected = false;			
	}
	
	/**
	 * Removes all selected options from list.
	 */
	this.removeSelected = function() {
		var selectedOptions = this.getSelectedOptions();
		
		for(var i = 0; i < selectedOptions.length; i++) 
			this.removeOption(selectedOptions[i]);		
	}
	
	this.createStatesList = function(selectedState) {
		this.addOption("none", "Select a state");
		for(var i = 0; i < states.length; i++) {
			this.addOption(states[i], states[i]);			
		}
		
		if(selectedState && selectedState.length > 3)
			this.setSelectedOption(selectedState);
		
	}
	
	/**
	 * This will sort the options in a list by the value, not text. First
	 * param determines order, desc or asc. Second parameter determines if
	 * we're sorting numerically. Ommitting both params will cause a normal
	 * ascending alphabetical sort.
	 */
	this.doSort = function(isDesc, isNumeric) {
		var sortingValues = new Array();
		var sortingText = new Array();
		for(var i = 0; i < this.obj.options.length; i++) {
			sortingValues[i] = this.obj.options[i].value;			
			sortingText[i] = this.obj.options[i].text;	
		}
		
		if(isNumeric) {
			sortingValues.sort((isDesc ? this.numSortDesc : this.numSortAsc));
		} else {
			if(isDesc) {
				sortingValues.sort(this.charSortDesc);
			} else {
				sortingValues.sort();
			}
		}
		
		var box = this.obj.options;

		for(var i = 0; i < this.obj.options.length; i++) {
			box[i] = new Option(sortingValues[i], sortingText[i]);	
		}	
	}
	
	/**
	 * This will swap two options in a list.
	 */
	this.swap = function(one, two) {
		if(one < 0 || two < 0 || one >= this.obj.options.length || two >= this.obj.length) 
			return;
			
		var option1 = this.obj.options[one];
		var option2 = this.obj.options[two];
		
		this.obj.options[one] = option2;
		this.obj.options[two] = option1;
	}
	
	/**
	 * Function needed to sort numeric values in ascending order.
	 */
	this.numSortAsc = function(a, b) {
		return a - b;
	}
	
	/**
	 * Function needed to sort numeric values in descending order.
	 */
	this.numSortDesc = function(a, b) {
		return b - a;
	}
	
	/**
	 * Function need to sort alphabetically in descending order.
	 */
	this.charSortDesc = function(a, b) {
		a = a.toLowerCase(); 
		b = b.toLowerCase();
		if(a < b) {
			return 1;
		}
		if (a >b) {
			return -1;
		}
		
		return 0;
	}	
}

function Checkbox(obj) {
	this.setObject(obj);
	
	/**
	 * Checks if Checkbox is checked.
	 */
	this.isChecked = function() {
		return this.obj.checked;
	}
	
	/**
	 * Sets checkbox to checked
	 */
	this.setChecked = function(checked) {
		this.obj.checked = checked;
	}
	
	/**
	 * Will toggle checked property
	 */
	this.toggleChecked = function() {
		this.obj.checked = !this.obj.checked;
	}
}

function RadioButton(obj) {
	this.setObject(obj);
}

function Hidden(obj) {
	this.setObject(obj);
}
function File(obj) {
	this.setObject(obj);
}

// Have fields inherit from Element
TextField.prototype = new Element();
TextArea.prototype = new Element();
Select.prototype = new Element();
Checkbox.prototype = new Element();
RadioButton.prototype = new Element();
Hidden.prototype = new Element();
File.prototype = new Element();

/**
 * Routine method to get HTML tag
 */
function getObject(id) {
	if(document.getElementById)
		return document.getElementById(id);
	else if(document.all)
		return document.all[id];
		
	return null;
}

function blockRestricted(e) {
	var keynum = -1;
	if(window.event) {
		keynum = window.event.keyCode;
	}
	else if(e.which) {
		keynum = e.which;	
	}	
	if(keynum > -1) {
		if(keynum == 60 || keynum == 62 || keynum == 92 || keynum == 94 || keynum == 126 || keynum == 96 || keynum == 123 || keynum == 125 || keynum == 91 || keynum == 93 || keynum == 43 || keynum == 61)
			return false;
	}
}

function blockAlpha(e) {	
	var keynum = -1;
	if(window.event) {
		keynum = window.event.keyCode;
	}
	else if(e.which) {
		keynum = e.which;	
	}	
	if(keynum > -1) {	
		if(((keynum < 45 || keynum > 57) && keynum != 8) || keynum == 47 || keynum == 45)
			return false;
		else
			return blockRestricted(e);
	}
}
