/* Objects that can be used to represent form elements */
var formCount;
				
function oForm (reference) {
	this.reference = reference;
	this.aFormElement = new Array ();
	this.parentform = this;
	var sIDforElements = 1;
}

oForm.prototype.addTextinput = function (maxLength, required, display, reference) {
	var elem = new oTextinput (maxLength, required,display,reference, this, this.parentform);
	this.aFormElement[this.aFormElement.length] = elem;
	elem.sID = ++this.SIDforElements;
	return elem;
}	

oForm.prototype.addSelect = function (required, display, reference) {
	var elem = new oSelect (required, display, reference, this, this.parentform);
	this.aFormElement[this.aFormElement.length] = elem;
	elem.sID = ++this.SIDforElements;
	return elem;
}

oForm.prototype.addTextarea = function (maxLength, required, display, reference) {
	var elem = new oTextarea (maxLength, required, display, reference, this, this.parentform);
	this.aFormElement[this.aFormElement.length] = elem;
	elem.sID = ++this.SIDforElements;
	return elem;
}

oForm.prototype.addRadioCollect = function (required, display, reference) {
	var elem = new oRadioCollect (required, display, reference, this, this.parentform);
	this.aFormElement[this.aFormElement.length] = elem;
	elem.sID = ++this.SIDforElemenets;
	return elem;
}

oForm.prototype.addCheckbox = function (requiredchecked, display, reference) {
	var elem = new oCheckbox (requiredchecked, display, reference, this, this.parentform);
	this.aFormElement[this.aFormElement.length] = elem;
	elem.sID = ++this.SIDforElemenets;
	return elem;
}

oForm.prototype.submithandle = function () {
	if (this.complete()) {
		return true;
	} else {
		return false;
	}
}

oForm.prototype.complete = function () {
	for (j=0;j<this.aFormElement.length;j++) {
		if (!this.aFormElement[j].complete()) {
			return false;
		}
	}
	return true;
}

oForm.prototype.selecthandle = selecthandle;

oForm.prototype.radiohandle = radiohandle;

function oTextinput (maxLength, required, display, reference, parent, parentform) {
	this.sID;
	this.type = "text";
	this.maxlength = maxLength;
	this.subtypecheck;
	this.required = required;
	this.display = display;
	this.reference = reference;
	this.parent = parent;
	this.parentform = parentform;
	this.hidden = false;
}
				
oTextinput.prototype.complete = text_complete;

oTextinput.prototype.addConfirm = function (maxLength, required, display, reference) {
	var elem = new oTextinput (maxLength, required, display, reference, this, this.parentform);
	this.child = elem;
	this.hasChild = true;
	elem.sID = ++this.SIDforElements;
	return elem;
} 

function oTextarea (maxLength, required, display, reference, parent, parentform) {
	this.sID;
	this.type = "textarea";
	this.maxlength = maxLength;
	this.required = required;
	this.display = display;
	this.reference = reference;
	this.parent = parent;
	this.parentform = parentform;
}

oTextarea.prototype.complete = textarea_complete;

function oRadioCollect (required, display, reference, parent, parentform) {
	this.sID;
	this.type = "radiocollect";
	this.required = required;
	this.display = display;
	this.reference = reference;
	this.parent = parent;
	this.parentform = parentform;
	this.aOptions = new Array ();
}

oRadioCollect.prototype.addRadioItem = function (reference) {
	var elem = new oRadioItem (reference, this, this.parentform);
	this.aOptions[this.aOptions.length] = elem;
	elem.sID = ++this.parentform.SIDforElements;
	return elem;
}

function oRadioItem (reference, parent, parentform) {
	this.reference = reference;
	this.hasChild = false;
	this.child;	
	this.parent = parent;
	this.parentform = parentform;
}

oRadioItem.prototype.addTextinput = function (maxLength, required, display, reference) {
	var elem = new oTextinput (maxLength, required, display, reference, this, this.parentform);
	this.child = elem;
	this.hasChild = true;
	elem.sID = ++this.SIDforElements;
	return elem;
}

oRadioCollect.prototype.complete = radiocollect_complete;

