// Miscellaneous

// create crossbrowser element object
function xbObj(el)
{
	if(document.layers)
		return document.layers[el];
	else if(document.all)
		return document.all[el];
	else if(document.getElementById)
		return document.getElementById(el);
	else
		return false;
}

// DX:TEXT CONTROL ----------------------------------------------------------------------------------------------------------------------------------

function dxText() {
	// Inherits dxControl functionality.
	dxControl.call(this);
}


//Support function - not a control object.
function dxTextCounter(field, countfield, maxlimit) {
	var value;

	if(field) {
		if(field.getValue) {
			value = field.getValue();
		}
		else {
			value = field.value;
		}
		
		if(value.length > maxlimit) {
			var overage = value.length - maxlimit;
			var unit = (overage == 1) ? "character" : "characters";
			
	   	if(countfield.style.color != "red") 
				countfield.style.color = "red";
	   	if(countfield.innerHTML != "You are " + overage + " " + unit + " over the limit") 
				countfield.innerHTML = "You are " + overage + " " + unit + " over the limit";
		}
	   else {
	   	if(countfield.style.color != "#000") 
	   		countfield.style.color = "#000";
	   	if(countfield.innerHTML != (maxlimit - value.length)) 
	   		countfield.innerHTML = maxlimit - value.length;
	   }
	}
}



// DX:DROP-DOWN CONTROL ----------------------------------------------------------------------------------------------------------------------------------

function dxDropDown() {
	// Inherits dxControl functionality.
	dxControl.call(this);
	this.getCode = dxDropDown_getCode;
	this.getText = dxDropDown_getText;
	this.toXml = dxDropDown_toXml;
	this.getSortValue = dxDropDown_getSortValue;
}

function dxDropDown_getCode() {
	var index = this.selectedIndex;
	if(index == -1) {
		return("");
	}
	else {
		var item = this.options[index];
		if(item.code) {
			return(item.code);
		}
		else {
			return("");
		}
	}
}

function dxDropDown_getText() {
	var index = this.selectedIndex;
	if(index == -1) {
		return("");
	}
	else {
		var item = this.options[index];
		if(item.text) {
			return(item.text);
		}
		else {
			return("");
		}
	}
}

function dxDropDown_toXml() {
	if(!this.multiple) {
		// If this is NOT a multi-select list, then do the default behavior that dxControl does.
		return(dxControl_toXml.call(this));
	}
	else {
		// If this IS a multi-select list, then the output is different.
		var aXML = new Array();
		var name = (this.name ? this.name : this.id);
		var tagName = XMLEncodeName((name ? name : this.tagName));
		var bStructured = (this["xml-format"] == "structured");
		if(bStructured) {
			aXML.push("<" + tagName + ">");
		}
		var options = this.options;
		var valueTagName = (bStructured ? "Value" : tagName);
		for(var counter = 0; counter < options.length; counter++) {
			var option = options[counter];
			if(option.selected) {
				aXML.push(XMLEncodeElement(valueTagName, option.value, true));
			}
		}
		if(bStructured) {
			aXML.push("</" + tagName + ">");
		}
		return(aXML.join(""));
	}
}


// Returns the value to be used when sorting a series of these controls.
function dxDropDown_getSortValue() {
	var index = this.selectedIndex;
	if(index == -1 ) {
		return(null);
	}
	else {
		var item = this.options[index];
		if(item.DisplayOrder) {
			return(item.DisplayOrder);
		}
		else {
			return(item.text);
		}
	}
}

