var strXMLFileRoot = "XML/";
var arrItems = new Array();
var bComboEnabled = true;
var oOpenedCombo = null;
var oTempDisabled = null;
var iOffset = 0;

function GetParentDivFromElement(oElement)
//Given an element, returns its parent div object
{
	var strElementName;
	
	// Try
	var oRes = null;
	var p = oElement.parentNode;
	for (i =0; i < 2; i++)
	{
		if (p.tagName.toLowerCase() == "span" && p.getAttribute("type") && p.getAttribute("type")=="ComboBox")
		{
			oRes = p;
			break;
		}
		else
		{
			p = p.parentNode;
		}
	}
	return oRes;	
}


function GetParentDivObjectFromName(strComboName)
{
	return document.getElementById(strComboName + "_Div");
}


function GetComboName( oElement )
{
	var strName = oElement.id;
	var iIndex;
	if ( strName )
	{
		iIndex = strName.lastIndexOf("_");
		if ( iIndex == -1 )
			strName = "[GetComboName] ERROR: " + strName + " is an invalid ComboBox element name.";
		else
			strName = strName.substring( 0, iIndex );
	}
	else
		strName = "[GetComboName] ERROR: the element passed in does not have an Id attribute.";
		
	return strName;
}


function GetButtonObject(oParentDiv)
{
	var strComboName = GetComboName(oParentDiv);
	var oBtn = document.getElementById( strComboName + "_Button" );
//alert( "[GetButtonObject]\n" + oBtn + "\n" + oBtn.id );
	return oBtn;
}


function GetListDivObject(oParentDiv)
{
	var strComboName = GetComboName(oParentDiv);
	var oLD = document.getElementById( strComboName + "_ListDiv" );
//alert( "[GetListDivObject]\n" + oLD + "\n" + oLD.id );
	return oLD;
}


function GetListObject(oParentDiv)
{
	var strComboName = GetComboName(oParentDiv);
	var oLst = document.getElementById( strComboName + "_List" );
//alert( "[GetListObject]\n" + oLst + "\n" + oLst.id );
	return oLst;
}


function GetTextObject(oParentDiv)
{
	var strComboName = GetComboName(oParentDiv);
	var oTxt = document.getElementById( strComboName + "_Text" );
//alert( "[GetTextObject] oParentDiv = " + oParentDiv.id + "\n" + oTxt + " " + oTxt.id );
	return oTxt;
}


function InitializeArray(oParentDiv)
{
	var oList = GetListObject(oParentDiv);
	arrItems.length = 0																	//truncate array to length 0 (delete existing items)
		
	//populate array with current values
	for (i = 0; i < oList.length; i++ )
	{
		arrItems[i] = oList[i].text;
	}
}


function GetParentTop(oChild)
{
	if ( oChild.offsetParent )
		iOffset += parseInt(oChild.offsetParent.offsetTop) + GetParentTop(oChild.offsetParent);
	return iOffset;
}


function GetParentLeft(oChild)
{
	var iOffset = 0;
	if ( oChild.offsetParent )
		iOffset += parseInt(oChild.offsetParent.offsetLeft) + GetParentLeft(oChild.offsetParent);
	return iOffset;
}


function ComboOpen(strComboName)
{
	ComboOpenObj(GetParentDivObjectFromName(strComboName));
}


function ComboOpenObj(oParentDiv)
{
	var i;																										//loop counter
	var oListDiv = GetListDivObject(oParentDiv);							//get object handle to list div
	var oText = GetTextObject(oParentDiv);										//get object handle to text
	var oList = GetListObject(oParentDiv);										//get object handle to list

	InitializeArray(oParentDiv);

	//if ( oList.options.length > 0 && oListDiv.style.display == "none" )
	if ( oParentDiv.ComboEnabled =="true" && oListDiv.style.display == "none" )
	{
		// Show list and set focus to it
		//oParentDiv.ComboEnabled = "true";
		oListDiv.style.zIndex = 10;
		iOffset = 0;																									//set global variable iOffset = 0 to calc top offset
		oListDiv.style.top = parseInt(oText.offsetTop) + parseInt(oText.style.height) + GetParentTop(oParentDiv);// + 5; removed = caused gap
		iOffset = 0;																									//set global variable iOffset = 0 to calc left offset
		oListDiv.style.left = parseInt(oText.offsetLeft) + GetParentLeft(oParentDiv); // + 5; removed = caused gap
		oListDiv.style.display = "";
		oList.selectedIndex = oParentDiv.SelectedItemIndex;
		oList.focus();
		oOpenedCombo = oParentDiv;
	}
}


