var conEmptyOptionValue = "";
var conAllOptionValue = "_ALL_";

function OptionList(listControl){
	DeliverOptionList(this);
	this.list = listControl;
}

function DeliverOptionList(toObject){
	toObject.list = null;
	toObject.moveOption = OLMoveOption;
	toObject.addOption = OLAddOption;
	toObject.removeOptions = OLRemoveOptions;
	toObject.removeOption = OLRemoveOption;
	toObject.moveOptionsToList = OLMoveOptionsToList;
	toObject.getSelectedIndexes = OLGetSelectedIndexes;
	toObject.getSelectedValues = OLGetSelectedValues;
	toObject.clearOptions = OLClearOptions;
	toObject.getSelectedValue = OLGetSelectedValue;
	toObject.getSelectedOption = OLGetSelectedOption;
	toObject.toString = OLToString;
	toObject.backup = OLBackup;
	toObject.restore = OLRestore;
	toObject.bindData = OLBindData;
	toObject.addAllOption = OLAddAllOption;
	toObject.relativeChange = OLRelativeChange;
	toObject.changeAccordingly = OLChangeAccordingly;
	toObject.isAllOptionSelected = OLIsAllOptionSelected;
	toObject.isEmptyOptionSelected = OLIsEmptyOptionSelected;
	toObject.getAllValues = OLGetAllValues;
	toObject.findOption = OLFindOption;
	toObject.setSelectedValue = OLSetSelectedValue;
	toObject.addEmptyOption = OLAddEmptyOption;
	toObject.sort = OLSort;
	toObject.selectAll = OLSelectAll;
	toObject.unselectAll = OLUnselectAll;
	toObject.getOptionIndex = OLGetOptionIndex;
}

// Move a item in the option list.
//	tnIndex - The index of the item to move
//  tnRelativePos - The relative position to move. 
function OLMoveOption(tnIndex, tnRelativePos){
	var lnDestIndex=tnIndex+tnRelativePos;
	var loOption;
	if(tnRelativePos==0) return;
	if(lnDestIndex>=0 && lnDestIndex<this.list.length){
		loOption = this.list.options[tnIndex];
		if(lnDestIndex<tnIndex){
			for(var lnIndex=tnIndex; lnIndex>lnDestIndex; lnIndex--) this.list.options[lnIndex] = new Option(this.list.options[lnIndex-1].text,this.list.options[lnIndex-1].value) ; 
		}else{
			for(var lnIndex=tnIndex; lnIndex<lnDestIndex; lnIndex++) this.list.options[lnIndex] = new Option(this.list.options[lnIndex+1].text,this.list.options[lnIndex+1].value); 
		}
		this.list.options[lnDestIndex]=new Option(loOption.text,loOption.value);
		this.list.selectedIndex = lnDestIndex;
	}
}

// Add an option item.
function OLAddOption(tsValue, tsText){
	var newOption = new Option(tsText, tsValue);
	this.list.options[this.list.length]= newOption;
	return newOption;
}

// Remove itmes in a option list according to the selected indexes.
function OLRemoveOptions(selectedIndexes){
	var lnListLength = this.list.length;
	var lnRemovedCount = 0;
	var lnSelectedIndex=0;
	if(selectedIndexes.length>0) lnSelectedIndex=selectedIndexes[0];
	for(var lnIndex=selectedIndexes.length-1; lnIndex>=0; lnIndex--){
		this.list.options[selectedIndexes[lnIndex]]=null;
	}
	
	if(lnSelectedIndex>=this.list.options.length) lnSelectedIndex=this.list.options.length-1;
	if(lnSelectedIndex>=0){
		this.list.options[lnSelectedIndex].selected = true;
	}
}

// Move the selected items from one option list to another
function OLMoveOptionsToList(toDestList){
	var loSelectedIndexes = this.getSelectedIndexes();
	var loSelectedOption;
	for(var lnIndex=0; lnIndex<loSelectedIndexes.length; lnIndex++){
		loSelectedOption=this.list.options[loSelectedIndexes[lnIndex]];
		toDestList.options[toDestList.length] = new Option(loSelectedOption.text, loSelectedOption.value);
	}
	this.removeOptions(loSelectedIndexes);
}