// dxFakeDropdown ----------------------------------------------------------------------------------
// <dx:drop-down edit-mode="table" ...>

	function dxFakeDropdown() {
	
		// Popup Management.
		this.displayPopup = dxFakeDropdown_displayPopup;
		this.hidePopup = dxFakeDropdown_hidePopup;
		this.popupVisible = dxFakeDropdown_popupVisible;
		this.updateText = dxFakeDropdown_updateText;
		this.togglePopup = dxFakeDropdown_togglePopup;

		// Mouse and keyboard event handling.
		this.onmousedown = dxFakeDropdown_onmousedown;
		this.ondblclick = dxFakeDropdown_onmousedown;
		this.onkeydown = dxFakeDropdown_onkeydown;
		this.ondragstart = function() {return(false);};		
		this.onmouseover = dxFakeDropdown_onmouseover;
		this.onmouseout = dxFakeDropdown_onmouseout;
		
		// Dropdown list manipulation.
		this.getContent = dxFakeDropdown_getContent;
		this.selectItem = dxFakeDropdown_selectItem;
		
		// Programmatic interface.
		this.getValue = dxFakeDropdown_getValue;
		this.setValue = dxFakeDropdown_setValue;
		this.getCode = dxFakeDropdown_getCode;
		this.setCode = dxFakeDropdown_setCode;
		this.getText = dxFakeDropdown_getText;
		this.toXml = dxFakeDropdown_toXml;
		this.setEnabled = dxFakeDropdown_setEnabled;
		this.raiseOnChanged = dxFakeDropdown_raiseOnChanged;
		this.getSortValue = dxFakeDropDown_getSortValue;
		this.getOptions = dxFakeDropDown_getOptions;
		this.setOptions = dxFakeDropDown_setOptions;

		// Cosmetic Behavior. (still needs work - flickers.)
		this.getButton = dxFakeDropDown_getButton;
		
		var Anchor = this.firstChild.firstChild;
		Anchor.onclick = dxFakeDropdown_Anchor_onclick;
		Anchor.onfocus = dxFakeDropdown_Anchor_onfocus;
		Anchor.onblur = dxFakeDropdown_Anchor_onblur;
		Anchor.getControlElement = dxFakeDropDown_Anchor_getControlElement;
		Anchor.onmouseenter = dxFakeDropDown_Anchor_onmouseenter;
		Anchor.onmouseout = dxFakeDropDown_Anchor_onmouseout;
		
		// Initialization.
		this.selectionColor = Anchor.style.color;
		this.getContent().multiple = this.multiple;
		if(typeof(this.onchange) == "string") this.onchange = new Function(this.onchange);

		if(!this.multiple) {
			if (this.value == "" && this["no-selection-text"]) {
				this.selectedIndex = -1;
			}
			else {
				this.setValue(this.value);
			}
		}
		else {
			this.selectedIndex = -1;
		}
		this.updateText();
		this.setEnabled(!this.disabled);
		this.previousValues = this.getValue();
		this.initialized = true;
	}

	/***************************************************
	Popup Management
	****************************************************/

	// Monitors the popup's visibility, raises certain events and cleans up when it is closed.
	// (This is not a method of the control.  Just a function that occurs in an "interval" when the popup is opened). 
	function dxFakeDropdown_checkPopup() {
		if(window.currentPopup) {
			if(!window.currentPopup.isOpen) {
				clearInterval(window.currentPopupTimer);
				window.currentPopup = null;
				if(window.currentFakeDropdown) {
					window.currentFakeDropdown.raiseOnChanged();
					window.currentFakeDropdown = null;
				}
			}
		}
		else {
			window.currentFakeDropdown = null;
		}
	}

	// Shows the popup window to display the dropdown list.
	function dxFakeDropdown_displayPopup() {
		var popup = window.popups[this.popupID];
		window.currentPopup = popup;
		window.currentFakeDropdown = this;
		popup.show(0, this.offsetHeight, 1, 1, this);
		var content = this.getContent();
		var table = content.firstChild;
		var rows = table.rows;
		var rowCount = rows.length;
		if(rowCount > 30) rowCount = 30;
		var lastVisibleRow = rows[rowCount - 1];
		var height;
		if(rowCount > 0)
			height = lastVisibleRow.offsetTop + lastVisibleRow.offsetHeight + 2;
		else
			height = 13;
			
		if(!this.optimalWidth) {
			this.optimalWidth = 0;
			for(var r = 0; r < rows.length; r++) {
				var rowWidth = 0;
				var row = rows[r];
				for(var c = 0; c < row.cells.length; c++) {
					var cell = row.cells[c];
					rowWidth += cell.scrollWidth + 8; // assume 4 pixels of padding on either side.
				}
				rowWidth += 20; // Add width of potential scroll bar.
				if(rowWidth > this.optimalWidth)
					this.optimalWidth = rowWidth;
			}
		}
		if(this.offsetWidth > this.optimalWidth) this.optimalWidth = this.offsetWidth;
		popup.show(0, this.offsetHeight, this.optimalWidth, height, this);
		window.currentPopupTimer = setInterval(dxFakeDropdown_checkPopup, 50);
		if(this.selectedIndex != -1) {
			content.highlightRow(this.selectedIndex);
			content.ensureVisible(table.rows[this.selectedIndex]);
		}
	}
	
	// Hides the popup window.
	function dxFakeDropdown_hidePopup() {
		window.popups[this.popupID].hide();
		if(!this.disabled) this.firstChild.focus();
	}
	
	// Returns whether the popup is currently visible.
	function dxFakeDropdown_popupVisible() {
		return(window.popups[this.popupID].isOpen);
	}
	
	function dxFakeDropdown_togglePopup() {
		if(!this.disabled) {
			if(!window.currentPopup) {
				this.getContent().highlightRow(this.selectedIndex);
				this.displayPopup();
			}
			else {
				this.hidePopup();
			}
		}
	}

	/***************************************************
	Mouse and Keyboard Event Handling
	****************************************************/
	
	//Show or hide the popup on a mouse click.
	function dxFakeDropdown_onmousedown() {
		if(event.button == 1) {
			this.togglePopup();
			event.cancelBubble = true;
		}
		return(false);	
	}
	
	// Handle keypresses.
	function dxFakeDropdown_onkeydown() {
		if(!this.disabled) {
			// Alt+Up or Alt+Down toggle the display of the popup.
			if(event.altKey && (event.keyCode == 40 || event.keyCode == 38)) {
				this.togglePopup();
				event.cancelBubble = true;
				return(false);
			}
			else {
				var inEditTable = false;
				if(event.keyCode == 40 || event.keyCode == 38) {
					var table = findParentByTagName(this, "TABLE");
					if(table) {
						var jsClass = table["js-class"];
						if(jsClass == "dxDataTable" || jsClass == "dxTreeTable") {
							inEditTable = true;
						}
					}
				}
			
				switch(event.keyCode) {
					// The up and down arrow keys change the selected item from the list.
					case 40: // Down.
						if(!inEditTable || this.popupVisible()) {
							this.selectItem(this.selectedIndex + 1);
							event.cancelBubble = true;
						}
						return(false);
						break;
					case 38: // Up.
						if(!inEditTable || this.popupVisible()) {
							if(this.selectedIndex > 0) {
								this.selectItem(this.selectedIndex - 1);
							}
							event.cancelBubble = true;
						}
						return(false);
						break;
	
					// The Enter key closes the list and commits the selection.				
					case 13: // Enter;
						if(this.popupVisible()) {
							this.hidePopup();
							this.raiseOnChanged();
							event.cancelBubble = true;
							return(false);
						}
						break;
					
					default:
						// If the key that is pressed is either a letter or a number, find the first (or next) item
						// in the list that starts with that character.
						if(!event.ctrlKey && !event.altKey && !event.shiftKey && String.fromCharCode(event.keyCode).search(/\w/) != -1) {
							var table = this.getContent().firstChild;
							var rows = table.rows;
							var re = new RegExp("^" + String.fromCharCode(event.keyCode), "i");
							var currentRowText = "";
							if(this.selectedIndex != -1) {
								currentRowText = rows[this.selectedIndex].innerText;
							}
							var start;
							// If the current row's text starts with the character that was typed
							if(currentRowText.search(re) != -1) {
								// then only search rows that are subsequent to this one.
								start = this.selectedIndex + 1;
							}
							else {
								// otherwise, start from the top.
								start = 0;
							}
							
							var rowCount = rows.length;
							// Examine the rows in the table.
							for(var i = 0; i < rowCount; i++) {
								var index = i + start;
								if(index >= rowCount) index -= rowCount;
								
								// Get the row's text.
								var text = rows[index].innerText;
								
								// If it matches the search expression...
								if(text.search(re) != -1) {
									// Select it and get out.
									this.selectItem(index);
									event.cancelBubble = true;
									return(false);
								}
							}
						}
						break;
				}
			}
		}
	}
	
	// onmouseover event handler for the dxFakeDropdown control
	// Note: this is overridden in dx-forms-fe.js
	function dxFakeDropdown_onmouseover() {
	}
	
	// onmouseover event handler for the dxFakeDropdown control
	// Note: this is overridden in dx-forms-fe.js
	function dxFakeDropdown_onmouseout() {
	}
	
	/***************************************************
	Dropdown List Manipulation
	****************************************************/
	// Returns the table element that presents the list.
	function dxFakeDropdown_getContent() {
		return(window.popups[this.popupID].document.body.firstChild);
	}
	
	// Highlights the specified list item, and sets the current value and selectionIndex.
	function dxFakeDropdown_selectItem(index) {
		var content = this.getContent();
		var table = content.firstChild;
		if(index == -1) {
			content.highlightRow(-1);
			this.lastChild.value = null;
			this.value = null;
			this.selectedIndex = -1;
			if(this.multiple == "1") {
				var rows = table.rows;
				for(var i = 0; i < rows.length; i++) {
					var row = rows[i];
					
					if(row.selected) {
						row.selected = null;
						row.firstChild.firstChild.checked = false;
						row.firstChild.firstChild.className = "GlobalImageList img_checkoff";
						row.style.backgroundColor = "";
					}
				}
			}
			this.updateText();
		}
		else {
			if(index < table.rows.length) {
				var rows = table.rows;

				if(this.multiple == "1") {
					for(var i = 0; i < rows.length; i++) {
						var row = rows[i];
						
						if(i == index) {
							row.selected = true;
							row.firstChild.firstChild.checked = true;
							row.firstChild.firstChild.className = "GlobalImageList img_checkon";
							row.style.backgroundColor = "#DBDFF9";
						}
						else {
							row.selected = false;
							row.firstChild.firstChild.checked = false;
							row.firstChild.firstChild.className = "GlobalImageList img_checkoff";
							row.style.backgroundColor = "";
						}
					}
				}

				var row = rows[index];
				content.highlightRow(index);
				this.value = row.value;
				this.lastChild.value = row.value;
				this.selectedIndex = index;
				this.updateText();
				content.ensureVisible(row);
			}
		}
		if(this.initialized && this.onchange && !this.popupVisible()) this.onchange();
	}
	
	function dxFakeDropdown_updateText() {
		if(this.multiple == "1") {
			var rows = this.getContent().firstChild.rows;
			var html = "";
			var text = "";
			var textSeparator = this["multiple-text-separator"];
			if(!textSeparator) textSeparator = ", ";
			var numSelected = 0;
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				if(row.selected) {
					numSelected ++;
				}
			}
			this.firstChild.firstChild.style.marginTop = "";
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				if(row.selected) {
					var textElement = row.lastChild;
					if(textElement) {
						if(html != "") html += textSeparator;
						html += (numSelected == 1 && row.image ? '<div class="GlobalImageList img_' + row.image + '" style="margin-top: -1px"></div>&#160;' : '') + textElement.innerHTML;
						if(text != "") text += textSeparator;
						text += textElement.innerText;
					}
					if(numSelected == 1 && row.image) {
						this.firstChild.firstChild.style.marginTop = "0px";
					}
				}
			}
			if(numSelected) {
				if(this["multiple-selection-text"] && numSelected > 1)
					this.firstChild.firstChild.innerText = this["multiple-selection-text"];
				else
					this.firstChild.firstChild.innerHTML = html;
				if (this["no-selection-color"])  this.firstChild.firstChild.style.color = this.selectionColor;
				this.title = text;
			}
			else {
				if(this["no-selection-text"]) {
					this.firstChild.firstChild.innerHTML = this["no-selection-text"];
					if(this["no-selection-color"]) {
						this.firstChild.firstChild.style.color = this["no-selection-color"];
					}
				}
				else {
					this.firstChild.firstChild.innerHTML = "";
				}
			}
			this.value = this.getValue();
			this.lastChild.value = this.value;
		}
		else {
			if(this.selectedIndex != -1 && !(this["no-selection-text"] && this.selectedIndex == 0)) {
				var row = this.getContent().firstChild.rows[this.selectedIndex];
				var html = "";
				if(row.image) {
					this.firstChild.firstChild.style.marginTop = "0px";
					html = '<div class="GlobalImageList img_' + row.image + '" style="margin-top: -1px"></div>&#160;';
				}
				else {
					this.firstChild.firstChild.style.marginTop = "";				}
				html += row.lastChild.innerHTML;
				this.firstChild.firstChild.innerHTML = html;
				this.title = row.lastChild.innerText;
				if (this["no-selection-color"])  this.firstChild.firstChild.style.color = this.selectionColor;
			}
			else {
				if(this["no-selection-text"]) {
					this.firstChild.firstChild.innerHTML = this["no-selection-text"];
					if(this["no-selection-color"]) {
						this.firstChild.firstChild.style.color = this["no-selection-color"]
					}
				}
				else {
					this.firstChild.firstChild.innerHTML = "";
				}
				this.title = "";
			}
		}
	}
	
	function dxFakeDropDown_getButton () {
		return this.children[1];
	}
	
	
	/***************************************************
	Programmatic Interface
	****************************************************/
	// Returns the "value" of the selected item.
	function dxFakeDropdown_getValue(delimiter) {
		if(this.multiple == "1") {
			var values = new Array();
			var rows = this.getContent().firstChild.rows;
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				if(row.selected) {
					values.push(row.value);
				}
			}
			if(!delimiter) delimiter = this["multiple-value-separator"];
			if(!delimiter || delimiter == "") delimiter = ",";
			return(values.join(delimiter));
		}
		else {
			return this.value;
		}
	}
	
	// Sets the selected item to the specified value.
	function dxFakeDropdown_setValue(value, delimiter, text) {
		var table = this.getContent().firstChild;
		var rows = table.rows;
		var values;
		if(this.multiple == "1") {
			if(typeof(value) != "object") {
				if(!delimiter) delimiter = this["multiple-value-separator"];
				if(!delimiter || delimiter == "") delimiter = ",";
				values = value.toString().split(delimiter);
			}
			else { 
				values = value;
			}
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				row.selected = false;
				var checkCell = row.cells[0];
				for(var v = 0; v < values.length; v++) {
					if(row.value.trim() == values[v].toString().trim()) {
						row.selected = true;
						break;
					}
				}
				if(row.selected) {
					row.style.backgroundColor = "#DBDFF9";
					checkCell.innerHTML = '<div class="GlobalImageList img_checkon" checked="true" cb="true"></div>';
				}
				else {
					row.stylebackgroundColor = "";
					checkCell.innerHTML = '<div class="GlobalImageList img_checkoff" cb="true"></div>';
				}
			}
			this.previousValues = this.getValue();
			this.updateText();
		}
		else {
			for(var i = 0; i < rows.length; i++) {
				if(rows[i].value == value) {
					this.selectItem(i);
					this.previousIndex = i;
					if(text) {
						var anchor = this.firstChild.firstChild;
						if(anchor.lastChild)
							anchor.lastChild.nodeValue = text;
						else
							anchor.innerText = text;
					}
					return;
				}
			}
			this.selectItem(-1);
			this.previousIndex = -1;
		}
		if(text) this.firstChild.firstChild.innerText = text;
	}
	
	// Returns the "code" of the selected item.
	function dxFakeDropdown_getCode() {
		if(this.selectedIndex != -1) {
			return(this.getContent().firstChild.rows[this.selectedIndex].code);
		}
		else {
			return("");
		}
	}

	// Returns the "text" of the selected item.
	function dxFakeDropdown_getText() {
		if(this.selectedIndex != -1) {
			return(this.getContent().firstChild.rows[this.selectedIndex].innerText);
		}
		else {
			return("");
		}
	}

	
	// Returns the value to be used when sorting a series of these controls.
	function dxFakeDropDown_getSortValue() {
		var index = this.selectedIndex;
		if(index == -1 ) {
			return(null);
		}
		else {
			var item = this.getContent().firstChild.rows[this.selectedIndex];
			if(item.DisplayOrder) {
				return(item.DisplayOrder);
			}
			else {
				return(item.innerText);
			}
		}
	}
	
	
	// Sets the selected item to the specified code.
	function dxFakeDropdown_setCode(code) {
		var table = this.getContent().firstChild;
		var rows = table.rows;
		for(var i = 0; i < rows.length; i++) {
			if(rows[i].code == code) {
				this.selectItem(i);
				return;
			}
		}
		this.selectItem(-1);
	}
	
	// Returns an XML representation of the item.
	function dxFakeDropdown_toXml() {
		if(!this.multiple) {
			return(XMLEncodeElement(this.name, this.value, true));
		}
		else {
			// If this IS a multi-select list, then the output is different.
			var aXML = new Array();
			var name = (this.name ? this.name : this.id);
			var tagName = XMLEncodeName((name ? name : this.tagName));
			var bStructured = (this["xml-format"] == "structured");
			if(bStructured) {
				aXML.push("<" + tagName + ">");
			}
			var valueTagName = (bStructured ? "Value" : tagName);
			var rows = this.getContent().firstChild.rows;
			for(var i = 0; i < rows.length; i++) {
				var row = rows[i];
				if(row.selected) {
					aXML.push(XMLEncodeElement(valueTagName, row.value, true));
				}
			}
			if(bStructured) {
				aXML.push("</" + tagName + ">");
			}
			return(aXML.join(""));
		}
	}

	// Enables or disables the control.
	function dxFakeDropdown_setEnabled(enabled) {
		this.disabled = !enabled;
		this.lastChild.disabled = !enabled;
		this.className = "dxFakeDropDown" + (enabled ? "" : " dxFakeDropDownDisabled");
	}

	// Raises the onchange event, it applicable.
	function dxFakeDropdown_raiseOnChanged() {
		var invokeSetDirty = false;
		if(this.multiple) {
			if(this.previousValues != this.getValue()) {
				this.previousValues = this.getValue();
				invokeSetDirty = true;
				if(this.onchange) {
					this.onchange();
				}
			}
			this.previousValues = this.getValue();
		}
		else {
			if(this.selectedIndex != this.previousIndex) {
				invokeSetDirty = true;
				if(this.onchange) {
					if(this.onchange() == false) {
						this.selectItem(this.previousIndex);
						invokeSetDirty = false;
					}
				}
				this.previousIndex = this.selectedIndex;
			}
		}
		if (invokeSetDirty) {
			setDirty();
		}
	}
	
	function dxFakeDropDown_getOptions() {
		var rows = this.getContent().firstChild.rows;
		var aOptions = new Array();
		for(var i = 0; i < rows.length; i++) {
			var row = rows[i];
			var Option = new Object();
			Option.value = row.value;
			Option.text = row.innerText;
			Option.title = row.title;
			Option.selected = row.selected;
			if(row.image) {
				Option.image = row.image;
			}
			aOptions.push(Option);
		}
		return(aOptions);
	}

	function dxFakeDropDown_setOptions(aOptions, bPreserveSelection) {
		var table = this.getContent().firstChild;
		var rows = table.rows;
		var selectedValues = new Object();
		var currentValue = this.getValue();
		this.optimalWidth = 0;
		while(rows.length) {
			if(bPreserveSelection) {
				if(rows[0].selected) {
					selectedValues[rows[0].value] = true;
				}
			}
			table.deleteRow(0);
		}
		var bNoSelectionOptionFound = false;
		var bHasImages = false;
		
		for(var i = 0; i < aOptions.length; i++) {
			if(aOptions[i].image) {
				bHasImages = true;
				break;
			}
		}
		
		for(var i = 0; i < aOptions.length; i++) {
			var Option = aOptions[i];
			var row = table.insertRow();
			var text;
			if(typeof(Option) == "string") {
				row.value = Option;
				text = Option;
			} 
			else {
				row.value = Option.value;
				text = (Option.text ? Option.text : (Option.description ? Option.description : Option.value));
			}
			if (!bNoSelectionOptionFound) {
				bNoSelectionOptionFound = (row.value == "");
			}

			if(bPreserveSelection)
				row.selected = selectedValues[row.value];
			else
				row.selected = Option.selected;
				
			if(bHasImages) {
				var imgCell = row.insertCell();
				if(Option.image) {
					row.image = Option.image;
					imgCell.innerHTML = '<div class="GlobalImageList img_' + Option.image + '"></div>';
				}
				else
					imgCell.innerHTML = '&#160;';
				
			}
			if(this.multiple == "1") {
				row.style.backgroundColor = "#DBDFF9";
				var checkCell = row.insertCell();
				if(row.selected)
					checkCell.innerHTML = '<div class="GlobalImageList img_checkon" checked="true"></div>';
				else 
					checkCell.innerHTML = '<div class="GlobalImageList img_checkoff"></div>';
			}
			var textCell = row.insertCell();
			textCell.innerText = text;
			row.onmouseover = dxFakeDropdownContentTableRow_onmouseover;
			row.onclick = dxFakeDropdownContentTableRow_onclick;
		}
		
		// in case embedded caption is requested, 
		// need to render a blank option, 
		// if it is not there already
		if (!bNoSelectionOptionFound) {
			if (this["no-selection-text"]) {
				row = table.insertRow(0);
				row.value = "";
				textCell = row.insertCell();
				textCell.innerText = " ";
				row.onmouseover = dxFakeDropdownContentTableRow_onmouseover;
				row.onclick = dxFakeDropdownContentTableRow_onclick;
			}
		}

		if(bPreserveSelection) {
			if(this.multiple) 
				this.updateText();
			else
				this.setValue(currentValue);
		}
	}
	
	/***************************************************
	Anchor Behavior
	****************************************************/
	//Cancel any click on the anchor.
	function dxFakeDropdown_Anchor_onclick() {
		return(false);
	}

	//Highlight the control when it receives focus.
	function dxFakeDropdown_Anchor_onfocus() {
		if(!this.getControlElement().noFocusHighlight) {
			with(this.style) {
				backgroundColor = "highlight";
				color = "highlighttext";
			}
		}
	}

	//Unhighlight the control when it loses focus.
	function dxFakeDropdown_Anchor_onblur() {
		var ctl = this.getControlElement();
		if(!ctl.noFocusHighlight) {
			with(this.style) {
				backgroundColor = "window";
				color = "windowtext";
			}
		}
		ctl.updateText();
	}
	
	function dxFakeDropDown_Anchor_getControlElement() {
		return this.parentNode.parentNode;
	}
	
	function dxFakeDropDown_Anchor_onmouseenter() {
		this.getControlElement().getButton().style.backgroundColor = "#E2E9FF";
	}
	
	function dxFakeDropDown_Anchor_onmouseout() {
		this.getControlElement().getButton().style.backgroundColor = "";
	}
	