function oCheckbox (requiredchecked, display, reference, parent, parentform) {
	this.sID;
	this.type = "checkbox";
	this.requiredchecked = requiredchecked;
	this.display = display;
	this.reference = reference;
	this.parent = parent;
	this.parentform = parentform;
}

oCheckbox.prototype.complete = checkbox_complete;

function oSelect (required, display, reference, parent, parentform) {
	this.sID;
	this.type = "select";
	this.required = required;
	this.display = display;
	this.parent = parent;
	this.reference = reference;
	this.parentform = parentform;
	this.aOptions = new Array ();
}

oSelect.prototype.addSpecialOption = function (value, display) {
	var elem = new oOption (value, display, this, this.parentform);
	this.aOptions[this.aOptions.length] = elem;
	elem.sID = ++this.parentform.SIDforElements;
	return elem;
}

oSelect.prototype.complete = select_complete;

function oOption (value, display, parent, parentform) {
		this.value = value;
		this.display = display;
		this.child;
		this.hasChild = false;
		this.parent = parent;
		this.parentform = parentform;
}

oOption.prototype.addTextinput = function (maxLength, required, display, reference) {
	var elem = new oTextinput (maxLength, required, display, reference, this, this.parentform);
	this.child = elem;
	this.hasChild = true;
	elem.sID = ++this.SIDforElements;
	return elem;
}


// Actual (prototype) functions here to tidy code

/* Function to test if a checkbox has been completed (very limited function - just if a tick is required for completion */

function checkbox_complete () {
	if (this.requiredchecked) {
		var elem = getobjfrommodel (this);
		if (!elem.checked) {
			alert ("'" + this.display + "' must be checked.");
			return false;
		}
	}
	return true;
}	

/* Function to test if a collection of radio buttons has been completed */
function radiocollect_complete () {
	if (this.required) {
		if (this.aOptions.length!=null&&this.aOptions.length!=0) {
			var bolOneSelected=false;
			for(i=0;i<this.aOptions.length;i++) {
				var elem = getobjbyid (this.aOptions[i].reference);
				if (elem.checked) {
					bolOneSelected=true;
					if (this.aOptions[i].hasChild) {
						return (this.aOptions[i].child.complete());
					}
				}
			}
			if (!bolOneSelected) {
				alert ("'" + this.display + "' must be completed.");
				return false;
			}
		}
	}
	return true;
}

/* Function to test if a textarea object has been completed */
function textarea_complete () {
	var elem = getobjfrommodel(this);
	/* Check to see if required or not null */
	if (elem.value=="") {
		if (this.required){
			alert ("'" + this.display + "' must be completed.");
			elem.focus ();
			elem.select ();
			return false;
		}
	}
	/* Check max length */
	if (this.maxlength!=0) {
		if (elem.value.length > this.maxlength) {
			alert ("'" + this.display + "' must be less than " + this.maxlength + " characters long.");
			elem.focus ();
			elem.select ();
			return false;
		}
	}
	return true;
}

