// This file is copyright 2003 feats.com limited. 
// Copying and/or distribution of this file in either its 
// original or modified form for any purpose whatsoever 
// without the agreement of feats.com limited is expressly
// forbidden. 

var FLD_UNDEFINED = 0;
var FLD_INTEGER = 3;
var FLD_BOOLEAN = 11;
var FLD_BYTE = 17;
var FLD_DATE = 135;
var FLD_TEXT = 202;
var FLD_MEMO = 203;

var FMT_BOOL_YES_NO = 1;
var FMT_BOOL_TRUE_FALSE = 2;
var FMT_BOOL_YES_NO_UNKNOWN = 3;
var FMT_BOOL_0_1 = 4;
var FMT_BOOL_MSACCESS = 5;
var FMT_BOOL_YES_NO_NO_DETAILS = 6;

var FMT_NULL_BLANK = 1;
var FMT_NULL_NOT_KNOWN = 2;
var FMT_NULL_NBSP = 3;
var FMT_NULL_UNDECIDED = 4;
var FMT_NULL_NO_DETAILS = 5;

var RE_WHITESPACE = /^\s+$/;
var	RE_SPECIAL_CHARS = /[^A-Za-z0-9'., -]+/gi;
var	RE_USER_TEXT_ENTRY_NOT_ALLOWED = /[^\sA-Za-z0-9()/?!\xA3&',.:+@*%;\x22-]/g; // \xA3 = £, \x22 = "
var RE_ESCAPE_CHARS = /(['|;|\\])/g;
var RE_QUOTE_TILDE_CARET = /[\"|~|^]/g;
var	RE_BREAK_AND_TABS = /\r\n/gi;
var RE_MONEY = /^((\d+[\,]\d{3})|(\d+))([.]\d{2})*$/;
var RE_CHARS_ONLY = /A-Za-z/;
var RE_INTEGER = /d*/;
var RE_NON_ZERO_INTEGER = /[1-9]+[0-9]*/;
var RE_NI_NUMBER = /[A-Za-z]{2}\d{6}[A-Za-z]{1}/;
var RE_VALID_DATE = /^[\d]{2}[\/][\d]{2}[\/][\d]{4}$/;
var RE_UTC_STRING = /\w+\s\w+\s\d+\s\d+[:]\d+[:]\d+\sUTC/i;
var RE_JS_CHARS = /([';\\])/g;

var CLASS_OBJECT = 'Object';
var CLASS_ARRAY = 'Array';
var CLASS_STRING = 'String';
var CLASS_FIELDACTION = 'FieldAction';

var CHAR_RS_NEWLINE = "¦";

checkRequiredFields = testElements;

function testElements(form, elements)
{
  var errors = '';
	var elements = (!isBlank(elements)) ? elements : form.elements;

  for(var i = 0; i < elements.length; i++) {
		var obj = elements[i];
		if (elementHasVal(obj, form)) {
			if(!isBlank(obj.regExp) && !obj.regExp.test(getElementVal(obj)))
				errors += obj.errorMessage + '\n';
			if (!isBlank(obj.validationFunction)) {
				if (! obj.validationFunction()) {
					errors += (!isBlank(obj.validationFunctionMessage)) ? obj.validationFunctionMessage + '\n' : '';
				}
			}
		}
  	else
			errors += (obj.required == true) ? obj.emptyMessage : '';
  }
  return (errors);
}

function setFieldProperties(obj, required, emptyMsg, errorMsg, regExp, source, categoryID, vFuncMsg, vFunc)
{
  obj.required = (!isBlank(required)) ? required : false;
	obj.emptyMessage = (!isBlank(emptyMsg)) ? emptyMsg : '';
	obj.errorMessage = (!isBlank(errorMsg)) ? errorMsg : '';
	obj.regExp = (!isBlank(regExp)) ? regExp : null;
	obj.datasource = (!isBlank(source)) ? source : null;
	obj.categoryID = (!isBlank(categoryID)) ? categoryID : null;
	// Gareth 29 Sept 2003
	// Extending setFieldProperties and testElements to
	// include a validation function
	// new field properties (arguments[7] and arguments[8]) validationFunctionMessage validationFunction
	//obj.validationFunctionMessage = (!isBlank(vFuncMsg)) ? vFuncMsg : null;
	//obj.validationFunction = (!isBlank(vFunc)) ? vFunc : null;
}

function isChanged(form) 
{
	var changed = false;
	var elements = (arguments.length >= 2) ? arguments[1] : form.elements;
	
	for (var i=0; i < elements.length; i++) {
		with (elements[i]) {
			if (type == 'text' || type == 'textarea' || type == 'password' || type == 'file' || type == 'hidden') {
	    		if (value != defaultValue)
						changed = true;
			}	
			else if (type == 'checkbox' || type == 'radio') {
					if (checked != defaultChecked)
						changed = true;
			}
	   		else if (type == 'select-one' || type == 'select-multiple') {
				if (!options[0].selected) {
	    			for (var j=0; j < options.length; j++) {
						if (options[j].selected != options[j].defaultSelected)
	      					changed = true;
	    			}
				}
			}
		}
	}
	return (changed);
}

function addSelectToAllSelects(theForm) {
	for (i = 0; i < theForm.elements.length; i++) {
		if (theForm.elements[i].type == 'select-one') {
			addSelectToSelect(theForm.elements[i]);
		}
	}
}

function addSelectToSelect(theSel) {
	newOption = document.createElement('<OPTION>');
	theSel.options.add(newOption, 0);
	newOption.value = "0";
	newOption.text = "Select...";
}

// Form routines
function joinSubForms(arrHTMLElements) {
	var arrSubForm = new Array();
	for (var i=0; i<arrHTMLElements.length; i++) {
		arrSubForm.concat(subFormArray(arrHTMLElements[i]))
	}
	return(arrSubForm);
}

function subFormArray(HTMLElement) {
	var theAll = (HTMLElement.all) ? HTMLElement.all : document.getElementById(HTMLElement).all;
	var arrSubForm = new Array();
	var j = 0;
	for (var i=0; i<theAll.length; i++) {
		if (theAll(i).tagName == 'INPUT' || theAll(i).tagName == 'SELECT' || theAll(i).tagName == 'TEXTAREA') {
			arrSubForm[j] = theAll(i);
			j++;
		}
	}
	return(arrSubForm);
}

function clearVals(elementsArray) {
	//alert('caller\n' + clearVals.caller + '\n' + elementsArray.toString());
	for (var i=0; i<elementsArray.length; i++) {
		obj = elementsArray[i];
		clearVal(obj);
	}
}

function clearVal(obj) {
	if (obj.type == 'checkbox') {
		obj.checked = false;
	} else if (obj.type == 'radio') {
		obj.checked = false;
	} else if (obj.type == 'select-one' || obj.type == 'select-multiple') {
		if (obj.size > 1) {
			obj.selectedIndex = -1;
		} else {
			obj.options[0].selected = true;
		}
	} else if (obj.type == 'hidden' || obj.type == 'text' || obj.type == 'password' || obj.type == 'textarea') {
		obj.value = '';
	} else if (obj.type == 'file') {
		// Only way to clear the value programmatically?
		obj.value = '';
		obj.outerHTML = obj.outerHTML;
	}
}

function clearOrZeroVals(elementsArray) {
	//alert('caller\n' + clearVals.caller + '\n' + elementsArray.toString());
	for (var i=0; i<elementsArray.length; i++) {
		obj = elementsArray[i];
		clearOrZeroVal(obj);
	}
}

function clearOrZeroVal(obj) {
	if (obj.type == 'checkbox') {
		obj.checked = false;
	} else if (obj.type == 'radio') {
		obj.checked = false;
	} else if (obj.type == 'select-one' || obj.type == 'select-multiple') {
		if (obj.size > 1) {
			obj.selectedIndex = -1;
		} else {
			obj.options[0].selected = true;
		}
	} else if (obj.type == 'hidden' || obj.type == 'text' || obj.type == 'password' || obj.type == 'textarea') {
		obj.value = '0';
	} else if (obj.type == 'file') {
		// Only way to clear the value programmatically?
		obj.value = '';
		obj.outerHTML = obj.outerHTML;
	}
}

//end

function Subform(els, msg) 
{
	function validate()
	{
		if (!isChanged(this)) {
			alert(this.errorMsg);
			return (false);
		}
		return (true);	
	}

	this.validate = validate;
	this.elements = els;
	this.errorMsg = msg;
}

function getElement(form, name, index)
{
	for (var i = 0; i < form.elements.length; i++)	{
		if (form.elements[i].name == name) {
			if (typeof(index) != 'number')
				return (form.elements[i]);
			else {
				var radio = getRadioCollection(form.elements[i]);
				return (radio[index]);
			}
		}
	}
	return (null);
}

function elementHasVal(obj, frm)
{
	if (obj.type == 'checkbox')
		return (obj.checked == true);
	else if (obj.type == 'radio') {
		var ri = getRadioIndex(getRadioCollection(obj, frm));
		return (ri != -1 && ri != null);
	}
	else if (obj.type == 'select-one' || obj.type == 'select-multiple') {
		return (obj.selectedIndex > 0);
	}
	else				
		return (!isWhitespace(obj.value));
}

function getElementVal(obj)
{
	if (obj != null) {
		if (obj.type == 'radio') {
			var radio = getRadioCollection(obj);
			for (var i=0; i < radio.length; i++) {
				if (radio[i].checked) 
					return (radio[i].value);
			}
		}
		else if (obj.type == 'checkbox' && obj.checked)
			return (obj.value);
		else if (obj.type == 'select-one' || obj.type == 'select-multiple') {
			if (obj.selectedIndex > -1) {
				return (obj.options[obj.selectedIndex].value);
			}
		}
		else if (obj.type != 'checkbox')
			return (obj.value);
	}
	return (null);
}

function getElementDefaultVal(obj)
{
	if (obj != null) {
		if (obj.type == 'radio') {
			var radio = getRadioCollection(obj);
			for (var i=0; i < radio.length; i++) {
				if (radio[i].defaultChecked) 
					return (radio[i].value);
			}
		}
		else if (obj.type == 'checkbox' && obj.defaultChecked)
			return (obj.value);
		else if (obj.type == 'select-one' || obj.type == 'select-multiple') {
			for (var i=0; i < obj.options.length; i++) {
				if (obj.options[i].defaultSelected == true)
					return (obj.options[i].value);
			}
		}
		else if (obj.type != 'checkbox')
			return (obj.defaultValue);
	}
	return (null);
}

function setElement(obj, val)
{
	val = (isBlank(val)) ? '' : val;
	if (!isBlank(obj)) {
		if (obj.type == 'radio' || obj.type == 'select-one' || obj.type == 'select-multiple') {
			var items = (obj.type == 'radio') ? getRadioCollection(obj) : obj.options;
			var set = false;
			for (var i = 0; i < items.length; i++) {
				var set = (items[i].value.toString() == val.toString());
				(obj.type == 'radio') ? items[i].checked = set : items[i].selected = set;
				if (set)
					return (true);
			}
			return (set);
		}
		else if (obj.type == 'checkbox') {
			obj.checked = (obj.value.toString() == val.toString());
			return (obj.checked);
		}
		else {
			obj.value = val;
			return (true);
		}
	}
	return (false);
}

function setElementDefault(obj, val, set)
{
	if (typeof(val) != 'undefined' && val != null) {
		if (obj.type == 'radio' || obj.type == 'select-one' || obj.type == 'select-multiple') {
			var items = (obj.type == 'radio') ? getRadioCollection(obj) : obj.options;
			var found = false;
			for (var i = 0; i < items.length; i++)
				(obj.type == 'radio') ? items[i].defaultChecked = false : items[i].defaultSelected = false;	
			for (var i = 0; i < items.length; i++) {
				found = (items[i].value.toString() == val.toString());
				(obj.type == 'radio') ? items[i].defaultChecked = found : items[i].defaultSelected = found;
				if (found)
					break;
			}
		}
		else if (obj.type == 'checkbox')
			obj.defaultChecked = (obj.value.toString() == val.toString());
		else
			obj.defaultValue = (val == null) ? '': val;
		if (typeof(set) != 'undefined')
			setElementToDefault(obj);
	}
}

function setElementToDefault(obj)
{
	if (obj.type == 'radio' || obj.type == 'select-one' || obj.type == 'select-multiple') {
		var items = (obj.type == 'radio') ? getRadioCollection(obj) : obj.options;
		for (var i = 0; i < items.length; i++) {
			if (obj.type == 'radio') 
				items[i].checked = items[i].defaultChecked;
			else {
			  items[i].selected = items[i].defaultSelected;
			}
		}	
	}
	else if (obj.type == 'checkbox')
		obj.checked = obj.defaultChecked;
	else
		obj.value = obj.defaultValue;
}

function getSelectText(obj) 
{
	return obj.options[obj.selectedIndex].text;
}

function getIndexInSelectOptions(text, obj) {
	var index = null;
	if (obj.options) {
		for (var i=0; i<obj.options.length; i++) {
			if (obj.options[i].text.toString() == text.toString()) {
				index = i;
				break;
			}
		}
	}
	return index;
}

function getSelectValFromSelectText(text, obj) {
	var index = null;
	if (obj.options) {
		for (var i=0; i<obj.options.length; i++) {
			if (obj.options[i].text == text) {
				index = i;
				break;
			}
		}
	}
	if (index) {
		return obj.options[index].value;
	} else {
		return null;
	}
}

function getSelectTextFromSelectVal(value, obj) {
	var index = null;
	if (obj.options) {
		for (var i=0; i<obj.options.length; i++) {
			if (obj.options[i].value.toString() == value.toString()) {
				index = i;
				break;
			}
		}
	}
	return obj.options[index].text;
}

function getRadioCollection(obj, frm)
{
	var form = (typeof(form) != 'undefined') ? frm : obj.form;
	with (obj.form)
		var radio = eval(obj.name);
	if (typeof(radio.length) == 'undefined')
		radio = [radio];
	return (radio);
}

function getRadioIndex(obj)
{
	var idx = -1;

 	for (var i = 0; i < obj.length; i++) {
 		if (obj[i].checked)
     	idx = i;
	}
	return idx;
}

function initialiseElements(elements, list)
{
	var fields = (isList(list, '~')) ? listToArray(list) : list;
	for (var i = 0; i < fields.length; i++) {
		var field = fields[i]; 
		for (var j = 0; j < elements.length; j++)	{
			if (field[0] == elements[j].name) {
				initialiseElement(elements[j], field[1], field[2]);
				break;
			}
		}
	}
}

function initialiseElement(obj, value, type)
{
	obj.actions = new Array();
	if (obj.type == 'textarea')
		value = reinstateNewLines(value, CHAR_RS_NEWLINE);
	(obj.initialise) ? obj.initialise(value) : setElementDefault(obj, value, true);
	if (isBlank(obj.datatype)) {
		type = (isBlank(type)) ? FLD_UNDEFINED : parseInt(type);
		if (obj.type == 'radio') {
			radio = getRadioCollection(obj);
			for (var i = 0; i < radio.length; i++)
				radio[0].datatype = type;
		}
		else
			obj.datatype = type;
	}
}

function blankElements(elements, toDefault)
{
	for (var i = 0; i < elements.length; i++) {
		blankElement(elements[i], toDefault);
	}
}

function blankElement(element, toDefault)
{
	if (element.type == 'radio') {
		var radio = getRadioCollection(element);
		for (var i = 0; i < radio.length; i++) {
			if (toDefault == true)
				radio[i].defaultChecked = false;
			radio[i].checked = false;
		}
	}
	else if (element.type == 'select-one' || element.type == 'select-multiple') {
		if (toDefault == true)
			element.options[0].defaultSelected = true;
		element.options[0].selected = true;
	}
	else if (element.type == 'checkbox') {
		if (toDefault == true)
			element.defaultChecked = false;
		element.checked = false;
	}
	else if (!(element.type == 'button' || element.type == 'submit' || element.type == 'reset')) {
		if (toDefault == true)
			element.defaultValue = '';
		element.value = '';
	}
}

function resetElements(elements)
{
	for(var i = 0; i < elements.length; i++)
		resetElement(elements[i]);
}

function resetElement(element)
{
	(element.reset) ? element.reset() : setElementToDefault(element);
	element.actions = new Array();
	element.required = false;
}

function setFormDisplay(form)
{
	for (var i = 0; i < form.elements.length; i++)
		triggerAction(form.elements[i]);
}

function FieldAction(op, trgs, shown, hidden, req, unreq, vcs, beh)
{
	function initialise(op, trgs, shown, hidden, req, unreq, vcs, beh)
	{
		this.classname = CLASS_FIELDACTION;
		this.fire = fire;
		this.test = test;
		this.show = show;
		this.hide = hide;
		this.change = change;
		this.behave = behave;
		this.require = require;
		this.unrequire = unrequire;
		this.setSource = setSource;
		this.addChanges = addChanges;
		this.addTriggers = addTriggers;
		this.addBehaviour = addBehaviour;
		
		this.source = null;
		this.operator = (isBlank(op)) ? '==' : op;
		this.shown = (isBlank(shown)) ? [] : shown;
		this.hidden = (isBlank(hidden)) ? [] : hidden;
		this.required = (isBlank(req)) ? [] : req;
		this.unrequired = (isBlank(unreq)) ? [] : unreq;
		this.changes = [];
		this.triggers = [];
		this.behaviour = [];
		this.addChanges(vcs);
		this.addTriggers(trgs);
		this.addBehaviour(beh);
	}


	function setDisplay(id, setting)
	{
		var tagname = id;

		if (id.indexOf('(') != -1 || id.indexOf('[') != -1) {
			var separator = (id.indexOf('(') != -1) ? '(' : '[';
			tagname = id.substring(0, id.indexOf(separator));
		}
		if (!isEmpty(document.getElementById(tagname)))	
			eval('document.all.' + id + '.style.display = "' + setting + '"');
	}

	function setFieldChange(vc, action)
	{
		if (isArray(vc)) {
			var value = (isEmpty(vc[1])) ? getElementVal(action.source) : eval(vc[1]);
			var target = vc[0];
			if (isBlank(vc[2]) || vc[2] == false) 
				setElement(target, value); 
			else
				initialiseElement(target, value);
		}
	}

	function setBehaviour(beh, action)
	{
		if (typeof(beh) == 'function') {
			action.temp = beh;
			action.temp();
			action.temp = null;
		}
	}

	function set(action, type, items, setting)
	{
		for (var i = 0; i < items.length; i++) {
			if (type == PROP_REQUIRE)
				items[i].required = setting;
			else if (type == PROP_SHOW)
				setDisplay(items[i], setting);
			else if (type == PROP_CHANGE)
				setFieldChange(items[i], action);
			else if (type == PROP_BEHAVE)
				setBehaviour(items[i], action);
		}	
	}

	function addProperties(preset, props)
	{
		props = (!isArray(props)) ? new Array(props) : props;
		for (var i = 0; i < props.length; i++) {
			if (!isEmpty(props[i]))
				preset[preset.length] = props[i];
		}
	}

	function addTriggers(trgs)
	{
		addProperties(this.triggers, trgs);
	}

	function addBehaviour(beh)
	{
		addProperties(this.behaviour, beh);
	}

	function addChanges(vcs)
	{
		addProperties(this.changes, vcs);
	}

	function setSource(obj)
	{
		this.source = obj;
	}

	function show(shown)
	{
		set(this, PROP_SHOW, shown, 'block');
	}

	function hide(hidden)
	{
		set(this, PROP_SHOW, hidden, 'none');
	}
	
	function change(vcs)
	{
		set(this, PROP_CHANGE, vcs);
	}

	function behave(beh)
	{
		set(this, PROP_BEHAVE, beh);
	}

	function require(flds)
	{
		set(this, PROP_REQUIRE, flds, true);
	}
	
	function unrequire(flds)
	{
		set(this, PROP_REQUIRE, flds, false);
	}

	function fire(ok)
	{
		if (isBlank(ok) || ok) {
			// debug
			//if (this.source.name == 'FATypeID') {
			//	alert('Debug: name= '+this.source.name+'\n this.triggers = '+this.triggers+'\n this.shown = '+this.shown+'\n this.hidden = '+this.hidden+'\n this.required = '+this.required+'\n this.unrequired = '+this.unrequired+'\n this.changes = '+this.changes+'\n this.behaviour = '+this.behaviour);
			//}
			this.show(this.shown);
			this.hide(this.hidden);
			this.change(this.changes);
			this.behave(this.behaviour);
			this.require(this.required);
			this.unrequire(this.unrequired);
		}
	}
	
	function test()
	{	
		if (this.source.type == 'checkbox') 
			this.fire(this.source.checked == this.triggers[0]);
		else {
			var val = getElementVal(this.source);
			var end = (isWhitespace(val) || isNaN(val)) ? "\' " : ' ';
			var start =	(isWhitespace(val) || isNaN(val)) ? " \'" : ' ';
			var logical = (this.operator == '==') ? '||' : '&&';
			if (this.triggers.length == 0)
				this.fire(true);
			else {
				var evalString = start + String(val).replace(RE_JS_CHARS, '\\'+'$1') + end + this.operator + start + this.triggers[0] + end;
				for (var i = 1; i < this.triggers.length; i++)
					evalString += ' ' + logical + start + String(val).replace(RE_JS_CHARS, '\\'+'$1').replace(RE_JS_CHARS, '\\'+'$1') + end + this.operator + start + this.triggers[i] + end;
				this.fire(eval(evalString));
			}	
		}
	}

	var PROP_SHOW = 1;
	var PROP_BEHAVE = 2;
	var PROP_CHANGE = 3;
	var PROP_REQUIRE = 4;
	var PROP_TRIGGER = 5;
	
	this.initialise = initialise;
	this.initialise(op, trgs, shown, hidden, req, unreq, vcs, beh);	
}

function addFieldAction(obj, actions)
{
	for (var i = 0; i < actions.length; i++) {
		actions[i].setSource(obj);
		obj.actions[obj.actions.length] = actions[i];
	}
}

function triggerAction(obj)
{
	if (!isBlank(obj.actions)) {
		for (var i = 0; i < obj.actions.length; i++) {
			obj.actions[i].test();
		}
	}
}

function getIndexInArray(value, array) {
	var index = null;
	for (i=0; i<array.length; i++) {
		if (array[i] == value) {
			index = i;
			break;
		}
	}
	return index;
}

function isInArray(value, array) {
	for (i=0; i<array.length; i++) {
		if (array[i].toString() == value.toString()) {
			return true;
		}
	}
	return false;
}

function displayArray(fieldArray)
{
	var tempStr = '';
	var i=0;
	for (i=0; i< fieldArray.length; i++)
		tempStr += fieldArray[i][0] + " : " + fieldArray[i][1] + "\n";
	return (tempStr);
}

function list3DArray(arr) {
	// theArray[] is the record row, theArray[][] is thearray for the field, [][][0] is name, [][][1] is value, [][][3] is type
	var i, j = 0;
	var strRow = '';
	var strTemp = '';
	for (i=0;i<arr.length;i++) {
		strRow += '\nrow '+i+'\n';
		for (j=0;j<arr[i].length;j++) {
			strTemp += '          name= '+arr[i][j][0]+' (arr['+i+']['+j+'][0]), value= '+arr[i][j][1]+' (arr['+i+']['+j+'][1]), type= '+arr[i][j][2]+' (arr['+i+']['+j+'][2]).\n';
		}
		strRow += strTemp+'\n';
		strTemp = '';
	}
	return strRow;
}

function arrayToList(array)
{
	var list = "";
	var caret = "";
	
	if (!(array == null))	{
		for (var i = 0; i < array.length; i++) {				// For each element in the 1st dimension of array
			list += caret;																// Create a caret separated item
			tilde = "";
			var itemArray = array[i];
			for (var j = 0; j < itemArray.length; j++) {	// For each element in the 2nd dimension of array
				list += tilde + formatString(itemArray[j]);		// Create a tilde separated item
				tilde = "~";
			}
			caret = "^";
		}
	}
	return (list);
}

function RecordObject(recordArray) {
	// RowColPropArray
	this.records = new Array();
	for (var i = 0; i < recordArray.length; i++) {
		this.records[i] = new RowObject(recordArray[i]);
	}
	return this;
	
	function RowObject(row) {
		for (var i = 0; i < row.length; i++) {
			// this.ColumnName = value - converted to string, integer or Date object by formatByDotNetType(column value, DataType))
			var val = formatByDotNetType(row[i][1], row[i][2]);
			var typ = val.constructor;
			var typstr = String(typ);
			if (typ == String) {
				eval("this." + row[i][0] + " = '" + val + "'");
			} else if (typ == Date) {
				eval("this." + row[i][0] + " = new Date()");
				var ev = eval("this." + row[i][0]);
				ev.setTime(val.getTime());
			} else {
				eval('this.' + row[i][0] + ' = ' + val);
			}
		}
		return this;
	}
}

function listRecordObject(recordObject) {
	var s = '';
	for (var i = 0; i < recordObject.records.length; i++) {
		s += 'Record ' + i + '. \n';
		for (var x in recordObject.records[i]) {
			s += x + '\n';
		}
	}
	return s;
}

function formatByDotNetType(val, type) {
	switch(type) {
		case 'System.DateTime':
			return parseDate(val);
		case 'System.Int32':
		case 'System.Byte': // Byte and Tinyint
			return parseInt(val, 10);
		case 'System.Decimal':
		case 'System.String':
		default:
			return String(val);
	}
}

function RecordArray(list) {
	return(listToRowColPropArray(list, '|', '^', '~'))
}

function listToRowColPropArray(list, rowSep, colSep, propSep) {
	//var rowSep = '', colSep = '', propSep = '';
	var rows = list.split(rowSep);
	for (var i = 0; i < rows.length; i++) {
		rows[i] = rows[i].split(colSep);
		for (var j = 0; j < rows[i].length; j++) {
			rows[i][j] = rows[i][j].split(propSep);
		}
	}
	return rows;
}

function listToArray(list) 
{
	var record = new Array();

	if (isList(list, '~')) {
		var arr = list.split('^');
		for (var i = 0; i < arr.length; i++) {
			var field = arr[i].split('~');
			record[record.length] = field;
		}
	} 
	return (record);
}

function elementsToArray(elements)
{
	var fields = new Array();
	var previous = '';
	for(var i = 0; i < elements.length; i++) {
		if (elements[i].name != previous) {
			var field = new Array(elements[i].name, getElementVal(elements[i]));
			if (!isBlank(elements[i].datatype))
				field[field.length] = elements[i].datatype;	
			fields[fields.length] = field;
		}
		previous = elements[i].name;
	} 
	return (fields);
}

function elementsToList(elements)
{
	return (arrayToList(elementsToArray(elements)));
}

function resetOptionsWithArray(targetObj, startIdx, twoDArray)
{
	targetObj.length = startIdx;

	for (var i=0; i < twoDArray.length; i++)
		targetObj.options[i + startIdx] = new Option(twoDArray[i][0],twoDArray[i][1]);
}

function rsResetSelectOptions(target, startIdx, source, defaultValue, selectValue)
{
	target.length = startIdx;
	var remScript = RSGetASPObject(rslibURL);
	var	cobj = remScript.rsGetOptionArray(source, defaultValue, selectValue);
	if (cobj.status != -1) {
		var rsOptions = cobj.return_value;
		for (var i = 0; i < rsOptions.length; i++) {
			var rsOption = rsOptions[i];
			target.options[i + startIdx] = new Option(rsOption[0], rsOption[1], rsOption[2], rsOption[3]);
		}
		return true;			
	}
	else {
		alert("There has been a problem getting options for " + target.name);
		return false;
	}
}

function rsGetORSArray(def) 
{
	var remScript = RSGetASPObject(rslibURL);
	var cobj = remScript.rsGetORSArray(def);
	if (cobj.status != -1)
		return (eval(cobj.return_value));
	else {
		//alert('Debug: cobj.data = '+cobj.data);
		return new Array();
	}
}

function setField(name, value, type)
{
	var field = new Array();
	field[0] = name;
	field[1] = (typeof(value) != 'undefined') ? value : 'No details';
	field[2] = (typeof(type) != 'number') ? FLD_TEXT : type;
	return (field);
}

function setRecord()
{
	var record = new Array();
	for (var i = 0; i < arguments.length; i++)
		record[record.length] = new Array(arguments[i][0], arguments[i][1], arguments[i][2]);
	return (record);
}

function setRecordset()
{
	var recordset = new Array();
	for (var i = 0; i < arguments.length; i++)
		recordset[recordset.length] = arguments[i];
	return (recordset);
}

function isWhitespace(str)
{
  return ((isBlank(str)) || (RE_WHITESPACE.test(str)));
}

function isEmpty(obj)
{
	return (typeof(obj) == 'undefined' || obj == null);
}

function isBlank(obj)
{  
	if (!isEmpty(obj)) {
		obj = obj + '';
		if (typeof(obj) == 'string')
			return (obj.length == 0 || obj == 'undefined' || obj == 'null');
		return (false);
	}
	return (true);
}

function oneOrOther(isVal, blankVal) {
	return (!isBlank(isVal)) ? isVal : blankVal;
}

function isDateObject(obj) {
// Gareth 39 Sept 2003
	if (obj != null && obj != 'undefined') {
		if (obj.constructor === new Date().constructor) {
			return true;
		}
	}
	return false;
}

function isClass(obj, classname)
{
	return (obj.constructor == Object);
}

function isArray(obj, d, len)
{
	var found = (!isBlank(obj) && obj.constructor == Array);

	if (!isBlank(d)) {
		d--;
		if (d < 0)
			return (!found);
		else if (d == 0)
			return (found && !isArray(obj[0]));
		else if (found && d > 0) {
			for (var i = 0; i < obj.length; i++) {
				if (!isArray(obj[i], d))
					return (false);
			}
			return (true);
		}
	}
	return ((!isBlank(len)) ? (found && len == obj.length) : found);
}

function isString(obj)
{
	return (typeof(obj) == 'string' || obj.constructor == String);
}

function isList(obj, delimiter)
{
	return (!isBlank(obj) && isString(obj) && obj.indexOf(delimiter) != -1)
}

function isInteger(obj) {
	if (isNaN(obj))
		return false;
	if (isNaN(parseInt(obj)))
		return false;
	if (isNaN(parseFloat(obj)))
		return false;
	if (parseInt(obj) != parseFloat(obj))
		return false;
	return true;
}

function zeroOrInt(val) {
	val *= 1;
	if (isInteger(val))
		return(val)
	else
		return(0);
}

function addEscapes(str)
{
	if (!(str == null || typeof(str) == 'undefined'))
	{
  	if (str.length > 0)
		{
  		var re = /(['|;|\\])/g;
  		return (str.replace(re, '\\'+'$1'));
  	}
 	}
	return(str);
}

function formatString(val)
{
	if (isString(val) && !isBlank(val))
		val = replaceNewLines(val.replace(RE_ESCAPE_CHARS, '\\'+'$1'), CHAR_RS_NEWLINE);
	return (val);
}

function formatBool(format, val)
{
	var value = String(val).toLowerCase();
	var yes = (value == 'true' || value == 'yes' || value == '1');
	var no = (value == 'false' || value == 'no' || value == '0');
	var unknown = (!yes && !no && !isBlank(value));

	if (format == FMT_BOOL_YES_NO_UNKNOWN && unknown)
		return ('Unknown');
	else if (format == FMT_BOOL_MSACCESS && (unknown || isBlank(value)))
		return ('false');
	else if (format == FMT_BOOL_YES_NO_NO_DETAILS && (unknown || isBlank(value)))
		return ('No details');
	else if (yes || no) {
		if (format == FMT_BOOL_YES_NO || format == FMT_BOOL_YES_NO_UNKNOWN || FMT_BOOL_YES_NO_NO_DETAILS)
			return ((yes) ? 'Yes' : 'No');
		else if (format == FMT_BOOL_TRUE_FALSE || FMT_BOOL_MSACCESS)
			return ((yes) ? 'true' : 'false');
	}
	return ('');
}

function formatNull(format, val) 
{
	if (isBlank(val))	{
		switch (format)	{
			case FMT_NULL_BLANK:
				return ('');
			case FMT_NULL_NOT_KNOWN:
				return ('Not known');
			case FMT_NULL_NBSP:
				return ('&nbsp\;');
			case FMT_NULL_UNDECIDED:
				return ('Undecided');
			case FMT_NULL_NO_DETAILS:
				return ('No details');
			default:
				return (new String(format));
		}
	}
	return (val);
}

function pad(str, len, char) 
{
	str = new String(str);
	char = new String(char.charAt(0));
	for (var i = 0; i < (len - str.length); i++)
		str = char + str;
	return (str);
}

function stripNewlines(str) {
	var newStr = '';
	for (i=0;i<str.length;i++) {
		if (!(str.charCodeAt(i) == 13 || str.charCodeAt(i) == 10)) {
			newStr += str.charAt(i);
		} else {
			newStr += ' ';
		}
	}
	return newStr.replace(/[ ]+/g, ' ');
}

function replaceNewLines(str, char) 
{
	var newStr = '';
	for (var i = 0; i < str.length; i++) {
		if (str.charCodeAt(i) == 13)
			newStr += char;
		else if (str.charCodeAt(i) != 10)
			newStr += str.charAt(i);
	}
	return (newStr);
}

function reinstateNewLines(str, char)
{
	var newStr = '';
	for (var i = 0; i < str.length; i++)
		newStr += (str.charAt(i) == char) ? String.fromCharCode(13,10) : str.charAt(i);
	return (newStr);
}

function cleanInput(str, textbox)
{
	var re = RE_USER_TEXT_ENTRY_NOT_ALLOWED;
	if (re.test(str)) {
		alert('You\'ve used a character which isn\'t allowed.');
		textbox.value = str.replace(re, '');
		return(RegExp.index);
	}
}

function memoLimit(theElement, theLimit) {
	var theText = theElement.value;
	if (theText.length > theLimit) {
		alert('The maximum number of keystrokes is '+theLimit+'.\nYou entered '+theText.length+' keystrokes.\nThe text will now be clipped to '+theLimit+' keystrokes.\n');
		theElement.value = theText.substring(0,theLimit);
	}
}

function textareaLimit() {
	// Uses global TEXTAREA_LIMIT DEFINED IN Application.js or PrototypeGlobals
	// Uses attribute/property maxlength or custom attribute textlimit or default global TEXTAREA_LIMIT
	var theElement = event.srcElement;
	var atrib = (theElement.getAttribute('maxlength')) ? theElement.getAttribute('maxlength') : theElement.getAttribute('textlimit');
	var limit = (!isBlank(atrib)) ? atrib : TEXTAREA_LIMIT;
	var theText = theElement.value;
	if (theText.length > limit) {
		alert('The maximum number of keystrokes is '+limit+'.\nYou entered '+theText.length+' keystrokes.\nThe text will now be clipped to '+limit+' keystrokes.\n');
		theElement.value = theText.substring(0,limit);
	}
}

function textareaEntryValidation() {
	// Uses global TEXTAREA_LIMIT DEFINED IN Application.js or PrototypeGlobals
	// Uses function cleanInput
	// Uses attribute/property textlimit or default global TEXTAREA_LIMIT
	// handler for onkeyup (keyboard entry and paste) and onfocus (drag and drop) events
	var del = 46, backspace = 8, shift = 16, leftArrow = 37, upArrow = 38, rightArrow = 39, downArrow = 40;
	var cursorPosition = null;
	if (event.keyCode != del && event.keyCode != shift && event.keyCode != leftArrow && event.keyCode != upArrow && event.keyCode != rightArrow && event.keyCode != downArrow) {
		var theTextarea = event.srcElement;
		var counterSpan = null;
		if (theTextarea.id) {
			// counterSpan = null if it doesn't exist.
			counterSpan = document.getElementById(theTextarea.id + 'CounterSPAN');
		}
		cursorPosition = cleanInput(theTextarea.value, theTextarea);
		var atrib = (theTextarea.getAttribute('maxlength')) ? theTextarea.getAttribute('maxlength') : theTextarea.getAttribute('textlimit');
		var limit = (!isBlank(atrib)) ? atrib : TEXTAREA_LIMIT;
		var len = event.srcElement.value.length;
		var charsRemaining = limit - len;
		if (counterSpan) {
			if (charsRemaining == limit) {
				counterSpan.innerHTML = '<BR>(Maximum ' + limit + ' keystrokes)';
			} else {
				counterSpan.innerHTML = '<BR><SPAN class=textBlue>' + charsRemaining + ' keystrokes remaining </SPAN> <BR>(Maximum ' + limit + ' keystrokes)';
			}
		}
		if (len >= limit) {
			if (len == limit) {
				if (event.type == 'keyup') {
					alert('You have now entered the maximum number of keystrokes ('+limit+') allowed in this text box.');
				}
			} else {
				alert('The maximum number of keystrokes is '+limit+'.\nYou entered '+len+' keystrokes.\nThe text will now be clipped to '+limit+' keystrokes.\n');
				theTextarea.value = theTextarea.value.substring(0, limit);
			}
		}
		if (cursorPosition != null) {
			var adjPos = theTextarea.value.substring(0, cursorPosition).replace(new RegExp("\n", "g"), '').length;
			var tr = theTextarea.createTextRange();
			tr.move('character', adjPos);
			tr.select();
		}
	}
}

function stripNonWordsAndDigits(inTxt) {
	if (isBlank(inTxt)) {
		return('');
	}
	var re = /[^\w\d]/gi;
	return(inTxt.replace(re, ''));
}

function getCookieVal(string, param, delim) {
	// returns value of param from string
	if (string.length == 0)
		return '';
	var sPos = string.indexOf(param + "=");
	if (sPos == -1)
		return '';
	sPos = sPos + param.length + 1;
	var ePos = string.indexOf(delim, sPos);
	if (ePos == -1)
		ePos = string.length;
	return unescape(string.substring(sPos, ePos));
}

function TableMenu(table, onclickClassName, onmouseoverClassName, onmouseoutClassName, rememberSelection) {
	this.Table = table;
	this.onclickFunc = onclickItem;
	this.onmouseoverFunc = onmouseoverItem;
	this.onmouseoutFunc = onmouseoutItem;
	this.showselectedFunc = showAsClicked;
	this.className = onmouseoutClassName;
	this.onclickClassName = onclickClassName;
	this.onmouseoverClassName = onmouseoverClassName;
	this.onmouseoutClassName = onmouseoutClassName;
	this.initialiseTableMenu = initialiseTableMenu;
	this.getMenuCookie = getMenuCookie;
	this.setMenuCookie = setMenuCookie;
	this.initialiseCell = initialiseCell;
	this.setTableHeight = setTableHeight;
	this.resetStyles = resetStyles;
	this.initialiseTableMenu();
	function initialiseTableMenu() {
		var tr, td;
		for (var i = 0; i < table.rows.length; i++) {
			tr = table.rows[i];
			for (var j=0; j<tr.cells.length; j++) {
				td = tr.cells[j];
				if (isBlank(td.className)) {
					initialiseCell(td, this);
				}
			}
		}
		if (rememberSelection) {
			this.showselectedFunc(stripNonWordsAndDigits(this.getMenuCookie()));
		}
	}
	function setTableHeight(theHeight) {
		var tr, td;
		var k = 0;
		var odds = 0;
		try {
			for (var i = 0; i < this.Table.rows.length; i++) {
				tr = this.Table.rows[i];
				if (tr.style.display != 'none') {
					k++;
				}
			}
			if (k > 0) {
				// deduct cellspacing from theHeight
				if (!isBlank(this.Table.cellSpacing)) {
					var cSp = parseInt(this.Table.cellSpacing);
					if (!isNaN(cSp)) {
						if (cSp > 0)
							theHeight -= (k + 1) * this.Table.cellSpacing; // (k + 1) is number of spaces
					}
				}
				// calculate the minimum row height from the number of displayed rows
				var minY = Math.floor(parseInt(theHeight, 10) / k);
				// calculate the number of odd pixels to add to rows
				odds = parseInt(theHeight, 10) % k;
				var rowHeight = minY;
				for (var i = 0; i < this.Table.rows.length; i++) {
					tr = this.Table.rows[i];
					if (tr.style.display != 'none') {
						if (odds > 0) {
							rowHeight = (i < odds) ? (minY + 1) : minY;
							odds--;
						}
					}
					for (var j=0; j<tr.cells.length; j++) {
						td = tr.cells[j];
						td.style.height = rowHeight;
					}
				}
			}
		} catch(e) {
		} finally {
		}
	}
	function initialiseCell(td, thisf) {
		//td.id = stripNonWordsAndDigits(td.innerText);
		td.onclick = thisf.onclickFunc;
		td.onmouseover = thisf.onmouseoverFunc;
		td.onmouseout = thisf.onmouseoutFunc;
		td.className = thisf.className;
		td.onclickClassName = thisf.onclickClassName;
		td.onmouseoverClassName = thisf.onmouseoverClassName;
		td.onmouseoutClassName = thisf.onmouseoutClassName;
	}
	function onclickItem(evalText, idText) {
		function sCookie(theInnerText) {
			document.cookie = new String(table.id)+'=' + theInnerText + '; path=/';
		}
		var theEl;
		if (!isBlank(idText)) {
			theEl = eval('document.all.' + idText)
		} else {
			theEl = window.event.srcElement;
		}
		if (rememberSelection) {
			sCookie(stripNonWordsAndDigits(theEl.innerText));
		}
		if (!isBlank(evalText)) {
			eval(evalText);
		} else {
			if (!isBlank(theEl.href)) {
				window.location = theEl.href;
				return;
			} else {
				try {
					eval('show' + stripNonWordsAndDigits(theEl.innerText) + '()');
				}
				catch(e) {
					//alert(e.name + ": " + e.message + '\n' + e.number + ": " + e.description + '\nThe function \'show' + stripNonWordsAndDigits(theEl.innerText) + ':\' is not available.\n');
				}
			}
		}
		with(theEl) {
			self.status = innerText;
			var tr, td;
			for (var i = 0; i < table.rows.length; i++) {
				tr = table.rows[i];
				for (var j=0; j<tr.cells.length; j++) {
					td = tr.cells[j];
					if (td.className == this.onclickClassName || td.className ==  this.onmouseoverClassName || td.className == this.onmouseoutClassName) {
						td.className = (td.contains(theEl)) ? this.onclickClassName : this.onmouseoutClassName;
					}
				}
			}
		}
		// Reset other related TableMenus if specified
		// Use:
		// var arrTableMenus = new Array('idOfTable', 'idOfTable', ... ) 
		if (window.arrTableMenus) {
			// only if the clicked TableMenu is part of the group
			if (isInArray(table.id, window.arrTableMenus)) {
				for (var i = 0; i < window.arrTableMenus.length; i++) {
					var tbl = eval('window.document.all.' + window.arrTableMenus[i]);
					// Dont reset the TableMenu that was clicked
					if (tbl.id != table.id) {
						var tr, td;
						for (var j = 0; j < tbl.rows.length; j++) {
							tr = tbl.rows[j];
							for (var k=0; k<tr.cells.length; k++) {
								td = tr.cells[k];
									if (td.className == tbl.menufunction.onclickClassName || td.className ==  tbl.menufunction.onmouseoverClassName || td.className == tbl.menufunction.onmouseoutClassName) {
										td.className = (td.contains(theEl)) ? tbl.menufunction.onclickClassName : tbl.menufunction.onmouseoutClassName;
									}
							}
						}
					}
				}
			}
		}
	}
	function onmouseoverItem() {
		with(window.event.srcElement) {
			if (className != this.onclickClassName) {
				className = this.onmouseoverClassName;
			}
			self.status = innerText;
		}
	}
	function onmouseoutItem() {
		with(window.event.srcElement) {
			if (className == this.onmouseoverClassName) {
				className = this.onmouseoutClassName;
			}
			self.status = '';
		}
	}
	function showAsClicked(idText) {
		if (!isBlank(idText)) {
			var tr, td;
			for (var i = 0; i < table.rows.length; i++) {
				tr = table.rows[i];
				for (var j=0; j<tr.cells.length; j++) {
					td = tr.cells[j];
					if (td.className == this.onclickClassName || td.className ==  this.onmouseoverClassName || td.className == this.onmouseoutClassName) {
						td.className = (stripNonWordsAndDigits(td.innerText) == idText) ? this.onclickClassName : this.onmouseoutClassName;
					}
				}
			}
		}
	}
	function resetStyles() {
		var tr, td;
		for (var i = 0; i < table.rows.length; i++) {
			tr = table.rows[i];
			for (var j=0; j<tr.cells.length; j++) {
				td = tr.cells[j];
				td.className = this.onmouseoutClassName;
			}
		}
	}
	function getMenuCookie() {
		var ck = getCookieVal(document.cookie, new String(table.id), ';');
		return (ck.length == 0) ? '' : ck;
	}
	function setMenuCookie(theInnerText) {
		document.cookie = new String(table.id)+'=' + theInnerText + '; path=/';
		return (this.getMenuCookie() != theInnerText) ? false : true;
	}
}

function getTextboxValue(ctrlName){
  var retVal = "";
  var inps = document.getElementsByTagName("INPUT");
 	  
  for(i = 0; i < inps.length; i++){
     if(inps[i].name.search(ctrlName) != -1)retVal = inps[i].value;
  }
	 
  return retVal;
}