// dxFakeDropdownContentWrapper -------------------------------------------------------------------------------------
/*
 * This class is for the DIV whose contents will be copied to a popup for use by dxFakeDropdown.
 */	
	
	var fakeDropdownStyles;
	
	function dxFakeDropdownContentWrapper() {
		if(!window.popups) window.popups = new Object();

		var popup = window.top.createPopup();
		var doc = popup.document;

		if(!fakeDropdownStyles) {
			fakeDropdownStyles = new Array();

			for (var s = 0; s < document.styleSheets.length; s++) { 
				var sheet = document.styleSheets[s];
				for(var r = 0; r < sheet.rules.length; r++) {
					var rule = sheet.rules[r];
					var selectorText = rule.selectorText;
					if(selectorText.indexOf("GlobalImageList") != -1 || selectorText.indexOf("img_") != -1 || selectorText.indexOf("dxFakeDropdown") != -1) {
						fakeDropdownStyles.push({selectorText: selectorText, cssText: rule.style.cssText});
					}
				}
			}
			fakeDropdownStyles.push({selectorText: ".GlobalImageList", cssText: "background-image: url(" + root + "/images/_GlobalImageList" + (is_ie7up ? ".png" : ".gif") + ")"});
		}

		var sheet = doc.createStyleSheet();
		// Copy the relevant styles from the current document into the Popup's document.
		for (var i=0; i < fakeDropdownStyles.length; i++) { 
			var rule = fakeDropdownStyles[i];
			if (!rule.cssText || rule.cssText == "") {
				rule.cssText = " ";
			}
			sheet.addRule(rule.selectorText, rule.cssText);
		}

		// Copy the contents of the DIV into the popup document.
		doc.body.innerHTML = this.innerHTML;

		// Apply the js-class to the popup internal table.
		dxFakeDropdownContent.call(doc.body.firstChild, window);

		// Store the popup.
		window.popups[this.id] = popup;
	}

	