function ComboClose(bSetValue)
{
	if (oOpenedCombo != null)
	{
		var bComboChange = false;
		var oParentDiv = oOpenedCombo;
		var oListDiv = GetListDivObject(oParentDiv);															//get object handle to the open list div
		var oList = GetListObject(oParentDiv);																	//get object handle to open list
		var oText = GetTextObject(oParentDiv);																	//get object handle to open box's textbox
		
		if ( oListDiv.style.display != "none" )
		{
			if (bSetValue && oList.selectedIndex != -1)
			{
				oText.value = oList.options[oList.selectedIndex].text;
				oParentDiv.SelectedItemIndex = oList.selectedIndex
				oText.createTextRange().select();
				bComboChange = true;
			}
			oText.focus();
			oListDiv.style.display = "none";
		}
		oOpenedCombo = null;
		if (bComboChange)
		{
			RunOnChangeScript(oParentDiv);
		}
	}
}


function ComboToggle(oParentDiv)
{
	var oListDiv = GetListDivObject(oParentDiv);																//get object handle to the open list div

	if ( oListDiv.style.display == "none" )
		//ComboOpen(GetBoxNameFromElement(oParentDiv.id));
		ComboOpenObj(oParentDiv);
	else
		ComboClose(false);
}


function OnComboClick()
{
	ComboClose(true);
}


function OnComboListKey()
{
	if (event.keyCode == 13) 				// Enter
		ComboClose(true);
	else
		if ( event.keyCode == 27 ) 		// Esc
			ComboClose(false);
}


function AutoCompleteFromArray( oInputText )
{
	var found = false;
	for (var i = 0; i < arrItems.length; i++)
	{
		if (arrItems[i].toUpperCase().indexOf(oInputText.value.toUpperCase()) == 0)
		{
			found=true;
			break;
		}
	}
	
	var iFound = -1;
	if (found)
	{
		iFound = i;
	}
	
	if (oInputText.createTextRange)
	{
		var cursorKeys ="8;46;37;38;39;40;33;34;35;36;45;";
		if (cursorKeys.indexOf(event.keyCode+";") == -1)
		{
			var r1 = oInputText.createTextRange();
			var oldValue = r1.text;
			var newValue = (found ? arrItems[iFound] : oldValue);
			if (newValue != oInputText.value)
			{
				oInputText.value = newValue;
				var rNew = oInputText.createTextRange();
				rNew.moveStart('character', oldValue.length);
				rNew.select();
			}
		}
	}
	return iFound;
}


function OnEditKeyUp()
{
	var oSourceElement = window.event.srcElement;								//get source element
	var oParentDiv = GetParentDivFromElement(oSourceElement)		//get object handle to the open box's parent div
	var oText = GetTextObject(oParentDiv);											//get object handle to open box's textbox
	var oList = GetListObject(oParentDiv);											//get object handle to open box's dropbox
	if ( !oParentDiv.XMLEnabled )
	{
		//regular combobox, with dropbox already populated.
		InitializeArray(oParentDiv);
	}

	//alert(event.keyCode);
	if ( event.keyCode == 40 ) // Down arrow
	{
		if ( event.altKey )
		{
			// Open dropdown list and move focus to it
			ComboToggle(oParentDiv);
		}
		else if ( oParentDiv.SelectedItemIndex != -1 && oParentDiv.SelectedItemIndex < arrItems.length - 1 )
		{
			oList.selectedIndex++
			oText.value = arrItems[oList.selectedIndex];
			oParentDiv.SelectedItemIndex = oList.selectedIndex;
			oText.createTextRange().select();
			RunOnChangeScript(oParentDiv);
		}
	}
	else if ( event.keyCode == 38 ) // Up arrow
	{
		if ( event.altKey )
		{
			// Open dropdown list and move focus to it
			ComboToggle(oParentDiv);
		}
		else if ( oParentDiv.SelectedItemIndex > 0 && oParentDiv.SelectedItemIndex < arrItems.length )
		{
			oList.selectedIndex--;
			oText.value = arrItems[oList.selectedIndex];
			oParentDiv.SelectedItemIndex = oList.selectedIndex;
			oText.createTextRange().select();
			RunOnChangeScript(oParentDiv);
		}
	}
	else 
	{
		if ( oParentDiv.XMLEnabled )
		{
			//XML Combo box, use XML to recreate the array and populate the dropdown
			if ( oParentDiv.MultiFile )
			{
				//XML is in multiple files. We'll need to decide which one to parse
				if ( oText.value.length > 0 )
				{
					var oXML = GetBandXMLObject( oText.value );
					FillDropBoxFromXML( oParentDiv, oXML, oParentDiv.XMLElementName, oParentDiv.XMLAttributeName );
				}
			}
			else	
			{
				//XML is in a single file, attached to the combo div. Proceed.
				FillDropBoxFromXML( oParentDiv, oParentDiv.oXML, oParentDiv.XMLElementName, oParentDiv.XMLAttributeName );
			}
		}

		oList.selectedIndex = AutoCompleteFromArray( oText );
		oParentDiv.SelectedItemIndex = oList.selectedIndex;
		RunOnChangeScript(oParentDiv);		
	}
}


