function Selector()
{
	this.ID				= "";
	this.OptionIndex	= new Array();
	this.Init			= Init;
	this.AddAllItems	= AddAllItems;
	this.AddItem		= AddItem;
	this.RemoveAllItems	= RemoveAllItems;
	this.RemoveItem		= RemoveItem;	
	this.FindItem		= FindItem;
	// private
	this.getInsertIndex	= getInsertIndex;
	this.addAllItems	= addAllItems;
	this.addItem		= addItem;
	this.removeAllItems	= removeAllItems;
	this.removeItem		= removeItem;		
	this.moveAllItems	= moveAllItems;
	this.moveItem		= moveItem;
	this.addOption		= addOption;
	this.moveUp			= moveUp;
	this.moveDown		= moveDown;	
	this.getOptionIndex	= getOptionIndex;
	this.addTextFromSelector=addTextFromSelector;
	//
	this.m_oSelected	= null;
	this.m_oTarget		= null;
	this.m_oHdn			= null;
		
	function Init(sID, sHidden)
	{
		this.ID				= sID;
		this.m_oSelected	= document.getElementById("lst" + this.ID);
		this.m_oTarget		= document.getElementById("lst" + this.ID + "Target");
		this.m_oHdn			= document.getElementById(sHidden);

		for(var i = 0; i < this.m_oSelected.length; i++)
		{
			this.OptionIndex[this.m_oSelected.options[i].value] = i;
		}
	}
	function AddItem()
	{
		this.addItem(this.m_oTarget, this.m_oSelected, 0, this.m_oHdn);
	}
	function AddAllItems()
	{
		this.addAllItems(this.m_oTarget, this.m_oSelected, this.m_oHdn);
	}
	function RemoveAllItems()
	{
		this.removeAllItems(this.m_oSelected, this.m_oTarget, this.m_oHdn);
	}
	function RemoveItem()
	{
		this.removeItem(this.m_oSelected, this.m_oTarget, this.m_oHdn);
	}
	function FindItem()
	{
		findItem(document.getElementById("txtFindlst" + this.ID), document.getElementById("lst" + this.ID));
	}
	//
	// private functions
	//
	function getOptionIndex(sValue)
	{
		return this.OptionIndex[sValue];
	}
	function addAllItems(oSelected, oAvail, oTxt, iBehavior, bAddPrimary)
	{
		this.moveAllItems(oSelected, oAvail, 'AddAll', null, bAddPrimary);
		if(oTxt != null && oTxt != 'undefined')
		{
			this.addTextFromSelector(oSelected, oTxt);
		}
	}

	function removeAllItems(oAvail, oSelected, oTxt, iBehavior)
	{
		this.moveAllItems(oAvail, oSelected, 'RemoveAll');
		if(oTxt != null && oTxt != 'undefined')
		{
			this.addTextFromSelector(oSelected, oTxt);
		}
	}	
	
	function addItem(oAvail, oSelected, lMaxSelected, oTxt, iBehavior, bAddPrimary) 
	{
		this.moveItem(oAvail, oSelected, lMaxSelected, 'Add', iBehavior, bAddPrimary);
		if(oTxt != null && oTxt != 'undefined') 
		{
			this.addTextFromSelector(oAvail, oTxt);
		}
	}

	function removeItem(oSelected, oAvail, oTxt, iBehavior, bAddPrimary) 
	{
		this.moveItem(oSelected, oAvail, 0, 'Remove', iBehavior, bAddPrimary);
		if(oTxt != null && oTxt != 'undefined')
		{
			this.addTextFromSelector(oAvail, oTxt);
		}
	}	
		
	function moveAllItems(oAvail, oSelected, sActionType, iBehavior, bAddPrimary)
	{
		if (oSelected.length > 0)
		{
			for (var i = oSelected.length - 1; i >= 0; i--)
				oSelected.options[i].selected = true;
			this.moveItem(oAvail, oSelected, null, sActionType, iBehavior, bAddPrimary);
		}		
	}		
	
	function moveItem(oAvail, oSelected, lMaxSelected, sActionType, iBehavior, bAddPrimary)
	{
		var blnItems	= false;
		var indSelected = new Array();
		var iSel		= 0;
		var index		= 0;
		var i			= oSelected.length - 1;
		var iAvailCount = oAvail.length - 1;
		while (i>=0)
		{
			if (oSelected.options[i].selected == true)
			{
				blnItems						= true;
				indSelected[iSel]				= i;
				oSelected.options[i].selected = false;
				iSel++;
			}
			i--;
		}
		if (Number(lMaxSelected > 0) && Number(indSelected.length + oAvail.length) > lMaxSelected)
		{
			blnItems = false;
			alert('Only ' + lMaxSelected + ' items may be added.');
		}
		if (blnItems == true)
		{
			for (i=oAvail.length - 1; i>=0; i--)
				oAvail.options[i].selected = false;
			var intInsIdx			= 0;
			var intFirstSelIndex	= 0;
			var el					= null;
			var iIndexOffset		= 0;
			for (i=0; i<=iSel-1; i++)
			{	
				index = parseInt(this.getOptionIndex(oSelected.options[indSelected[i]].value));
				if(typeof(iBehavior) != 'number') //Behavior = Original Design 
													 //Items maintain their original order when moved between the left and right sides 
				{
					intInsIdx = this.getInsertIndex(0, oAvail.length - 1, index, oAvail, oSelected);
					this.addOption(oAvail, oSelected.options[indSelected[i]], intInsIdx, sActionType, bAddPrimary);
					oSelected.remove(indSelected[i]);
					intFirstSelIndex = indSelected[i];
				}
				else
				{	
					switch(iBehavior)
					{
						case 0 : // Behavior =	Deactivates the buttons in the selector (Part of Original Design)
							intInsIdx = -1;
							break;
						case 1 : // Behavior =	AddItems:		items are added to the bottom of the right side 
								 //				AddAllItems:	items are added to the bottom of the right side 
								 //				RemoveItems:	items are moved from the right to the left side and placed in their original order
								 //				RemoveAllItems: items are moved from the right to the left side and placed in their original order
							switch(sActionType)
							{
								case 'Remove' :
									iIndexOffset = 0;
									for (var iCount = oSelected.length - 1; iCount >= 0; iCount--)
										if(parseInt(this.getOptionIndex(oSelected.options[indSelected[i]].value)) > parseInt(this.getOptionIndex(oSelected.options[iCount].value)))
											iIndexOffset++;
									this.addOption(oAvail, oSelected.options[indSelected[i]], this.getOptionIndex(oSelected.options[indSelected[i]].value) - iIndexOffset, sActionType);
									break;
								case 'Add' : 
									this.addOption(oAvail, oSelected.options[indSelected[i]], iAvailCount + 1,sActionType);
									break;
								case 'RemoveAll' : 
									iIndexOffset = 0;
									for (var iCount = oSelected.length - 1; iCount >= 0; iCount--)
										if(parseInt(this.getOptionIndex(oSelected.options[indSelected[i]].value)) > parseInt(this.getOptionIndex(oSelected.options[iCount].value)))
											iIndexOffset++;
									this.addOption(oAvail, oSelected.options[indSelected[i]], this.getOptionIndex(oSelected.options[indSelected[i]].value) - iIndexOffset, sActionType);
									break;
								case 'AddAll' : 
									this.addOption(oAvail, oSelected.options[indSelected[i]], iAvailCount + 1, sActionType);
									break;
								default :									
							}
							oSelected.remove(indSelected[i]);
							intFirstSelIndex = indSelected[i];						
							break;						
						default :
					}
				}
			}
				
			if (oSelected.length > 0)
			{
				if (intFirstSelIndex >= oSelected.length)
					intFirstSelIndex = oSelected.length - 1;
				oSelected.options[intFirstSelIndex].selected = false;
			}
		}		
	}
	function addTextFromSelector(oElement, oTxt) 
    {
		if(oElement.tagName == null || oElement.tagName == 'undefined')
		{
			oElement = document.getElementById(oElement);
		}
		if(oTxt.tagName == null || oTxt.tagName == 'undefined')
		{
			oTxt = document.getElementById(oTxt);
		}
        var _sTxt = "";
        oTxt.value = "";
        for (var i = 0;i < oElement.options.length;i++)
        {
            _sTxt += oElement.options[i].value + ",";
        }
        _sTxt = _sTxt.substr(0, (_sTxt.length - 1));            
        oTxt.value = _sTxt;
	}      

	function addOption(oSelect, oOption, intIdx, sActionType, bAddPrimary)
	{
		var bCompleteAdd = true;
		if( sActionType == 'Remove' || sActionType == 'RemoveAll' )
		{
			if( document.getElementById("lstClass") != null )
			{
				var aryItems = oOption.value.split('^');
				if (aryItems.length > 1)
				{
					var aryClasses = aryItems[1].split('~');
					if( !IsInArray(aryClasses, document.getElementById("lstClass").value ) )
						bCompleteAdd = false;
				}
			}
		}
	
		if( bCompleteAdd )
		{
			var el = document.createElement("OPTION");
//gh			el.optionIndex = oOption.optionIndex;
			el.text = oOption.text;
			el.value = oOption.value;
			if(bAddPrimary != null && bAddPrimary != 'undefined') 
				el.primary = "0";
			
			if (document.all)
			{
				if(intIdx >= 0)
					oSelect.add(el, intIdx);
				else 
					oSelect.add(el, oSelect.options[intIdx]);
			}
			else
			{
				if(intIdx >= 0)
				{
					oSelect.add(el, oSelect.options[intIdx]);
				}
				else 
					oSelect.add(el, null);
			}
		}
	}

	function getInsertIndex(iBeginIdx, iEndIdx, iOptionIndex, oAvail, oSelected)
	{
		var index = 0;
		if (iEndIdx > iBeginIdx)
		{
			var iMidIdx			= parseInt( (iBeginIdx + iEndIdx) / 2 );
			var iMidOptionIndex = parseInt(this.getOptionIndex(oAvail.options[iMidIdx].value));

			if (iOptionIndex < iMidOptionIndex)
				return this.getInsertIndex(iBeginIdx, iMidIdx - 1, iOptionIndex, oAvail, oSelected);
			else if(iOptionIndex > iMidOptionIndex)
			{
				index = parseInt(this.getOptionIndex(oAvail.options[iBeginIdx].value));
				return this.getInsertIndex(iMidIdx + 1, iEndIdx, iOptionIndex, oAvail, oSelected);
			}
			else
				return iMidIdx;
		}
		else if(iEndIdx == iBeginIdx)
		{
			index = this.getOptionIndex(oAvail.options[iBeginIdx].value);
			return (iOptionIndex < index) ? iBeginIdx : (iBeginIdx + 1);
		}
		else
		{
			return iBeginIdx;
		}
	}		
	
	function moveUp(_oSelected, oTxt)
	{
		oSelected = document.getElementById(_oSelected);
		var arySel		= new Array();
		var aryMoveFrom = new Array();
		var aryMoveTo	= new Array();
		var oOption	= null;
		var iSel		= 0;
		var iShift		= 0;
		for (var i=oSelected.length-1; i >= 0; i--)
		{
			if (oSelected.options[i].selected == true)
			{
				arySel[arySel.length] = i;
				oSelected.options[i].selected = false;
				iSel++;
			}
			else if (iSel > 0)
			{
				aryMoveFrom[aryMoveFrom.length] = i;
				aryMoveTo[aryMoveTo.length] = i+iSel;
				iSel = 0;
			}
		}
		
		if (arySel[arySel.length-1] > 0)
		{
			for (var i=0; i < aryMoveFrom.length; i++)
			{
				oOption = oSelected.options[aryMoveFrom[i]];
				oSelected.options.remove(aryMoveFrom[i]);
				oSelected.options.add(oOption, aryMoveTo[i]);
			}
			iShift = -1;
		}

		for (var i=0; i < arySel.length; i++)
			oSelected.options[arySel[i]+iShift].selected = true;

		if(oTxt != null && oTxt != 'undefined') 
			this.AddTextFromSelector(oSelected, oTxt);
	}	
	
	function moveDown(_oSelected, oTxt)
	{
		oSelected = document.getElementById(_oSelected);
		var arySel		= new Array();
		var aryMoveFrom = new Array();
		var aryMoveTo	= new Array();
		var oOption	= null;
		var iSel		= 0;
		var iShift		= 0;

		for (var i=0; i < oSelected.length; i++)
		{
			if (oSelected.options[i].selected == true)
			{
				arySel[arySel.length] = i;
				oSelected.options[i].selected = false;
				iSel++;
			}
			else if (iSel > 0)
			{
				aryMoveFrom[aryMoveFrom.length] = i;
				aryMoveTo[aryMoveTo.length] = i-iSel;
				iSel = 0;
			}
		}

		if (arySel[arySel.length-1] < oSelected.length-1)
		{
			for (var i=0; i < aryMoveFrom.length; i++)
			{
				oOption = oSelected.options[aryMoveFrom[i]];
				oSelected.options.remove(aryMoveFrom[i]);
				oSelected.options.add(oOption, aryMoveTo[i]);
			}
			iShift = 1;
		}

		for (var i=0; i < arySel.length; i++)
			oSelected.options[arySel[i]+iShift].selected = true;

		if(oTxt != null && oTxt != 'undefined') 
			this.AddTextFromSelector(oSelected,oTxt);
	}	
		
}
// utility function
function findItem(oTextBox, oListBox)
{
    var sTextBoxValue = oTextBox.value.toLowerCase();
    var bFound        = false;
    var iIndex        = oListBox.selectedIndex;
    var iNumOptions   = oListBox.options.length;
    var iPosition     = 0;
    while ((!bFound) && (iPosition < iNumOptions))
    {
        bFound = (oListBox.options[iPosition].text.toLowerCase().indexOf(sTextBoxValue) == 0);
        if (bFound)
			iIndex = iPosition;
		iPosition++;
    }
    if (bFound)
        oListBox.selectedIndex = iIndex;
}
function IsInArray( aItems, sValue )
{
	for(x = 0; x < aItems.length; x++ )
	{
		if( aItems[x] == sValue )
			return true;
	}
	return false;
}