// dxFakeDropdownContent ----------------------------------------------------------------------------------------
/*
 * This class assigns behavior to the "list" portion of the dxFakeDropdown.
 */	
	
function dxFakeDropdownContent(ownerWindow) {
	document.ownerWindow = ownerWindow;
	var table = this.firstChild;
	var rows = table.rows;
	for(var i = 0; i < rows.length; i++) {
		var row = rows[i];
		row.onmouseover = dxFakeDropdownContentTableRow_onmouseover;
		row.onclick = dxFakeDropdownContentTableRow_onclick;
	}
	this.highlightRow = dxFakeDropdownContent_highlightRow;
	this.onselectstart = dxFakeDropdownContent_onselectstart;
	this.ensureVisible = dxFakeDropdownContent_ensureVisible;
}

// Make sure that the selected item is visible within the scroll area of a long list.
function dxFakeDropdownContent_ensureVisible(row) {
	if(row) {
		if((row.offsetTop + row.offsetHeight - this.scrollTop) >= this.clientHeight)
			this.scrollTop = row.offsetTop + row.offsetHeight - this.clientHeight;
		if(row.offsetTop < this.scrollTop)
			this.scrollTop = row.offsetTop;
	}
}

// Prevent drag-and-drop text selection.
function dxFakeDropdownContent_onselectstart() {
	return(false);
}

// Highlight a row as the mouse hovers over it.
function dxFakeDropdownContentTableRow_onmouseover() {
	var div = this.parentNode.parentNode.parentNode;
	div.highlightRow(this.sectionRowIndex);
}

// Handle the click event.
function dxFakeDropdownContentTableRow_onclick() {
	var event = this.document.parentWindow.event;
	var srcElement = event.srcElement;
	var dropdown = document.ownerWindow.currentFakeDropdown;
	if(srcElement.tagName == "DIV" && srcElement.cb) {
		srcElement.checked = !srcElement.checked;
		srcElement.className = (srcElement.checked ? "GlobalImageList img_checkon" : "GlobalImageList img_checkoff");
		if(srcElement.checked) {
			this.selected = true;
			dropdown.selectedIndex = -1;
			this.style.backgroundColor = "#DBDFF9";
			this.style.color = "";
		}
		else {
			this.selected = null;
			this.style.backgroundColor = "";
			this.style.color = "";
		}
		dropdown.updateText();
	}
	else {
		if(dropdown) {
			dropdown.selectItem(this.sectionRowIndex);
			dropdown.hidePopup();
		}
	}
}

// Highlight the specified row, and remove highlighting from any other row.
function dxFakeDropdownContent_highlightRow(index) {
	var rows = this.firstChild.rows;
	for(var i = 0; i < rows.length; i++) {
		var row = rows[i];
		
		if(row.sectionRowIndex == index) {
			row.style.backgroundColor = "highlight";
			row.style.color = "highlighttext";
			if(!row.title) row.title = row.innerText;
		}
		else {
			if(this.multiple != "1" || !row.selected) {
				row.style.backgroundColor = "";
				row.style.color = "";
			}
			else {
				row.style.backgroundColor = "#DBDFF9";
				row.style.color = "";
			}
		}
	}
}




// DX:NUMBER CONTROL ----------------------------------------------------------------------------------------------------------------------------------
// Depends on code in DebtX.Formatting.js

function dxNumber() {
	// Inherits dxControl functionality.
	dxControl.call(this);
	
	this.dxNumber_base_getValue = this.getValue;
	this.getValue = dxNumber_getValue;
	this.formatValue = dxNumber_formatValue;
	this.unFormatValue = dxNumber_unFormatValue;
	
}

function dxNumber_getValue() {
	var val = this.dxNumber_base_getValue();
	var nVal = parseFloat(val);
	if(!isNaN(nVal))
		return(parseFloat(val));
	else
		return(val);
}

function dxNumber_formatValue(value) {
	var multiplier = this.multiplier;
	if(!multiplier || isNaN(multiplier)) multiplier = 1;

	if(!isNaN(value) && value != "") {
		value = parseFloat(value) / multiplier;
	}

	return(dxFormatNumber(value, this.getAttribute("decimal-places")));
}

function dxNumber_unFormatValue(value) {
	var multiplier = this.multiplier;
	if(!multiplier) multiplier = 1;
	
	var result = dxUnFormat(value);

	if(!isNaN(result) && result != "") {
		result = parseFloat(result) * multiplier;
	}
	return(result);
}



// DX:CURRENCY CONTROL --------------------------------------------------------------------------------------------------------------------------------
// Depends on code in DebtX.Formatting.js

function dxCurrency() {
	// Inherits dxControl functionality.
	dxControl.call(this);

	this.hiddenCurrencyInput = dxCurrency_hiddenCurrencyInput;
	this.hiddenRawValueInput = dxCurrency_hiddenRawValueInput;
	
	if(!this.getAttribute("currency")) this.setAttribute("currency", "USD");

	this.dxCurrency_base_getValue = this.getValue;
	this.getValue = dxCurrency_getValue;

	this.setCurrency = dxCurrency_setCurrency;
	this.formatValue = dxCurrency_formatValue;
	this.unFormatValue = dxCurrency_unFormatValue;
	this.oncurrencychanged = dxCurrency_oncurrencychanged;
}

function dxCurrency_hiddenCurrencyInput() {
	if(this.tagName.toUpperCase() == "INPUT") {
		return(this.nextSibling);
	}
	else {
		return(null);
	}
}

function dxCurrency_hiddenRawValueInput() {
	if(this.tagName.toUpperCase() == "INPUT") {
		return(this.nextSibling.nextSibling.nextSibling.nextSibling);
	}
	else {
		return(null);
	}
}



function dxCurrency_getValue() {
	var val = this.dxCurrency_base_getValue();
	var nVal = parseFloat(val);
	if(!isNaN(nVal))
		return(parseFloat(val));
	else
		return(val);
}

function dxCurrency_setCurrency(currency) {
		var tmp = this.getValue();
		//Update the hidden input control containing the additional currency info.
		this.setAttribute("currency", currency);
		if(this.hiddenCurrencyInput()) {
			this.hiddenCurrencyInput().value = currency;
		}
		this.setValue(tmp);
}

function dxCurrency_formatValue(value) {
	var multiplier = this.multiplier;
	if(!multiplier) multiplier = 1;

	if(!isNaN(value) && value != "") {
		value = parseFloat(value) / multiplier;
	}

	return(dxFormatCurrency(this.getAttribute("currency"), value, this.getAttribute("decimal-places"), false));
}