function ListBlur()
{
	var oParentDiv = GetParentDivFromElement(window.event.srcElement);
	ComboClose(false);
	if ( window.event.srcElement.name = GetButtonObject(oParentDiv).name )
	{
		oParentDiv.ComboEnabled = "false";
		oTempDisabled = oParentDiv;
		setTimeout("EnableComboBox();", 500);
	}
}


function EnableComboBox()
{
	if (oTempDisabled != null)
	{
		oTempDisabled.ComboEnabled = "true";
		oTempDisabled = null;
	}
}


function RunOnChangeScript(oComboDiv)
{
	// execute onchangescript if available
	var strOnChangeScript = oComboDiv.getAttribute("onchangescript");
	if (strOnChangeScript != null)
	{
		eval(strOnChangeScript);
	}
}


function OnArrowBtnClick()
{
	ComboOpenObj(window.event.srcElement.parentNode);
}


function FillDropBoxFromXML( oParentDiv, oXML, strElementName, strAttributeName )
{
/*
alert("[FillDropBoxFromXML]\noParentDiv = " + oParentDiv.id +
	"\noXML = " + oXML +
	"\nstrElementName = " + strElementName +
	"\nstrAttributeName = " + strAttributeName );
*/
	var oList = GetListObject( oParentDiv );
	var oText = GetTextObject( oParentDiv );
	var strIn = oText.value;
	var iChars = strIn.length;
	var i = 0;
	var strValue = "";
	if ( iChars > 1 )
	{
		oList.options.length = 0;													//delete existing items from dropdown.
		arrItems.length = 0;															//clear the array;
		var strQuery = "/" + strElementName + "List/" + strElementName + "[starts-with(" + 
			"translate(@" + strAttributeName + ", \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", \"abcdefghijklmnopqrstuvwxyz\"), " +
			"translate(\"" + strIn + "\", \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\", \"abcdefghijklmnopqrstuvwxyz\"))]";
			
		if (oXML.documentElement)
		{
			oNodeList = oXML.documentElement.selectNodes( strQuery );
			oCurrNode = oNodeList.nextNode;
			while ( oCurrNode )
			{
				strValue = oCurrNode.getAttribute( strAttributeName );
				arrItems[i] = strValue;
				i++;
				oCurrNode = oNodeList.nextNode;
			}
			for ( j = 0; j < i; j++ )
			{
				var oOption = document.createElement("OPTION");
				oList.options.add(oOption);
				oOption.innerText = arrItems[j];
			}
		}
	}
}