// Return an array of selected indexes.
function OLGetSelectedIndexes(){
	var loSelectedIndexes;
	loSelectedIndexes=new Array();
	for(var lnIndex=0; lnIndex<this.list.length; lnIndex++){
		if(this.list.options[lnIndex].selected) loSelectedIndexes[loSelectedIndexes.length] = lnIndex; 
	}
	return loSelectedIndexes;
}

// Return an array of the value of selected optoins.
function OLGetSelectedValues(){
	var loSelectedValues=new Array();
	for(var lnIndex=0; lnIndex<this.list.length; lnIndex++){
		if(this.list.options[lnIndex].selected) loSelectedValues[loSelectedValues.length] = this.list.options[lnIndex].value; 
	}
	return loSelectedValues;
}

// Clear an option list.
function OLClearOptions(){
	for(var lnIndex=this.list.length-1; lnIndex>=0; lnIndex--){
		this.list.options[lnIndex]= null;
	}
}

// Remove an option in an option list according to the given option value.
function OLRemoveOption(tsValue){
	for(var lnIndex=0; lnIndex<this.list.length; lnIndex++){
		if(this.list.options[lnIndex].value==tsValue){
			this.list.options[lnIndex]=null;
		}
	}
}

function OLGetSelectedValue(){
	if(this.list.selectedIndex>=0) return this.list.options[this.list.selectedIndex].value;
	else return null;
}

// Return the first selected option in an option list.
function OLGetSelectedOption(){
	for(var lnIndex=0; lnIndex<this.list.length; lnIndex++){
		if(this.list.options[lnIndex].selected){
			return this.list.options[lnIndex];
		}
	}
	return null;
}

function OLToString(tsSeperator){
	var lsString = "";
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++){
		if(lsString!="") lsString += tsSeperator;
		lsString += this.list.options[lnIndex].value;
	}
	return lsString;
}

function OLBackup(){
	var listId = this.list.id;
	if(listId==null||listId=="") listId = this.list.name;
	var listValuesControl = getElementById(listId + "Values");
	var listTextsControl = getElementById(listId + "Texts");
	var listSelectionsControl = getElementById(listId + "Selections");

	var lsListValues = "";
	var lsListTexts = "";
	var lsListSelections = "";
	
	
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++){
		// Backup values
		lsListValues += this.list.options[lnIndex].value + "\r\n";

		// Backup texts
		lsListTexts += this.list.options[lnIndex].text + "\r\n";

		// Backup selections.
		if(this.list.options[lnIndex].selected)
			lsListSelections += "1" + "\r\n";
		else
			lsListSelections += "0" + "\r\n";
	}
	if(listValuesControl==null)
		alert("The control - " + this.list.id + "Values" + " is expected.");
	else
		listValuesControl.value = lsListValues;

	if(listTextsControl!=null)
		listTextsControl.value = lsListTexts;

	if(listSelectionsControl!=null)
		listSelectionsControl.value = lsListSelections;

	//loForm[tsListName + "IsFirstTime"].value = "0";
}

function OLRestore(){
    var listId = this.list.id;
    if(listId==null||listId=="") listId = this.list.name;
	var loListValuesField = getElementById(listId + "Values");
	var loListTextsField = getElementById(listId + "Texts");
	var loListSelectionsField = getElementById(listId + "Selections");
	//if(document.all[tsListName + "IsFirstTime"].value=="1") return;
	
	this.clearOptions();
	if(loListValuesField.value=="") return;
	var lsListValues = loListValuesField.value.split("\r\n");
	var lsListTexts = loListTextsField.value.split("\r\n");
	var lsListSelections = loListSelectionsField.value.split("\r\n");
	
	var loOption;
	this.list.IsRestoring = true;
	for(var lnIndex=0; lnIndex<lsListValues.length-1; lnIndex++){
		loOption = new Option(lsListTexts[lnIndex], lsListValues[lnIndex])
		this.list.options[this.list.length] = loOption;
		if(lsListSelections[lnIndex] == "1") loOption.selected = true;
	}
	this.list.IsRestoring = false;
}