function dxCurrency_unFormatValue(value) {
	var multiplier = this.multiplier;
	if(!multiplier || isNaN(multiplier) || multiplier == "") multiplier = 1;
	
	var result = dxUnFormatCurrency(this.getAttribute("currency"), value);

	if(!isNaN(result) && result != "") {
		result = parseFloat(result) * multiplier;
	}
	return(result);
}

function dxCurrency_oncurrencychanged(CurrencyCode, SourceFieldName) {
	if(!this.CurrencyIDSibling || this.CurrencyIDSibling == SourceFieldName) {
		if(CurrencyCode == "NAV" || CurrencyCode == "VAR") {
			this.setCurrency("");
		}
		else {
			this.setCurrency(CurrencyCode);
		}
	}
}

// Setup RaiseCurrencyChangedEvent method on the document object.  If a currency selector changes its value, 
// it should call this method in its onchange event, and all dependent dxCurrency controls will be updated.
document.RaiseCurrencyChangedEvent = function(CurrencyCode, SourceFieldName) {
	var controlArrays = [
		this.getElementsByTagName("INPUT"),
		this.getElementsByTagName("DIV"),
		this.getElementsByTagName("SPAN"),
		this.getElementsByTagName("IFRAME")
	];
	
	for(var i = 0; i < controlArrays.length; i++) {
		var controls = controlArrays[i];
		for(var c = 0; c < controls.length; c++) {
			var control = controls[c];
			
			if(control.oncurrencychanged) {
				try {
					if(typeof(control.oncurrencychanged) == "string") {
						control.oncurrencychanged = new Function(control.oncurrencychanged);
					}
					control.oncurrencychanged(CurrencyCode, SourceFieldName);
				}
				catch(e){}
			}
		}
	}
}
	


// DX:PERCENT CONTROL --------------------------------------------------------------------------------------------------------------------------------

function dxPercent() {
	// Inherits dxControl functionality.
	dxControl.call(this);

	this.dxPercent_base_getValue = this.getValue;
	this.getValue = dxPercent_getValue;
	this.formatValue = dxPercent_formatValue;
	this.unFormatValue = dxPercent_unFormatValue;
}

function dxPercent_getValue() {
	var val = this.dxPercent_base_getValue();
	var nVal = parseFloat(val);
	if(!isNaN(nVal))
		return(parseFloat(val));
	else
		return(val);
}

function dxPercent_formatValue(value) {
	var strNum = value.toString().replace(/\s|%|,/g, "");
	var convert = this.getAttribute("convert");
	var decimalPlaces = this.getAttribute("decimal-places");

	if(isNaN(parseFloat(strNum)) || value.toString().length == 0) {
		return(value);
	}
	if(isNaN(parseInt(decimalPlaces))) {
		decimalPlaces=2;
	}
	
	var num = value.toString().replace(/%|\,/g,'');
	
	if(!(convert && convert == "no")) {
		num = num * 100.00;
	}
	return(dxFormatNumber(num, decimalPlaces, ",", ".") + (this.getAttribute("show-symbol") == "no" ? "" : "%"));
}

function dxPercent_unFormatValue(value) {
	var strNum = dxUnFormat(value, ".");
	var convert = this.getAttribute("convert");

	if(isNaN(parseFloat(strNum)) || strNum == "") {
		return(this.getControlValue());
	}
	
	if(convert && convert == "no") {
		return(parseFloat(strNum));
	}
	else {
		return(parseFloat(strNum) / 100);		
	}
}


// DX:DATE CONTROL --------------------------------------------------------------------------------------------------------------------------------

function dxDate() {
	// Inherits dxControl functionality.
	dxControl.call(this);
	
	//Setup the control accessors.
	if(this.tagName.toUpperCase() == "INPUT") {
		this.getCalendarButton = dxDate_getCalendarButton;
		var calendarButton = this.getCalendarButton();
		calendarButton.getInput = dxDate_calendarButton_getInput;
		calendarButton.pickDate = dxDate_calendarButton_pickDate;
		calendarButton.onclick = dxDate_calendarButton_onclick;
	}

	this.formatValue = dxDate_formatValue;
	this.unFormatValue = dxDate_unFormatValue;
	this.setVisible = dxDate_setVisible;
	this.toXml = dxDate_toXml;
	
	this.useRealPopup = (this.getAttribute("use-real-popup") == "true");
}

function dxDate_getCalendarButton() {
	return(this.parentNode.parentNode.getElementsByTagName("A")[0]);
}

function dxDate_formatValue(value) {
	if((new Date(value)).toString() != 'NaN') {
		if(value.indexOf(":") != -1) {
			return(dxFormatDateTime(value));
		}
		else {
			return(dxFormatDate(value));
		}
	}
	else {
		return(value);
	}
}

function dxDate_unFormatValue(value) {
	return(value);
}

function dxDate_setVisible(boolFlag) {
	var table = findParentByTagName(this, 'table');
	table.style.visibility = (boolFlag ? 'visible' : 'hidden');
}

function dxDate_calendarButton_getInput() {
	return(this.parentNode.parentNode.getElementsByTagName("INPUT")[0]);
}

function dxDate_calendarButton_pickDate(date) {
	this.getInput().setValue(date);
}

function dxDate_calendarButton_onclick() {
	var textbox = this.getInput();
	if (!textbox.disabled && !textbox.readOnly) {
		date = textbox.value;
		var cal = new dxCalendar(date);
		var field = textbox;
		cal.useRealPopup = field.useRealPopup;
		var dateOnly = true;
		cal.onDateSelected = function (value) {
			var originalDate;
			var originalTime = "";
			if(dateOnly) {
				if(!isNaN(date)) {
					originalTime = dxFormatDateTime(date, "%i:%N %p");
				}
			}
			field.setValue(dxFormatDateTime(value, "%Y-%M-%D" + (!dateOnly ? "\xA0\xA0" + originalTime : "")));
		}
		cal.selectDate(textbox, -2, textbox.offsetHeight);
	}
	return(false);
}

function dxDate_pad(value, num) {
	var padding = ""
	for(var c = 1; c <= num; c++) 
		padding += "0";
		
	padding += value;
	return(padding.substr(padding.length -num));
}

function dxDate_toXml() {
	if(this.isStatic()) return("");
	var value = this.getValue()
	var d = new Date(Date.parse(value));
	if(!isNaN(d.valueOf())) {
		value = dxDate_pad(d.getFullYear(), 4)
				+ "-" 
				+ dxDate_pad((d.getMonth()+1), 2)
				+ "-"
				+ dxDate_pad(d.getDate(), 2)
				+ (d.getHours() + d.getMinutes() + d.getSeconds() != 0 ? 
					"T"
					+ dxDate_pad(d.getHours(), 2)
					+ ":"
					+ dxDate_pad(d.getMinutes(), 2)
					+ ":"
					+ dxDate_pad(d.getSeconds(), 2)
					: 
					""
				);
	}
	return(XMLEncodeElement(this.name, value, true));
}

// DX:TIME CONTROL --------------------------------------------------------------------------------------------------------------------------------
function dxTime() {
	// Inherits dxControl functionality.
	dxControl.call(this);

	this.formatValue = dxTime_formatValue;
	this.unFormatValue = dxTime_unFormatValue;
}

function dxTime_formatValue(value) {
	if (value.indexOf(':') <1)
	{
		value = getNumbersOnly(value);
	}
	return(dxFormatTime(value));
}


function getNumbersOnly(strString)
	 //  check for valid numeric strings	
	 {
	 var strValidChars = "0123456789";
	 var strChar;
	 var retString
	 var stop = false;
	 var i = 0;
	 var hour = '';

	 if (strString.length == 0) return false;

	var pm = strString.indexOf('p');
	if (pm < 1)
	{
		pm = strString.indexOf('P');
	}
	var am = strString.indexOf('a');
	if (am < 1)
	{
		am = strString.indexOf('A');
	}
	 var iCount = 0;
	 for (i = 0; i < strString.length+1 && stop == false && i < 5; i++)
			{
			strChar = strString.charAt(i);
			if (strValidChars.indexOf(strChar) == -1)
				 {
				 stop = true;
				 }
			iCount = i;
			}
	 retString = strString.substr(0,iCount);
	 
				 if (retString.length < 3)
				 {
						hour = retString;
						hr = parseInt(hour);
						if (hr > 12)
						{
							hr = hr - 12;
							hour=hr.toString();
							pm = 1;
						}
						retString = hour+':00';
					}
					else
					{
						hour = retString.substr(0,retString.length-2);
						hr = parseInt(hour);
						if (hr > 12)
						{
							hr = hr - 12;
							hour=hr.toString();
							pm = 1;
						}
						retString = hour+':'+retString.substr(retString.length-2,2);
					}
					if (pm > 0)
						retString = retString + ' PM';
					else if (am > 0)
						retString = retString + ' AM';
					else
					{
						if ((hr > 6) && (hr < 12))
						{
							retString = retString + ' AM';
						}
						else
						{
							retString = retString + ' PM';
						} 
					}
					return(retString);
	 }