/* Function to test if a text-input object has been completed */
function text_complete () {
	var elem = getobjfrommodel(this);
	/* Check to see if required or not null */
	if (elem.value=="") {
		if (this.required&&!this.hidden) {
			alert ("'" + this.display + "' must be completed.");
			elem.focus ();
			elem.select ();
			return false;
		} else {
			return true;
		}
	}
	/* Check max length */
	if (this.maxlength!=0) {
		if (elem.value.length > this.maxlength) {
			alert ("'" + this.display + "' must be less than " + this.maxlength + " characters long.");
			elem.focus ();
			elem.select ();
			return false;
		}
	}
	/* Check email */
	if (this.subtypecheck=="email") {
		invalidChars = " /:,;";
		for (i=0; i<invalidChars.length; i++) {
			badChar = invalidChars.charAt(i)
			if (elem.value.indexOf(badChar, 0) > -1) {
				elem.focus ();
				elem.select ();
				alert ("'" + this.display + "' cannot contain '" + badChar + "'.");
				return false;
			}
		}
		atPos = elem.value.indexOf ("@",1);
		if (atPos == -1) {
			 elem.focus ();
			 elem.select ();
			 alert ("'" + this.display + "' must contain '@'.");
			 return false;
		}
		if (elem.value.indexOf("@", atPos+1) > -1) { 
			elem.focus ();
			 elem.select ();
			 alert ("'" + this.display + "' cannot contain more than one '@' symbol.");
			 return false;
		}
		periodPos = elem.value.indexOf(".", atPos)
		if (periodPos == -1) { 
			elem.focus ();
			elem.select ();
			alert ("'" + this.display + "' must contain '.'");
			return false;
		}
		if (periodPos+3 > elem.value.length) { 
			elem.focus ();
			elem.select ();
			alert ("'" + this.display + "' must be of the format 'name@xyzcorp.com'");
			return false;
		}
	}
	/* Check numeric */
	if (this.subtypecheck=="number"||this.subtypecheck=="integer") {
		if (isNaN(elem.value)){
			elem.focus ();
			elem.select ();
			alert("'" + this.display + "' must be a number.");
			return false;
		}
	}
	/* Check integer (subcase - will have already passed test for being numeric) */
	if (this.subtypecheck=="integer") {
		if (elem.value%1>0){
			elem.focus ();
			elem.select ();
			alert("'" + this.display + "' must be an integer.");
			return false;
		}
	}
	/* Check date */
	if (this.subtypecheck=="date") {
		var temp = Date.parse(elem.value);
		if (isNaN(temp)) {
			elem.focus ();
			elem.select ();
			alert("'" + this.display + "' must be a date.");	
			return false;
		}
	}
	/* Check parent-confirm fields */
	if (this.subtypecheck=="parentconfirm") {
		if (elem.value!=getobjfrommodel(this.parent).value) {
			alert("'" + this.display + "' must match '" + this.parent.display + "'.");
			return false;
		}
	}
	if (this.hasChild) {
		return this.child.complete();
	}
	return true;
}
/* Function to test if a select object has been completed */
function select_complete () {
	var elem = getobjfrommodel(this);
	/* check to see if not required */
	if (!this.required) {
		return true;
	} else {
		if ((elem.value).toLowerCase().substring(0,7)=="_system") {
				alert ("Please select a value for '" + this.display + "'.");
				elem.focus ();
				return false;
		}
		if (this.aOptions.length!=null&&this.aOptions.length!=0) {
			for (i=0; i<this.aOptions.length;i++){
				if (this.aOptions[i].hasChild) {
					if (!this.aOptions[i].child.complete()) {
						return false;
					}
				} 
			}
		}
	}
	return true;
} 
/* Function to check if visibility of select-->other form elements etc needs to be updated */
function selecthandle () {
	for (j=0;j<this.aFormElement.length;j++) {
		if (this.aFormElement[j].type=="select") {
			for (k=0;k<this.aFormElement[j].aOptions.length;k++) {
				if (this.aFormElement[j].aOptions[k].hasChild) {
					elem = getobjfrommodel (this.aFormElement[j].aOptions[k].child);
					if ((getobjfrommodel(this.aFormElement[j])).value!=this.aFormElement[j].aOptions[k].value) {
						elem.style.visibility="hidden";
						this.aFormElement[j].aOptions[k].child.hidden=true;
					} else {
						elem.style.visibility="visible";
						this.aFormElement[j].aOptions[k].child.hidden=false;
					}
				}
			}
		}
	}
}
/* Function to check if visibility of radiobutton-->other form elements etc needs to be updated */
function radiohandle () {
	for (j=0;j<this.aFormElement.length;j++) {
		if (this.aFormElement[j].type=="radiocollect") {
			for (k=0;k<this.aFormElement[j].aOptions.length;k++) {
				if (this.aFormElement[j].aOptions[k].hasChild) {
					elem = getobjfrommodel (this.aFormElement[j].aOptions[k].child);
					if (!(getobjbyid(this.aFormElement[j].aOptions[k].reference).checked)) {
						elem.style.visibility="hidden";
						this.aFormElement[j].aOptions[k].child.hidden=true;
					} else {
						elem.style.visibility="visible";
						this.aFormElement[j].aOptions[k].child.hidden=false;
					}
				}
			}
		}
	}
}
/* retrieving form object from model object */
function getobjfrommodel (mod) {
	return document[mod.parentform.reference][mod.reference];
}
/* retrieveing elements by id */
function getobjbyid (id) {
	return document.getElementById (id);
}