// Bind the data to the option list.
//		toDataSource - The data source, which should be an XMLArray or XMLItemCollection object.
//		tsValueField - The value field name.
//		tsTextField - The text field name.
function OLBindData(toDataSource, tsValueField, tsTextField, tbDistinct){
	if(tbDistinct==null) tbDistinct = false;
	var lsValue;
	for(var lnIndex=0; lnIndex<toDataSource.getCount(); lnIndex++){
		toDataSource.setCurrentIndex(lnIndex);
		lsValue = toDataSource.getAttribute(tsValueField);
		if( (tbDistinct&&this.findOption(lsValue)==null) || (!tbDistinct) )
			this.AddOption(lsValue, toDataSource.getAttribute(tsTextField));
	}
}

function OLAddAllOption(){
	this.addOption("_ALL_", "(All)");
}

function OLIsAllOptionSelected(){
	if(this.getSelectedValue()=="_ALL_") return true;
	else return false;
}

function OLIsEmptyOptionSelected(){
	if(this.getSelectedValue()=="") return true;
	else return false;
}

function OLRelativeChange(toRelativeListObject, toListData, tsRelativeField, tsValueField, tsTextField){
	var lsSelectedValues = this.getSelectedValues();
	var lsItems;
	if(lsSelectedValues.length>0){
		for(var lnIndex=0; lnIndex<lsSelectedValues.length; lnIndex++){
			lsItems = toListData.selectItems(tsRelativeField, lsSelectedValues[lnIndex]);
			toRelativeListObject.bindData(lsItems, tsValueField, tsTextField);
		}
	}else{
		toRelativeListObject.bindData(toListData, tsValueField, tsTextField);
	}
}

function OLGetAllValues(){
	var loValues=new Array();
	for(var lnIndex=0; lnIndex<this.list.length; lnIndex++){
		loValues[loValues.length] = this.list.options[lnIndex].value; 
	}
	return loValues;
}

function OLChangeAccordingly(toRelativeListObject, toListData, tsRelativeField, tsValueField, tsTextField){
	var lsSelectedValues = toRelativeListObject.getSelectedValues();
	var lsItems;
	var lbMultiple = toRelativeListObject.list.multiple;
	if(lbMultiple==null) lbMultiple = false;
	if(lsSelectedValues.length>0){
		if((!lbMultiple)&&toRelativeListObject.isAllOptionSelected()){
			lsSelectedValues = toRelativeListObject.getAllValues();
		}
	}
	else{
		if(lbMultiple){
			lsSelectedValues = toRelativeListObject.getAllValues();
		}
	}
	
	for(var lnIndex=0; lnIndex<lsSelectedValues.length; lnIndex++){
		lsItems = toListData.selectItems(tsRelativeField, lsSelectedValues[lnIndex]);
		this.BindData(lsItems, tsValueField, tsTextField);
	}
}

function OLFindOption(tsValue){
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++){
		if(this.list.options[lnIndex].value==tsValue){
			return this.list.options[lnIndex];
		}
	}
	return null;
}

function OLSetSelectedValue(tsValue){
	var loSelectedOption = this.findOption(tsValue);
	if(loSelectedOption!=null) loSelectedOption.selected = true;
}

function OLAddEmptyOption(){
	this.addOption(conEmptyOptionValue, " ");
}

function OLSort(){
	var loArray = new Array();
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++){
		loArray[lnIndex] = this.list.options[lnIndex];
	}
	loArray.sort(OLCompareOption);
	this.clearOptions();
	for(var lnIndex=0; lnIndex<loArray.length; lnIndex++){
		this.list.options[lnIndex] = loArray[lnIndex];
	}
}

function OLCompareOption(toOption1, toOption2){
	if(toOption1.text>toOption2.text) return 1;
	else if(toOption1.text<toOption2.text) return -1;
	else return 0;
}

function OLSelectAll(){
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++)
		this.list.options[lnIndex].selected = true;
}

function OLUnselectAll(){
	for(var lnIndex=0; lnIndex<this.list.options.length; lnIndex++)
		this.list.options[lnIndex].selected = -this.list.options[lnIndex].selected;
}

function OLGetOptionIndex(tsValue){
	var loOptionIndex = new Array();
	for (var lnIndex = 0; lnIndex < this.list.options.length; lnIndex++)
		if (this.list[lnIndex].value == tsValue)
			loOptionIndex[loOptionIndex.length] = lnIndex;
	return loOptionIndex;
}