function dxTime_unFormatValue(value) {
	return(value);
}



// DX:PHONE CONTROL -------------------------------------------------------------------------------------------------------------------------
// Depends on code in DebtX.Formatting.js

function dxPhone() {
	// Inherits dxControl functionality.
	dxControl.call(this);

	this.formatValue = dxPhone_formatValue;
}

function dxPhone_formatValue(value) {
	return(dxFormatPhoneNumber('USCA', value));
}


// DX:SSN CONTROL -------------------------------------------------------------------------------------------------------------------------
// Depends on code in DebtX.Formatting.js

function dxSSN() {
	// Inherits dxControl functionality.
	dxControl.call(this);

	this.formatValue = dxSSN_formatValue;
}

function dxSSN_formatValue(value) {
	return(dxFormatSSN(value));
}


// DX:TEXT-AREA CONTROL ----------------------------------------------------------------------------------------------------------------------------------

function dxTextArea() {
	switch(this.tagName) {
		case "TEXTAREA":
			this.getValue = dxTextArea_textarea_getValue;
			this.setValue = dxTextArea_textarea_setValue;
			break;
			
		case "DIV":
			this.getValue = dxTextArea_div_getValue;
			this.setValue = dxTextArea_div_setValue;
			this.generateFormInput = dxTextArea_generateFormInput;
			
			if(this.value && this.childNodes.length == 0) {
				this.setValue(this.value);
			}
			break;			
	}
	this.isStatic = dxControl_isStatic;
	this.toXml = dxTextArea_toXml;
}

function dxTextArea_textarea_getValue() {
	return(this.value);
}
function dxTextArea_textarea_setValue(value) {
	this.value = value;
}

function dxTextArea_div_getValue() {
	return(this.innerText);
}
function dxTextArea_div_setValue(value) {
	this.innerText = value;
}

function dxTextArea_generateFormInput(dest, prefix) {
	var inp = document.createElement("input");
	inp.setAttribute("type", "hidden");
	inp.setAttribute("name", (prefix ? prefix : "") + (this.name ? this.name : this.id));
	inp.value = this.getValue();
	dest.insertAdjacentElement("BeforeEnd", inp);
}

function dxTextArea_toXml() {
	if(this.isStatic()) return("");
	return(XMLEncodeElement(this.name, this.getValue(), true));
}


// DX:RADIO CONTROL ----------------------------------------------------------------------------------------------------------------------------------
function dxRadio () {
	dxControl.call(this);
	this.toXml = dxRadio_toXml;
}

function dxRadio_toXml () {
	if(this.checked) {
		return(XMLEncodeElement(this.name, this.value, true));
	}
	else {
		return("");
	}
}

// DX:RADIO-GROUP CONTROL ----------------------------------------------------------------------------------------------------------------------------------
function dxRadioGroup () {
	this.getValue = dxRadioGroup_getValue;
	this.setValue = dxRadioGroup_setValue;
	this.setEnabled = dxRadioGroup_setEnabled;
	this.isStatic = dxControl_isStatic;
	this.toXml = dxRadioGroup_toXml;

	var options = this.parentNode.getElementsByTagName("input");
	for(var i = 0; i < options.length; i++) {
		var opt = options[i];
		if(opt.type == "radio") {
			if(opt.onclick) opt.dxRadioGroup_Item_OriginalOnClick = opt.onclick;
			opt.onclick = dxRadioGroup_Item_onclick;
		}
	}
}

function dxRadioGroup_Item_onclick() {
	var input = findParentByTagName(this, 'DIV').getElementsByTagName('INPUT')[0];
	input.value = this.value;
	if(input.onchange) input.onchange();
	if(this.dxRadioGroup_Item_OriginalOnClick) this.dxRadioGroup_Item_OriginalOnClick();
}

function dxRadioGroup_getValue() {
	var options = this.parentNode.getElementsByTagName("input");
	for(var i = 0; i < options.length; i++) {
		var opt = options[i];
		if(opt.type == "radio") {
			if(opt.checked) {
				return(opt.value);
			}
		}
	}
	return(null);
}

function dxRadioGroup_setValue(value) {
	var options = this.parentNode.getElementsByTagName("input");
	for(var i = 0; i < options.length; i++) {
		var opt = options[i];
		if(opt.type == "radio" && opt.value.toString() == value.toString()) {
			if(!opt.checked) {
				opt.click();
				return;
			}
		}
	}
}

function dxRadioGroup_setEnabled(enabled) {
	var options = this.parentNode.getElementsByTagName("input");
	for(var i = 0; i < options.length; i++) {
		var opt = options[i];
		if(opt.type == "radio") {
			opt.disabled = !enabled;
		}
	}
}

function dxRadioGroup_toXml() {
	if(this.isStatic()) return("");
	return(XMLEncodeElement(this.name, this.getValue(), true));
}


// DX:CHECKBOX CONTROL ----------------------------------------------------------------------------------------------------------------------------------

function dxCheckbox() {
	dxControl.call(this);
	this.toXml = dxCheckbox_toXml;
}

function dxCheckbox_toXml() {
	if(this.isStatic()) return("");
	if(this.checked) {
		return(XMLEncodeElement(this.name, this.getValue(), true));
	}
	else {
		return("<" + this.name + "/>");
	}
}

// DX:FRAME CONTROL ----------------------------------------------------------------------------------------------------------------------------------
function dxFrame() {
	this.loadContent = dxFrame_loadContent;
	this.toXml = dxFrame_toXml;
	if(this.load == "always") {
		this.contentLoaded = true;
	}
}

function dxFrame_loadContent() {
	this.src = this.contentUrl;
	this.contentLoaded = true;
}

function dxFrame_toXml() {
	if(!this.noxml) {
		var aXML = new Array();
		// Create the Frame element's opening tag, supplying the name attribute.
		aXML.push("<Frame " + XMLEncodeAttribute("name", this.name) + ">");
		
		// Recursively search for elements within the content document that can be converted to XML.
		aXML.push(dxForm_recurseToXML(this.contentWindow.document.body));
		
		// Create the form element's closing tag.
		aXML.push("</Frame>");
		
		// Merge the array into a single string.
		return(aXML.join(""));
	}
	else {
		return("");
	}
}

// DX:FILE CONTROL -----------------------------------------------------------------------------------------------------------------------------------

var dxFileUploadIDCounter = 0;

function dxFile() {
	this.extractFileName = dxFile_extractFileName;
	this.getDisplayValue = dxFile_getDisplayValue;
	this.getUploadID = dxFile_getUploadID;
	this.getValue = dxFile_getValue;
	this.setDisplayValue = dxFile_setDisplayValue;
	this.setBrowseMode = dxFile_setBrowseMode;
	this.toXml = dxFile_toXml;
	
	if(is_ie && !is_ie8up) {
		this.onkeypress = dxFile_onkeypress;
	}
}

function dxFile_getUploadID() {
	if(!this.uploadID) {
		dxFileUploadIDCounter ++;
		this.uploadID = "u" + dxFileUploadIDCounter + (new Date().valueOf().toString(36));
	}
	return this.uploadID;
}

function dxFile_toXml() {
	if(this.value.trim().length != 0) {
		xml = [];
		xml.push("<" + XMLEncodeName(this.name));
	
		xml.push(XMLEncodeAttribute("UploadID", this.getUploadID()));
		xml.push(XMLEncodeAttribute("ClientPath", this.value));
		xml.push(">" + XMLEncode(this.extractFileName(this.value)) + "</" + XMLEncodeName(this.name) + ">");

		return xml.join("");
	}
}

function dxFile_extractFileName(path) {
	if(path) {
		var tmpPath = path.replace(/[\\\/\:]/g, "/");
		var index = tmpPath.lastIndexOf("/");
		if(index != -1) {
			return tmpPath.substring(index + 1);
		}
		else {
			return path;
		}
	}
}

function dxFile_getValue() {
	return this.value;
}

function dxFile_getDisplayValue() {
	return this.extractFileName(this.getValue());
}

function dxFile_setDisplayValue(value) {
	// Can't actually set the value of the file input for security reasons.  But this will set the display value.
	var span = this.parentNode.parentNode;
	var span2 = span.nextSibling;
	var table = span2.getElementsByTagName("table")[0];
	var cell = table.tBodies[0].rows[0].cells[0];
	cell.innerText = value;
	cell.setAttribute("title", value);
	this.setBrowseMode(false);
}

function dxFile_setBrowseMode(browseMode) {
	var span = this.parentNode.parentNode;
	var span2 = span.nextSibling;
	
	if(browseMode) {
		span2.style.display = "none";
		span.style.display = "inline";
	}
	else {
		span.style.display = "none";
		span2.style.display = "inline";
	}
}