function CreateCombo(oContainer, strComboName, iListHeight, bLineBreak, chrAccessKey )
/**********************************************
Creates a combobox control

Params:
	oContainer - DHTML element that will contain new combobox
	strComboName - combobox name (its outer SPAN Id will be "<name>_Div", text input box - "<name>_Text", etc.
	iListHeight - number of rows to display in the listbox
	bLineBreak - (boolean) whether or not to include a line break after the combobox
	
Returns: combobox (reference to its outer SPAN)
**********************************************/
{
	var ctrlComboSpan = document.createElement("SPAN");
	oContainer.appendChild(ctrlComboSpan);
	ctrlComboSpan.id = strComboName + "_Div";
	ctrlComboSpan.Type = "ComboBox";
	ctrlComboSpan.ComboEnabled = "true";
	ctrlComboSpan.ComboEnabledDefault = "true";
	ctrlComboSpan.SelectedItemIndex = -1;

	// Text box
	var ctrlText = document.createElement("input");
	ctrlText.type = "text";
	ctrlComboSpan.appendChild(ctrlText);
	ctrlText.id = strComboName + "_Text";
	ctrlText.name = strComboName;
	ctrlText.size = 18;
	ctrlText.style.width = 180;
	ctrlText.style.height = 22;
	ctrlText.onkeyup = OnEditKeyUp;
	if ( chrAccessKey )
		ctrlText.accessKey = chrAccessKey;

//alert("[CreateCombo]\n\n" + ctrlText.onkeyup );

	// "Down arrow" Button
	var ctrlBtn = document.createElement("input");
	ctrlBtn.type = "button";
	ctrlComboSpan.appendChild(ctrlBtn);
	ctrlBtn.id = strComboName + "_Button";
	ctrlBtn.value = "6";
	ctrlBtn.style.fontFamily = "Webdings";
	ctrlBtn.style.height = 22;
	ctrlBtn.onclick = OnArrowBtnClick;

	// Div which contains list box
	var ctrlListDiv = document.createElement("div");
	ctrlComboSpan.appendChild(ctrlListDiv);
	ctrlListDiv.id = strComboName + "_ListDiv";
	ctrlListDiv.style.left = 0;
	ctrlListDiv.style.top = 0;
	ctrlListDiv.style.width = 200;
	ctrlListDiv.style.cursor= "default";
	ctrlListDiv.style.position = "absolute";
	ctrlListDiv.style.zIndex = -10;
	ctrlListDiv.style.display = "none";

	// List box
	var ctrlList = document.createElement("<select size=" + iListHeight + ">");
	ctrlListDiv.appendChild(ctrlList);
	ctrlList.id = strComboName + "_List";
	ctrlList.style.width = "100%";
	ctrlList.onclick = OnComboClick;
	ctrlList.onkeypress = OnComboListKey;
	ctrlList.onblur = ListBlur;

	//add a line break after the combobox, if requested.	
	if ( bLineBreak )
	{
		var oLineBreak = document.createElement( "BR" );
		oLineBreak.id = strComboName + "_BR";
		oContainer.appendChild( oLineBreak );
	}
		
	return ctrlComboSpan;
}


function CreateXMLCombo( oContainer, strComboName, oXML, strElementName, strAttributeName, iListHeight,
	bLineBreak, chrAccessKey )
/**********************************************
Creates a combobox control using an XML file as data source. XML file is assumed
to have one element repeating, with an attribute that contains the values to fill
the dropbox with. 

EXAMPLE: 
	...
	<band Id="1" Name="Sicko" />
	<band Id="2" Name="Beatles" />
	...

Params:
	oContainer - DHTML element that will contain new combobox
	strComboName - combobox name (its outer SPAN Id will be "<name>_Div", text input box - "<name>_Text", etc.
	strElementName - Name of the Element to search for (in the example above, this would be "Band")
	strAttributeName - Name of the Attribute that contains values to fill the dropbox with (in the example 
		above, this would be "Name").
	iListHeight - Number of options to display at a time in the dropbox
	
Returns: combobox (reference to its outer SPAN)
**********************************************/
{
	var oCombo;
	oCombo = CreateCombo( oContainer, strComboName, iListHeight, bLineBreak, chrAccessKey );
	oCombo.XMLEnabled = true;
	oCombo.oXML = oXML;
	oCombo.XMLElementName = strElementName;
	oCombo.XMLAttributeName = strAttributeName;

	return oCombo;
}


function CreateBandXMLCombo( oContainer, strComboName, strElementName, strAttributeName, iListHeight,
	bLineBreak, chrAccessKey )
/**********************************************
Creates a combobox control using an XML file as data source. XML file is assumed
to have one element repeating, with an attribute that contains the values to fill
the dropbox with. 

EXAMPLE: 
	...
	<band Id="1" Name="Sicko" />
	<band Id="2" Name="Beatles" />
	...

Params:
	oContainer - DHTML element that will contain new combobox
	strComboName - combobox name (its outer SPAN Id will be "<name>_Div", text input box - "<name>_Text", etc.
	strXML_BaseName - Name of the XML Data Island series (o
	strElementName - Name of the Element to search for (in the example above, this would be "Band")
	strAttributeName - Name of the Attribute that contains values to fill the dropbox with (in the example 
		above, this would be "Name").
	iListHeight - Number of options to display at a time in the dropbox
	
Returns: combobox (reference to its outer SPAN)
**********************************************/
{
	var oCombo;
	oCombo = CreateCombo( oContainer, strComboName, iListHeight, bLineBreak );
	oCombo.XMLEnabled = true;
	oCombo.MultiFile = true;
	oCombo.XMLElementName = strElementName;
	oCombo.XMLAttributeName = strAttributeName;

/*
alert("[CreateBandXMLCombo]\noCombo = " + oCombo.id +
			"\nXMLEnabled = " + oCombo.XMLEnabled +
			"\nMultiFile = " + oCombo.MultiFile +
			"\nXMLElementName = " + oCombo.XMLElementName +
			"\nXMLAttributeName = " + oCombo.XMLAttributeName
)
*/

	return oCombo;
}