function dxFile_ReplaceButton_onclick() {
	var span2 = findParentByTagName(this, "span");
	var span = span2.previousSibling;
	span2.style.display = "none";
	span.style.display = "inline";
}

// Only used in IE7 or lower.  In IE8 and up, this behavior is built-in.  Also built-in to other browsers.
function dxFile_onkeypress() {
	return false;
}


//dx:simple-data-table -------------------------------------------------------------------------------------------------------------------------

function dxSimpleDataTable() {
	this.toXml = dxSimpleDataTable_toXml;
	this.addRow = dxSimpleDataTable_addRow;
	this.deleteRow = dxSimpleDataTable_deleteRow;
	this.getCurrentRow = dxSimpleDataTable_getCurrentRow;
	this.getCurrentRowFields = dxSimpleDataTable_getCurrentRowFields;
	this.getRowFields = dxSimpleDataTable_getRowFields;
	this.setRowEnabled = dxSimpleDataTable_setRowEnabled;
}

function dxSimpleDataTable_getCurrentRow(element) {
	var tr = findParentByTagName(element, "tr");
	return tr;
}

// Gets all the fields in the same row as the specified element.
function dxSimpleDataTable_getCurrentRowFields(element) {
	return this.getRowFields(this.getCurrentRow(element));
}

// Gets all the inputs, selects, and textareas in the specified row.
// Returns an array that is also indexed by field name.
function dxSimpleDataTable_getRowFields(tr) {
	var fields = [];
	var tags = ["input", "select", "textarea"];
	
	for(var t = 0; t < tags.length; t++) {
		var elements = tr.getElementsByTagName(tags[t]);
		for(var i = 0; i < elements.length; i++) {
			var element = elements[i];
			fields[element.name] = element;
			fields.push(element);
		}
	}
	return fields;
}

// Enables or disables a row and all the inputs within.
function dxSimpleDataTable_setRowEnabled(tr, enabled) {
	tr.disabed = !enabled;
	var fields = this.getRowFields(tr);
	for(var i = 0; i < fields.length; i++) {
		var fld = fields[i];
		if(fld.setEnabled) 
			fld.setEnabled(enabled);
		else if(fld.setDisabled)
			fld.setDisabled(!enabled);
		else
			fld.disabled = !enabled;
	}
}


function dxSimpleDataTable_toXml(useAttributes) {
	if(this.getAttribute("no-xml") == "true") {
		return "";
	}
	
	if(useAttributes == undefined) {
		useAttributes = (this.getAttribute("save-fields-as") == "attributes");
	}
	
	var xml = new Array();	
	var elementName = XMLEncodeName(this.id);
	var rowElementName = this.getAttribute("data-element-name");
	if(!rowElementName) rowElementName = "Row";
	rowElementName = XMLEncodeName(rowElementName);
	xml.push("<" + elementName + ">");
	
	var row = this.tBodies[0].rows[0];
	while(row) {
		if(row.nodeType == 1) {
			xml.push("<" + rowElementName + ">");
			
			xml.push(dxForm_recurseToXML(row));
					
			xml.push("</" + rowElementName + ">");
		}
		row = row.nextSibling;
	}
	xml.push("</" + elementName + ">");
	
	return xml.join("");
}

function dxSimpleDataTable_addRow() {
	var newRow = this.tBodies[1].rows[0].cloneNode(true);
	this.tBodies[0].appendChild(newRow);
	setupJSClasses(newRow, true);
	if(this.onNewRowAdded) this.onNewRowAdded(newRow);
}

function dxSimpleDataTable_deleteRow(row) {
	row.parentNode.removeChild(row);
	if(this.onRowDeleted) this.onRowDeleted(row);
}


/*********************************************************************************************************************************
dxCalendar
**********************************************************************************************************************************
Popup calendar. IE Only for now, but could easily be made multi-browser by using an iframe instead of createPopup in other 
browsers.
**********************************************************************************************************************************/
function dxCalendar(currentDate) {
	if(!currentDate) 
		this.currentDate = new Date();
	else {
		var dateValue = Date.parse(currentDate);
		if(isNaN(dateValue)) 
			this.currentDate = new Date();
		else
			this.currentDate = new Date(dateValue);
	}
		
	this.monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

	this.toString = function (year, month) {
		var a = [];
		
		if(!year) year = this.currentDate.getFullYear();
		if(!month) month = this.currentDate.getMonth() + 1;
		var numWeeks = this.getNumWeeksInMonth(year, month);
		var firstDay = this.getFirstDayOfMonth(year, month);
		var today = new Date();
		return '<html>\
					<head>\
						' + this.renderHeaderContent() + '\
					</head>\
					<body style="margin: 0px; border: 1px solid black;" scroll="no" onselectstart="return false;" ondragstart="return false;">\
						' + this.renderBodyContent(year, month) + '\
					</body>\
				</html>\
				';
	}
	
	this.renderHeaderContent = function (year, month) {
		return '<style type="text/css"> \
					select { font: 8pt tahoma; font-weight: bold; width: 100%;} \
					tr.week { height: 17px; }\
					tr.week a { width: 100%; height: 100%; padding-left: 5px; padding-right: 5px; padding-top: 2px; padding-bottom: 2px; color: blue;} \
					tr.week a:hover { background-color: #D5DCFF; color: black;} \
					td { font: 8pt tahoma; text-align: right; padding: none;} \
					td.today a { border: 1px solid darkred; }  \
					td.selected a { background-color: darkblue; color: white; }  \
					tr.Month td { font-weight: bold; text-align: center; padding: 2px; }  \
					tr.Header td { border-bottom: 1px solid black; text-align: center; padding-top: 5px;}  \
					td.Weekend { background-color: #dddddd; }  \
					td.nextMonth a, td.lastMonth a { color: #909090; }  \
					input { font: 8pt tahoma; border: 1px raised; height: 25px; }  \
				</style> \
				';
	}
	
	this.renderBodyContent = function(year, month) {
		var a = [];
		
		if(!year) year = this.currentDate.getFullYear();
		if(!month) month = this.currentDate.getMonth() + 1;
		var numWeeks = this.getNumWeeksInMonth(year, month);
		var firstDay = this.getFirstDayOfMonth(year, month);
		var today = new Date();
		a.push('<form name="frmCalendar"> \
				<table cellspacing="0" cellpadding="0" width="100%" height="100%"> \
				<tr class="Month">\
				<td colspan="4" align="center"> \
					<select name="Month" onchange="document.owner.refreshPopup(parseInt(frmCalendar.Year.value), parseInt(frmCalendar.Month.value) + 1);">');
						for(var i = 0; i < 12; i++) {
							a.push('<option value="' + i + '"' + (i == month-1 ? ' selected': '') + '>' + this.monthNames[i] + '</option>'); 
						}				
						a.push('\
					</select> \
				</td>\
				<td colspan="3" align="center"> \
					<select name="Year" onchange="document.owner.refreshPopup(parseInt(frmCalendar.Year.value), parseInt(frmCalendar.Month.value) + 1);">')
						for(var i = year - 20; i <= year + 40; i++) {
							a.push('<option value="' + i + '"' + (i == year ? ' selected' : '') + '>' + i + '</option>');
						}	
						a.push(' \
					</select> \
				</td></tr> \
				<tr class="header"><td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td><td>S</td></tr>');
		var day = -firstDay + 1;

		for(var week = 0; week < numWeeks; week++) {
			a.push('<tr class="Week">');
			for(var i = 0; i < 7; i++) { 
				var date = new Date(year, month - 1, day);
				var className = "";
				if(i == 0 || i == 6) className += "weekend";
				if(date.getMonth() < month - 1)	className += " lastMonth";
				if(date.getMonth() > month - 1)	className += " nextMonth";
				if(date.getMonth() > month - 1)	className += " nextMonth";
				if(new Date(this.currentDate.getFullYear(), this.currentDate.getMonth(), this.currentDate.getDate()).toString() == date.toString()) className += " selected";

				if(new Date(today.getFullYear(), today.getMonth(), today.getDate()).toString() == date.toString()) className += " today";
				
				a.push('<td' + (className != '' ? ' class="' + className + '"' : '') + '><a href="#" onclick="document.owner.popupWindow.hide(); if(document.owner.onDateSelected) document.owner.onDateSelected(new Date(' + date.getFullYear() + ',' + date.getMonth() + ',' + date.getDate() + ')); return false;">' + date.getDate() + '</a></td>');
				day ++;
			}
			a.push('</tr>');
		}
		a.push('\
			<tr height="100%"><td colspan="7" align="middle" valign="bottom"><input type="button" value="Today" style="width: 100%;" onclick="document.owner.popupWindow.hide(); if(document.owner.onDateSelected) document.owner.onDateSelected(new Date(' + today.getFullYear() + ',' + today.getMonth() + ',' + today.getDate() + '));"></input></td></tr> \
			</table> \
			</form> \
		');
		return a.join("");
	}
	
	this.getNumDaysInMonth = function(year, month) {
		return new Date(year, month, 0).getDate();
	}
	
	this.getFirstDayOfMonth = function (year, month) {
		return new Date(year, month-1, 1).getDay();
	}
	
	this.getNumWeeksInMonth = function(year, month) {
		var numDaysInMonth = this.getNumDaysInMonth(year, month);
		var firstDayOfMonth = this.getFirstDayOfMonth(year, month);
		return Math.ceil((numDaysInMonth + firstDayOfMonth) / 7);
	}
	
	this.selectDate = function (owner, left, top) {
		if(is_ie7up || (is_ie6 && this.useRealPopup)) {
			this.popupWindow = window.createPopup();
			this.popupWindow.document.write(this.toString());
		}
		else {
			this.popupWindow = fake_createPopup();
			this.popupWindow.document.open();
			this.popupWindow.document.write(this.toString());
			this.popupWindow.document.close();
			this.popupWindow.show = fake_popup_show;
			this.popupWindow.hide = fake_popup_hide;
		}
		this.popupWindow.document.owner = this;
		if(is_ie6 && !this.useRealPopup) {
			top += 8;
		}
		this.popupWindow.show(left, top, 175, 175, owner);
		var cal = this;
		// Must clean up the object references once the calendar has closed.
		this.popupTimer = setInterval(
			function () { 
				if(!cal.popupWindow || !cal.popupWindow.isOpen) {
					clearInterval(cal.popupTimer);
					cal.popupWindow.document.owner = null;
					cal.popupWindow = null;
					if(this.onCalendarClosed) this.onCalendarClosed();
					this.onDateSelected = null;
				}
			},
			1
		);
	}
	
	this.refreshPopup = function (Year, Month) {
		this.popupWindow.document.body.innerHTML = this.renderBodyContent(Year, Month);
	}
	
	this.onDateSelected = function() {};
}

function fake_createPopup() {
	var iframe = document.createElement("iframe");
	iframe.style.position = "absolute";
	iframe.style.display = "none";
	iframe.style.left = 0;
	iframe.style.top = 0;
	iframe.style.backgroundColor = "white";
	iframe.style.border = "none";
	iframe.style.zIndex = 100;
	iframe.frameBorder = 0;
	iframe.scrolling = "no";
	iframe.src = "javascript:''";
	document.body.appendChild(iframe);
	var contentWindow = iframe.contentWindow;
	return contentWindow;	
}

function fake_popup_show(left, top, width, height, owner) {
	var style = this.frameElement.style;
	style.left = (getX(owner) + left) + "px";
	style.top = (getY(owner) + top) + "px";
	style.display = "block";
	style.width = width + "px";
	style.height = height + "px";
	this.isOpen = true;
	var pDoc = this.parent.document;
	pDoc.currentPopup = this;
	if(pDoc.onmousedown != doc_onmousedown) {
		this.old_doc_onmousedown = pDoc.onmousedown;
		pDoc.onmousedown = doc_onmousedown;
	}
}

function fake_popup_hide() {
	this.frameElement.style.display = "none";
	this.isOpen = false;
	if(this.parent.document.currentPopup) {
		this.parent.document.currentPopup = null;
		this.parent.document.onmousedown = this.old_doc_onmousedown;
	}
}

function doc_onmousedown() {
	if(this.currentPopup) {
		this.currentPopup.hide();
		this.currentPopup = null;
	}
}



// MISCELLANEOUS CONTROLS --------------------------------------------------------------------------------------------------------------------------------

var errorDisplayStyle;		//This variable determines which style of error display (popup boxes, or div's) to use
var popupTimer = null;
var errorSubstitutions = new Object();
var popups = new Object();

function getPopup(fieldName) {
	var popup;
	
	if(typeof(popups[fieldName]) == 'undefined') {
		popup = DxCreatePopup("msg" + fieldName, "HelpBox");

		//Set the onMouseOut and onMouseOver events.
		popup.onmouseout = function() { popupTimer = setTimeout("hideBoxes();", 4000); };
		popup.onmouseover = function() { clearTimeout(popupTimer);};
		popup.onclick = function () { this.style.visibility = xbHide; };
		popups[fieldName] = popup;
	}
	else
		popup = popups[fieldName];

	return(popup);
}

function DxCreatePopup(fieldName, className) {
	if(browserName == "IE") {
		var sHTML = '<div name="' + fieldName + '" id="' + fieldName + '" class="' + className + '" style="position: absolute; visibility: hidden"></div>';
		document.body.insertAdjacentHTML("BeforeEnd", sHTML);
		return(xbObj(fieldName));
	}
	else {
		var popup = new Layer(150);
		popup.id = "msg" + fieldName;
		popup.name = "msg" + fieldName;
		return(popup);
	}
}

function setPopupText(popup, text) {
	if(document.layers) {
		popup.document.open("text/html", "replace");
		popup.document.write("<html><body bgcolor='#ffffe1' marginleft='2' margintop='2' marginbottom='2' marginright='2'><a href='javascript://' style='text-decoration: none; color: black;' onclick='hideBoxes();'><font size='2'>" + text + "</font></a></body></html>");
		popup.document.close();
	}
	else {
		if(popup.innerHTML != text) popup.innerHTML = text;
	}
}



function showBox(fieldName, text, e, mode) {
	// Clear any pre-existing timer.
	clearTimeout(popupTimer);
	
	// Get the initialized popup.
	var popup = getPopup(fieldName);
	
	// If not displaying custom text, get the mouse coordinates.  This is where the popup will be displayed.
	if(mode == "help") {
		if(browserName == "IE") {
			popup.style.left = event.x; 
			popup.style.top = event.y + document.body.scrollTop;
		}
		else {
			popup.left = e.pageX;
			popup.top = e.pageY;
		}
	}
	else { // Else, text will be displayed next to field.
		
		if(browserName == "IE") {
			var pos = GetElementPosition("pos" + fieldName);
			if(pos) {
				popup.style.left = pos.x + 22;
				popup.style.top = pos.y - document.body.scrollTop - 2;
			}
			else {
				popup.style.left = 0;
				popup.style.top = 100;
			}
		}
		else {
			var pos = GetElementPosition("aErr" + fieldName);
			if(pos) {
				popup.left = pos.x + 22;
				popup.top = pos.y;
			}
			else {
				popup.left = 0;
				popup.top = 100;
			}
		}
	}

	// Set text to be displayed in popup.
	setPopupText(popup, text);
	
	// Display the popup.
	if(browserName == "IE") {
		popup.style.visibility = xbShow;
	}
	else {
		popup.visibility = xbShow;
	}
}

function showHelpBox(fieldName, text, e) {
	// Hide all other popup boxes.
	hideBoxes();

	showBox(fieldName, text, e, "help");

	// Activate the timer.
	popupTimer = setTimeout("hideBoxes()", 4000);	}

function showErrorBox(fieldName, errText) {
	if(typeof(errorSubstitutions[fieldName]) != "undefined") {
		fieldName = errorSubstitutions[fieldName];
	}
	showBox(fieldName, errText, null, "error");
	if(document.layers) {
		var a = document.anchors["aErr" + fieldName]
		if(a) a.onclick = function() { hideBoxes(); showErrorBox(fieldName, errText); }
		var img = document.images["imgErr" + fieldName];
		if(img) img.src = imgRoot + "x.gif";
	}
	else {
		var row = xbObj("row" + fieldName);
		var img = xbObj("imgErr" + fieldName);
		if(img) {
			img.onclick = function() { hideBoxes(); showErrorBox(fieldName, errText); };
			img.src = imgRoot + "x.gif";
		}
		if(row) paintErrorArea(fieldName);
	}
}

function paintErrorArea(fieldName) {
	var row = xbObj("row" + fieldName);
	if (row) row.className = "errField";
}

function hideErrorBox(fieldName) {
	if(typeof(errorSubstitutions[fieldName]) != "undefined") {
		fieldName = errorSubstitutions[fieldName];
	}
	if(popups[fieldName]) {
		var msg = popups[fieldName];

		msg.style.visibility = xbHide;
	
		var img;
		if(document.layers) {
			document.anchors["aErr" + fieldName].onclick = function() { }
			var img = document.images["imgErr" + fieldName];
			if(img) img.src = imgRoot + "spacer.gif";
		}
		else {
			var img = xbObj("imgErr" + fieldName);
			if(img) {
				img.src = imgRoot + "spacer.gif";
				img.onclick = function() { };
			}
			var row = xbObj("row" + fieldName);
			if(row) row.className = "Field";
		}		
	}
}


function hideBoxes(bHideErrors) {
	for(var fieldName in popups) {
		if (bHideErrors) {
			hideErrorBox(fieldName);
		}
		else {
			var popup = popups[fieldName];
			if(browserName == "IE") {
				if(popup.style.visibility != xbHide) popup.style.visibility = xbHide;
			}
			else {
				if(popup.visibility != xbHide) popup.visibility = xbHide;
			}
		}
	}
}


