function a5_AJAX_Form(action,formID,url){
	/*
		'action' - name of the action to invoke in the .a5w page that handles the callbacks
		'formID' - the ID of the form
		'url' - the URL of the .a5w page that will handle the callback
		'optionalData' - an optinal attribute that causes some additional data to be submitted to the .a5w page.
		'flagSubmitData' - an optional attribute that cause the data to be submitted,
		 but not invoke the validation logic in the .a5w page.
		If flagSubmitData is not specified, then set it to false.
		An action of 'submit' implies that flagSubmitData is true.
	*/

	var optionalData = typeof arguments[3] != 'undefined' ? arguments[3] : '';
	var flagSubmitData = typeof arguments[4] != 'undefined' ? arguments[4] : false;
	var stateID = formID + '.STATEINFO';
	var data = '';
	var stateInfo = $(stateID).value ? $(stateID).value : '' ;
	var stateInfoArray = stateInfo.split('&');
	var finalStateInfoArray = new Array();

	if (action=='submit:dirty') 
	{
		//submit all 'old' values and only edited fields as the 'new' values.
		data = a5_AJAX_Form_RegionHarvest(formID);
		data = $u.s.rTrim(data,' &') + '&' + '__FormID='+formID +'&__FormAction=submit';
	}
	
		else if (action=='submit:all' || action=='submit') 
	{
		//submit all 'old' values and all 'new' values
		data = a5_AJAX_Form_RegionHarvest(formID,true);
		data = $u.s.rTrim(data,' &') + '&' + '__FormID='+formID +'&__FormAction=submit';		
	}

	else if (action=='submit:new' || flagSubmitData) 
	{
		//submit all 'old' values and all 'new' values
		data = a5_AJAX_Form_RegionHarvest(formID,true,false);
		var actionName = $if(action='submit:new','submit',action);
		data = $u.s.rTrim(data,' &') + '&' + '__FormID='+formID +'&__FormAction='+actionName;		
	}
	
	
	else data = '__FormAction=' +action +'&' +  '__FormID=' + formID;

	var URLInfo = document.URL;
	URLInfo=URLInfo.split('?').slice(1).join('?');

	if(URLInfo != '') URLInfo = URLInfo+'&';
	if(stateInfo != '') stateInfo = stateInfo+'&';
	if(optionalData != '') optionalData = optionalData+'&';
	data = URLInfo + stateInfo+optionalData + data;

	data = $u.s.tran(data,'\n','%20%0D%0A');

	new $a.simple(url,{data: data, handleGeneric: true, method: 'post'})
}


function a5_AJAX_Form_SetFocus() { 
	var ele = this.parentNode;
	while(ele.getAttribute('A5DataRegion') != 'A5DataRegion'){
		if(ele.tagName.toLowerCase() == 'body') return;
		ele = ele.parentNode;
	}
	ele.setAttribute('A5FocusControl',this.name);
}




function a5_AJAX_Form_SetDirty(){
	
	var isDirty = false;
	if(this.tagName.toLowerCase() == 'input' && (this.type.toLowerCase() == 'radio' || this.type.toLowerCase() == 'checkbox')){
		var eles = $n(this.name);
		if($gvs(eles).join('||A5ARRAYSEP||') != eles[0].getAttribute('A5OriginalValue')){
			for(var i=0;i<eles.length;i++) eles[i].setAttribute('A5IsDirty','true');
			isDirty = true;
		} else for(var i=0;i<eles.length;i++) eles[i].setAttribute('A5IsDirty','false');
	} else{
		if($gvs(this) != this.getAttribute('A5OriginalValue')){
			this.setAttribute('A5IsDirty','true');
			isDirty = true;
		} else this.setAttribute('A5IsDirty','false');
	}

	if(isDirty){
		var ele = this.parentNode;
		while(ele.getAttribute('A5DataRegion') != 'A5DataRegion'){
			if(ele.tagName.toLowerCase() == 'body') return;
			ele = ele.parentNode;
		}
		
		if(ele.getAttribute('A5IsDirty') != 'true') {
			var funcCall = ele.getAttribute('A5OnDirty');
			if(funcCall != '') eval(funcCall);
		}
		ele.setAttribute('A5IsDirty','true');
	}
}


function a5_AJAX_Form_SetDirtyControl(ele) {
	a5_AJAX_Form_SetDirty.call($(ele));
}



function a5_AJAX_Form_ErrorsSet(eTargs,eHTML,eleCNs,eEleCNs){

	var baseEleCN = '';
	var baseEEleCN = '';
	var curEleCN = '';
	var curEEleCN = '';
	if(typeof eleCNs == 'string') baseEleCN = eleCNs;
	if(typeof eEleCNs == 'string') baseEEleCN = eEleCNs;

	var ele = new Object();
	var eleCtl = new Object();
	var errorArr = new Array();
	for(var i=0;i<eTargs.length;i++){
		curEleCN = typeof eleCNs == 'object' && eleCNs[i] ? eleCNs[i] : baseEleCN;
		curEEleCN = typeof eEleCNs == 'object' && eEleCNs[i] ? eEleCNs[i] : baseEEleCN;
		ele = $(eTargs[i]+'.ERRORMSG');
		eleCtl = $(eTargs[i]);
		ele.innerHTML = eHTML[i];
		if(curEEleCN != '') $acn(ele,curEEleCN);
		if(curEleCN != '') $acn(eleCtl,curEleCN);

		$sa(eleCtl,'A5IsDirty','true');
		eleCtl = eleCtl.parentNode;
		while(eleCtl.getAttribute('A5DataRegion') != 'A5DataRegion'){
			if(eleCtl.tagName.toLowerCase() == 'body') return;
			eleCtl = eleCtl.parentNode;
		}
		eleCtl.setAttribute('A5IsDirty','true');

		errorArr[i] = {id: eTargs[i], errorEleClassName: curEEleCN, eleClassName: curEleCN};
	}
	return errorArr;
}

function a5_AJAX_Form_ErrorsClear(errorArr){
	var ele = new Object();
	for(var i=0;i<errorArr.length;i++){
		ele = $(errorArr[i].id+'.ERRORMSG')
		if(ele) ele.innerHTML = '';
		if(errorArr[i].errorEleClassName != '') $rcn(ele,errorArr[i].errorEleClassName);
		if(errorArr[i].eleClassName != '') $rcn($(errorArr[i].id),errorArr[i].eleClassName);
	}
	return new Array();
}




function a5_AJAX_FormPrepare(regionID){

	//stores the original values of all of the controls so that we can determine what controls are dirty when we submit.
	var rObj = new Array();
	if(typeof regionID == 'object' && regionID.length){
		for(var i=0;i<regionID.length;i++) rObj[rObj.length] = $(regionID[i]);
	} else{
		rObj = [$(regionID)];
	}

	for(var i=0;i<rObj.length;i++){
		var eles = rObj[i].getElementsByTagName('input');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
		}
		$e.add(eles,'keyup',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'blur',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'focus',a5_AJAX_Form_SetFocus,null,false,rObj.id+'Events');
		eles = rObj[i].getElementsByTagName('select');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
		}
		$e.add(eles,'keyup',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'blur',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'focus',a5_AJAX_Form_SetFocus,null,false,rObj.id+'Events');
		eles = rObj[i].getElementsByTagName('textarea');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
		}
		$e.add(eles,'keyup',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'blur',a5_AJAX_Form_SetDirty,null,false,rObj.id+'Events');
		$e.add(eles,'focus',a5_AJAX_Form_SetFocus,null,false,rObj.id+'Events');
		rObj[i].setAttribute('A5DataRegion','A5DataRegion');
		
	}
}




function a5_AJAX_Callback(url,data) {
	new $a.simple(url,{data: data, handleGeneric: true, method: 'post'})
}



function a5_AJAX_Form_populateSelect(curID,curValue,clearOld,popList){



	curObj = document.getElementById(curID)
	if(clearOld){
		if(curObj.options.length > 0){
			for(var i = (curObj.options.length-1); i >= 0; i--){
				curObj.options[i] = null;
			}
			curObj.options[0] = null;
		}
		curIndx = 0

	}
	else{
		curIndx = curObj.options.length
	}

	var optArr = new Array()
	optArr = popList.split('\n')
	if(optArr.length > 0){
		var optTempArr = new Array()
		for(i=0;i<optArr.length;i++){
			optTempArr = optArr[i].split('|')
			if(optTempArr.length > 1){
				curObj.options[curIndx] = new Option(optTempArr[0],optTempArr[1])
			}
			else{
				curObj.options[curIndx] = new Option(optTempArr[0],optTempArr[0])
			}
			curIndx++
		}
	}

	otpValFound = false

	if(curObj.options.length > 0){
		for(i=0;i<curObj.options.length;i++){
			if(curObj.options[i].value == curValue){
				otpValFound = true
				curObj.options.selectedIndex = i
				break;
			}
		}
		if(otpValFound == false){
			curObj.options[curObj.options.length] = new Option(curValue,curValue)
			curObj.options.selectedIndex = curObj.options.length-1
		}
	}

}



function a5_AJAX_Form_RegionHarvest(regionID){
	
	//'sendAllNewValues' is an optional parameter with a default value of false.
	//If this parameter is true then when the form is submitted values are submitted for all of the
	//controls, not just the controls that were edited.
	
	//'sendOldValues' is an optional parameter with a defualt value of true.
	//If this parameter is false, when the form is submitted, the original values in each control
	//are not submitted.
	
	
	var sendAllNewValues = typeof arguments[1] != 'undefined' ? arguments[1] : false;
	var sendOldValues = typeof arguments[2] != 'undefined' ? arguments[2] : true;
	
	var rObj = new Array();
	if(typeof regionID == 'object' && regionID.length){
		for(var i=0;i<regionID.length;i++) rObj[rObj.length] = $(regionID[i]);
	} else{
		rObj = [$(regionID)];
	}


	var eles = new Object();
	var valArr = new Array();
	var curVal = new Array();
	var usedNames = new Array();
	var dirtyRegions = new Array();
	var dirtyValues = new Array();
	var isDirty = false;

	for(var i=0;i<rObj.length;i++){
		$e.removeGroup(rObj[i].id+'Events');
		if(rObj[i].getAttribute('A5IsDirty') == 'true' || sendAllNewValues ){
			dirtyRegions[dirtyRegions.length] = rObj[i].id;
			eles = rObj[i].getElementsByTagName('input');
			for(var j=0;j<eles.length;j++){
				if(eles[j].type.toLowerCase() == 'radio'){
					if($u.a.find(usedNames,eles[j].name) == -1){
						usedNames[usedNames.length] = eles[j].name;
						if(sendOldValues) valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam('old.'+eles[j].name,eles[j].getAttribute('A5OriginalValue').split('||A5ARRAYSEP||'));
						isDirty = eles[j].getAttribute('A5IsDirty') == 'true' ? true : false;
						if( isDirty  || sendAllNewValues ){
							if(isDirty) dirtyValues[dirtyValues.length] = eles[j].name;
							valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam(eles[j].name,$gvs($n(eles[j].name)));
						}
					}
				} else if(eles[j].type.toLowerCase() == 'checkbox'){
					if($u.a.find(usedNames,eles[j].name) == -1){
						usedNames[usedNames.length] = eles[j].name;
						if(sendOldValues) valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam('old.'+eles[j].name,eles[j].getAttribute('A5OriginalValue').split('||A5ARRAYSEP||'));
						isDirty = eles[j].getAttribute('A5IsDirty') == 'true' ? true : false;
						if( isDirty || sendAllNewValues ){
							if(isDirty) dirtyValues[dirtyValues.length] = eles[j].name;
							valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam(eles[j].name,$gvs($n(eles[j].name)));
						}
					}
				
				} else if(eles[j].type.toLowerCase() == 'text' || eles[j].type == 'hidden' || eles[j].type == 'password'  || eles[j].type == ''){
					if(sendOldValues) valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam('old.'+eles[j].name,eles[j].getAttribute('A5OriginalValue').split('||A5ARRAYSEP||'));
					isDirty = eles[j].getAttribute('A5IsDirty') == 'true' ? true : false;
					if( isDirty || sendAllNewValues ){
						if(isDirty) dirtyValues[dirtyValues.length] = eles[j].name;
						valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam(eles[j].name,$gvs(eles[j]));
					}
				}
			}
			eles = rObj[i].getElementsByTagName('select');
			for(var j=0;j<eles.length;j++){
				if(sendOldValues) valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam('old.'+eles[j].name,eles[j].getAttribute('A5OriginalValue').split('||A5ARRAYSEP||'));
				isDirty = eles[j].getAttribute('A5IsDirty') == 'true' ? true : false;
				if( isDirty || sendAllNewValues ){
					if(isDirty) dirtyValues[dirtyValues.length] = eles[j].name;
					valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam(eles[j].name,$gvs(eles[j]));
				}
			}
			eles = rObj[i].getElementsByTagName('textarea');
			for(var j=0;j<eles.length;j++){
				if(sendOldValues) valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam('old.'+eles[j].name,eles[j].getAttribute('A5OriginalValue').split('||A5ARRAYSEP||'));
				isDirty = eles[j].getAttribute('A5IsDirty') == 'true' ? true : false;
				if( isDirty || sendAllNewValues ){
					if(isDirty) dirtyValues[dirtyValues.length] = eles[j].name;
					valArr[valArr.length] = a5_AJAX_Form_SubmitValueParam(eles[j].name, $gvs(eles[j]));
				}
			}
		}
	}

	return 'a5DirtyRegions='+dirtyRegions.join('\n')+'&'+'a5RegionsDirtyValues='+dirtyValues.join('\n')+'&'+valArr.join('&');
}






function a5_AJAX_Form_SubmitValueParam(eleName,eleValue){
	if(typeof eleValue == 'string'){
		//return urlencode(eleName)+'='+urlencode($u.s.tran(eleValue,'\n','%0D%0A'));
		return urlencode(eleName)+'='+urlencode(eleValue);
			//return eleName+'='+eleValue;
	} else{
		var valArr = new Array();
		if(eleValue.length==0) {
			return urlencode(eleName) + '=';
		} else
		{
			for (var j=0;j<eleValue.length;j++){
				valArr[valArr.length] = urlencode(eleName)+'='+urlencode(eleValue[j]);
			}
			return valArr.join('&');
		}
	}
}




function urlencode(text){

		return escape(text);

		text = escape(text.toString()).replace(/\+/g, "%2B");

		// this escapes 128 - 255, as JS uses the unicode code points for them.
		// This causes problems with submitting text via AJAX with the UTF-8 charset.
		var matches = text.match(/(%([0-9A-F]{2}))/gi);
		if (matches){
			for (var matchid = 0; matchid < matches.length; matchid++){
				var code = matches[matchid].substring(1,3);
				if (parseInt(code, 16) >= 128){
					text = text.replace(matches[matchid], '%' + code);
				}
			}
		}

		// %25 gets translated to % by PHP, so if you have %25u1234,
		// we see it as %u1234 and it gets translated. So make it %u0025u1234,
		// which will print as %u1234!
		//text = text.replace('%25', '%u0025');

		return text;
}



function a5_AJAX_FormReset(regionID) {

	//resets the dirty flags, and stores the original values of all of the controls so that we can determine what controls are dirty when we submit.
	//differs from a5_AJAX_FormPrepare() which adds 'blur' events (to capture edited values) to all controls.
	var rObj = new Array();
	if(typeof regionID == 'object' && regionID.length){
		for(var i=0;i<regionID.length;i++) rObj[rObj.length] = $(regionID[i]);
	} else{
		rObj = [$(regionID)];
	}

	for(var i=0;i<rObj.length;i++){
		var eles = rObj[i].getElementsByTagName('input');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
			eles[j].setAttribute('A5IsDirty','false');
		}
		
		eles = rObj[i].getElementsByTagName('select');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
			eles[j].setAttribute('A5IsDirty','false');
		}
		
		eles = rObj[i].getElementsByTagName('textarea');
		for(var j=0;j<eles.length;j++){
			eles[j].setAttribute('A5OriginalValue',$gvs($n(eles[j].name)).join('||A5ARRAYSEP||'));
			eles[j].setAttribute('A5IsDirty','false');
		}
		
		ele = rObj[i];
		if(ele.getAttribute('A5IsDirty') == 'true') {
			var funcCall = ele.getAttribute('A5OnClean');
			if(funcCall != '') eval(funcCall);
			ele.setAttribute('A5IsDirty','false');
			
		}	
		
	}
}





//Following section is for dropdown suggestion lists.

a5_AJAX_autoSuggest = Class.create();
a5_AJAX_autoSuggest.prototype = {
	initialize: function(targetId,settings){
		this.targetId = targetId;
		
		$u.o.assign(this,{
			url: '',
			data: '',
			dynamicHandle: 0,
			minimum: 1,
			width: '',
			height: '',
			contextControls: 0,
			columns: 0,
			className: '',
			item: {
				className: '',
				selectedClassName: '',
				keyClassName: ''
			},
			title: {
				className: '',
				location: 'top'
			},
			onSelect: 0
		});
		
		// use defaults if defined
		if(typeof a5_AJAX_autoSuggestDefaults != 'undefined') $u.o.assign(this,a5_AJAX_autoSuggestDefaults);
		
		$u.o.assign(this,settings);
		$e.add(targetId,'focus',this._focus,this,true);
		$e.add(targetId,'blur',this._hideMatchList,this,true);
		$e.add(targetId,'keyup',this._getList,this,true);
		this._kw = new AUI.KeyWatcher([
			{key: 'enter', handle: this._selectCurValue},
			{key: 'up', handle: this._prevValue},
			{key: 'down', handle: this._nextValue}],this);
		this._listValue = 0;
		this._listTotal = 0;
		this._list = [];
		
		this._parseColumns();
		
		var ele = document.createElement('div');
		ele.id = this.targetId+'.LIST';
		ele.className = this.className;
		ele.style.position = 'absolute';
		ele.style.display = 'none';
		ele.style.height = this.height;
		ele.style.overflow = 'auto';
		document.body.appendChild(ele);
		
	},
	_parseColumns: function(e){
		if(this.columns.constructor == Array){
			var keyFlag = false;
			var colTitle = '';
			for(var i=0;i<this.columns.length;i++){
				if(typeof this.columns[i] == 'object'){
					$u.o.assign(this.columns[i],this._defaultColumn,true);
					if(!keyFlag && this.columns[i].key) keyFlag = true;
					else if(keyFlag && this.columns[i].key) this.columns[i].key = false;
				} else{
					colTitle = this.columns[i];
					this.columns[i] = new Object();
					$u.o.assign(this.columns[i],this._defaultColumn);
					this.columns[i].title = ''+colTitle;
				}
			}
			if(!keyFlag){
				this.columns[0].key = true;
			}
		} else{
			var colTitle = this.columns;
			this.columns = new Array();
			$u.o.assign(this.columns[0],this._defaultColumn);
			this.columns[0].title = ''+colTitle;
			this.columns[0].key = true;
		}
	},
	_focus: function(e){
		e = $e.getEvent(e);
		var lObj = $(this.targetId+'.LIST');
		$po(lObj,$(this.targetId),14,2,0);
		this._kw.on();
	},
	_hideMatchList: function(e){
		var lObj = $(this.targetId+'.LIST');
		classInst = this;
		setTimeout(function(){classInst._hideMatchListComplete();},400);
	},
	_hideMatchListComplete: function(){
		var lObj = $(this.targetId+'.LIST');
		lObj.style.display = 'none';
		this._kw.off();
	},
	_selectValue: function(e,classInst){
		var indx = Number(this.getAttribute('A5SuggestIndex'));
		var val = typeof classInst._list[indx] != 'undefined' ? classInst._list[indx] : '';
		var finVal = val;
		if(finVal.constructor == Array){
			var keyIndx = 0;
			for(var i=0;i<classInst.columns.length;i++){
				if(classInst.columns[i].key){
					keyIndx = i;
					break;
				}
			}
			finVal = finVal[keyIndx];
		}
		if(finVal != '') $(classInst.targetId).value = finVal;
		if(classInst.onSelect.constructor == Function) classInst.onSelect(val);
	},
	_selectCurValue: function(e){
		var val = typeof this._list[this._listValue] != 'undefined' ? this._list[this._listValue] : '';
		var finVal = val;
		if(finVal.constructor == Array){
			var keyIndx = 0;
			for(var i=0;i<this.columns.length;i++){
				if(this.columns[i].key){
					keyIndx = i;
					break;
				}
			}
			finVal = finVal[keyIndx];
		}
		if(finVal != '') $(this.targetId).value = finVal;
		if(this.onSelect.constructor == Function) this.onSelect(val);
		var lObj = $(this.targetId+'.LIST');
		lObj.style.display = 'none';
	},
	_nextValue: function(e){
		if(this._listValue < this._listTotal-1){
			$(this.targetId+'.LIST.'+this._listValue).className = this.item.className;
			this._listValue = this._listValue+1;
			$(this.targetId+'.LIST.'+this._listValue).className = this.item.selectedClassName;
			this._scrollToEntry();
		}
	},
	_prevValue: function(e){
		if(this._listValue > 0){
			$(this.targetId+'.LIST.'+this._listValue).className = this.item.className;
			this._listValue = this._listValue-1;
			$(this.targetId+'.LIST.'+this._listValue).className = this.item.selectedClassName;
			this._scrollToEntry();
		}
	},
	_scrollToEntry: function(){
		var ele = $(this.targetId+'.LIST.'+this._listValue);
		var cEle = $(this.targetId+'.LIST');
		if(cEle.scrollTop > ele.offsetTop) cEle.scrollTop = ele.offsetTop-2;
		else if(cEle.scrollTop+cEle.offsetHeight < (ele.offsetTop+ele.offsetHeight)) cEle.scrollTop = ele.offsetTop+(ele.offsetHeight)-cEle.offsetHeight;
	},
	_getList: function(e){
		e = $e.getEvent(e);
		var keyCode = e.charCode || e.keyCode;
		if(keyCode == 13 || keyCode == 37 || keyCode == 38 || keyCode == 39 || keyCode == 40) return false;
		
		var lObj = $(this.targetId+'.LIST');
		var tObj = $(this.targetId)
		
		if(tObj.value.length < this.minimum){
			lObj.style.display = 'none';
			return '';
		}
		
		if(this.dynamicHandle.constructor == Function){
			var dArr = this.dynamicHandle(tObj.value);
			if(typeof dArr != 'undefined'){
				if(dArr.constructor == Array){
					this.populateList(dArr);
				}
			}
			return '';
		}
		
		var tData = this.data;
		if(tData != '') tData = tData+'&';
		if(this.contextControls.constructor == Array){
			var eles = new Object();
			var varName = '';
			for(var i=0;i<this.contextControls.length;i++){
				eles = $(this.contextControls[i]);
				if(!eles.tagName) varName = eles[0].name;
				else varName = eles.name;
				if(varName != '') tData = tData+a5_AJAX_Form_SubmitValueParam(varName,$gvs(eles))+'&';
			}
		}
		tData = tData+a5_AJAX_Form_SubmitValueParam(tObj.name,tObj.value);
		a5_AJAX_Callback(this.url,tData);
	},
	populateList: function(dArr){
		var lObj = $(this.targetId+'.LIST');
		this._list = dArr;
		this._listTotal = dArr.length;
		if(dArr.length > 0){
			var html = Array();
			
			html[html.length] = '<table style="width: '+this.width+';" id="'+this.targetId+'.LIST.TABLE" cellspacing="0">'
			
			if(this.title.location == 'top' || this.title.location == 'both'){
				html[html.length] = '<tr class="'+this.title.className+'">';
				for(var i=0;i<this.columns.length;i++) html[html.length] = '<td>'+this.columns[i].title+'</td>';
				html[html.length] = '</tr>';
			}
			
			if(dArr[0].constructor == Array){
				for(var i=0;i<dArr.length;i++){
					html[html.length] = '<tr id="'+this.targetId+'.LIST.'+i+'" A5SuggestIndex="'+i+'" class="'+$if(i==0,this.item.selectedClassName,this.item.className)+'">';
					for(var j=0;j<this.columns.length;j++){
						if(this.columns[j].key) html[html.length] = '<td class="'+this.item.keyClassName+'">'+dArr[i][j]+'</td>';
						else html[html.length] = '<td>'+dArr[i][j]+'</td>';
					}
					html[html.length] = '</tr>';
				}
			} else{
				for(var i=0;i<dArr.length;i++){
					html[html.length] = '<tr id="'+this.targetId+'.LIST.'+i+'" A5SuggestIndex="'+i+'" class="'+$if(i==0,this.item.selectedClassName,this.item.className)+'">';
					html[html.length] = '<td class="'+this.item.keyClassName+'">'+dArr[i]+'</td>';
					html[html.length] = '</tr>';
				}
			}
			
			if(this.title.location == 'bottom' || this.title.location == 'both'){
				html[html.length] = '<tr class="'+this.title.className+'">';
				for(var i=0;i<this.columns.length;i++) html[html.length] = '<td>'+this.columns[i].title+'</td>';
				html[html.length] = '</tr>';
			}
			
			html[html.length] = '</table>';
			lObj.innerHTML = html.join('');
			for(var i=0;i<dArr.length;i++){
				$e.add($(this.targetId+'.LIST.'+i),'click',this._selectValue,this);
			}
			
			lObj.style.display = 'block';
		} else{
			lObj.style.display = 'none';
			lObj.style.width = this.width;
		}
		this._listValue = 0;
	},
	_defaultColumn: {
		title: '',
		type: 'text',
		key: false
	}
}


// Tree control
a5_AJAX_tree = Class.create();
a5_AJAX_tree.prototype = {
	initialize: function(contId,data,options){
		this.contId = contId
		
		var fullOptions = {
			inputId: '',
			focusClassName: '',
			multiple: false,
			separator: '.',
			loadingMessage: 'Loading...',
			dynamicDataURL: '',
			dynamicDataHandle: '',
			node: {
				className: '',
				selectedClassName: '',
				labelClassName: '',
				icon: '',
				expandedIcon: '',
				collapsedIcon: '',
				leaf: {
					firstImage: '',
					image: '',
					lastImage: ''
				},
				branch: {
					firstExpandedImage: '',
					firstCollapsedImage: '',
					firstExpandedHoverImage: '',
					firstCollapsedHoverImage: '',
					expandedImage: '',
					collapsedImage: '',
					expandedHoverImage: '',
					collapsedHoverImage: '',
					lastExpandedImage: '',
					lastCollapsedImage: '',
					lastExpandedHoverImage: '',
					lastCollapsedHoverImage: ''
				}
			},
			branch: {
				className: '',
				lineImage: '',
				nullImage: ''
			},
			onFocus: 0,
			onBlur: 0,
			onRightClick: 0,
			onNodeSelect: 0,
			onNodeClick: 0,
			onNodeExpand: 0,
			onNodeCollapse: 0,
			selection: [],
			value: [],
			_hasFocus: false
		};
		$u.o.assign(fullOptions,options);
		
		// use defaults if defined
		if(typeof a5_AJAX_treeDefaults != 'undefined') $u.o.assign(fullOptions,a5_AJAX_treeDefaults);
		
		if(fullOptions.node.collapsedIcon == '') fullOptions.node.collapsedIcon = fullOptions.node.icon;
		if(fullOptions.node.expandedIcon == '') fullOptions.node.expandedIcon = fullOptions.node.collapsedIcon;
		
		if(fullOptions.node.selectedCollapsedIcon == '') fullOptions.node.selectedCollapsedIcon = fullOptions.node.selectedIcon;
		if(fullOptions.node.selectedExpandedIcon == '') fullOptions.node.selectedExpandedIcon = fullOptions.node.selectedCollapsedIcon;
		
		if(fullOptions.branch.lineImage == '') fullOptions.branch.lineImage = fullOptions.branch.nullImage;
		
		if(fullOptions.node.leaf.image == '') fullOptions.node.leaf.image = fullOptions.branch.nullImage;
		if(fullOptions.node.branch.expandedImage == '') fullOptions.node.branch.expandedImage = fullOptions.branch.nullImage;
		if(fullOptions.node.branch.collapsedImage == '') fullOptions.node.branch.collapsedImage = fullOptions.branch.nullImage;
		if(fullOptions.node.leaf.firstImage == '') fullOptions.node.leaf.firstImage = fullOptions.node.leaf.image;
		if(fullOptions.node.leaf.lastImage == '') fullOptions.node.leaf.lastImage = fullOptions.node.leaf.image;
		if(fullOptions.node.branch.firstExpandedImage == '') fullOptions.node.branch.firstExpandedImage = fullOptions.node.branch.expandedImage;
		if(fullOptions.node.branch.lastExpandedImage == '') fullOptions.node.branch.lastExpandedImage = fullOptions.node.branch.expandedImage;
		if(fullOptions.node.branch.firstCollapsedImage == '') fullOptions.node.branch.firstCollapsedImage = fullOptions.node.branch.collapsedImage;
		if(fullOptions.node.branch.lastCollapsedImage == '') fullOptions.node.branch.lastCollapsedImage = fullOptions.node.branch.collapsedImage;
		
		if(fullOptions.node.branch.firstExpandedHoverImage == '') fullOptions.node.branch.firstExpandedHoverImage = fullOptions.node.branch.expandedHoverImage;
		if(fullOptions.node.branch.lastExpandedHoverImage == '') fullOptions.node.branch.lastExpandedHoverImage = fullOptions.node.branch.expandedHoverImage;
		if(fullOptions.node.branch.firstCollapsedHoverImage == '') fullOptions.node.branch.firstCollapsedHoverImage = fullOptions.node.branch.collapsedHoverImage;
		if(fullOptions.node.branch.lastCollapsedHoverImage == '') fullOptions.node.branch.lastCollapsedHoverImage = fullOptions.node.branch.collapsedHoverImage;
		
		$u.o.assign(this,fullOptions);
		
		this.populate(data);
		
		this._keyWatch = new AUI.KeyWatcher([
								{key: 'up', handle: this._keyPrevNode},
								{key: 'down', handle: this._keyNextNode},
								{key: 'left', handle: this._keyBranchNode},
								{key: 'right', handle: this._keyChildNode},
								{key: 'enter', handle: this._keyEnter},
								{key: 'tab', handle: this._blur},
								{key: 'shift+tab', handle: this._blur}
							],this);
		
		var contElement = $(contId);
		var HTMLFocusCatcher = document.createElement('input');
		HTMLFocusCatcher.id = contId+'.FOCUSCATCHER';
		HTMLFocusCatcher.readonly = true;
		HTMLFocusCatcher.style.position = 'absolute';
		HTMLFocusCatcher.style.top = '-20px';
		HTMLFocusCatcher.style.left = '-20px';
		HTMLFocusCatcher.style.height = '1px';
		HTMLFocusCatcher.style.width = '1px';
		HTMLFocusCatcher.style.fontSize = '0px';
		$e.add(HTMLFocusCatcher,'focus',this._focus,this,true);
		$e.add(contElement,'click',this._focus,this,true);
		$e.add(contElement,'contextmenu',this._rClick,this,true);
		contElement.parentNode.insertBefore(HTMLFocusCatcher,contElement);
	},
	populate: function(data){
		this.data = this._expandTreeData(data);
		var HTMLNodes = this._generateHTMLNodes([],[],this.data,true,'');
		HTMLNodes.id = this.contId+'.TREE';
		var contElement = $(this.contId);
		contElement.innerHTML = '';
		contElement.insertBefore(HTMLNodes,contElement.lastChild);
	},
	populateNode: function(nodeLoc,data){
		data = this._expandTreeData(data);
		var nodeImages = new Array();
		nodeImages[nodeImages.length] = $if(nodeLoc[0] == this.data.length-1,this.branch.nullImage,this.branch.lineImage);
		var dataNode = this.data[nodeLoc[0]];
		for(var i=1;i<nodeLoc.length;i++){
			nodeImages[i] = $if(nodeLoc[i] == dataNode.children.length-1,this.branch.nullImage,this.branch.lineImage);
			dataNode = dataNode.children[nodeLoc[i]];
		}
		dataNode.children = data;
		dataNode.location = nodeLoc;
		dataNode.expanded = true;
		var HTMLNodes = this._generateHTMLNodes(nodeLoc,nodeImages,data,true,dataNode.branchClassName);
		$(this.contId+'.'+nodeLoc.join('.')).appendChild(HTMLNodes);
		
		
		
		var iNode = $(this.contId+'.'+dataNode.location.join('.')+'.LABEL').previousSibling;
		$e.remove(iNode,'mouseup',this._clickToggleBranch);
		$e.add(iNode,'mouseup',this._clickToggleBranch,this);
		if(this.node.branch.collapsedHoverImage != '' || dataNode.collapsedHoverImage != ''){
			$e.remove(iNode,'mouseover',this._nodeImageMouseOver);
			$e.remove(iNode,'mouseout',this._nodeImageMouseOut);
			$e.add(iNode,'mouseover',this._nodeImageMouseOver,this);
			$e.add(iNode,'mouseout',this._nodeImageMouseOut,this);
		}
		if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.firstExpandedImage);
		else if(dataNode.isLast) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.lastExpandedImage);
		else iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.expandedImage);
		
	},
	getDataNode: function(dataLoc){
		if(dataLoc.length == 0) return 0;
		var dataNode = this.data[dataLoc[0]];
		
		if(typeof dataLoc[0] == 'number'){
			var dataNode = this.data[dataLoc[0]];
			var parsedNodeLoc = [dataLoc[0]];
		} else {
			for(var i=0;i<this.data.length;i++){
				if(this.data[i].value.toLowerCase() == String(dataLoc[0]).toLowerCase()){
					var dataNode = this.data[i];
					var parsedNodeLoc = [i];
					break;
				}
			}
		}
		
		for(var i=1;i<dataLoc.length;i++){
			if(typeof dataLoc[i] == 'number'){
				dataNode = dataNode.children[dataLoc[i]];
				parsedNodeLoc[parsedNodeLoc.length] = dataLoc[i];
			} else {
				for(var j=0;j<dataNode.children.length;j++){
					if(dataNode.children[j].value.toLowerCase() == String(dataLoc[i]).toLowerCase()){
						dataNode = dataNode.children[j];
						parsedNodeLoc[parsedNodeLoc.length] = j;
						break;
					}
				}
			}
		}
		dataNode.location = parsedNodeLoc;
		return dataNode;
	},
	scrollToNode: function(dataNode){
		var bId = this.contId+'.'+dataNode.location.join('.')+'.LABEL';
		if($(bId)){
			var bNode = $(bId);
			var cEle = $(this.contId);
			if(cEle.scrollTop > bNode.offsetTop-(bNode.parentNode.offsetHeight*2)) cEle.scrollTop = bNode.offsetTop-(bNode.parentNode.offsetHeight*2)
			else if(cEle.scrollTop+cEle.offsetHeight < bNode.offsetTop) cEle.scrollTop = bNode.offsetTop+(bNode.parentNode.offsetHeight)-cEle.offsetHeight;
			//cEle.scrollTop = bNode.offsetTop-(bNode.parentNode.offsetHeight*2);
			cEle.scrollLeft = bNode.offsetLeft-40;
		}
	},
	setValue: function(){
		this._deselectAll();
		var selClassName = '';
		var dataNode = new Object();
		var dataLoc = 0;
		var valArr = 0;
		var valStart = arguments.length-1;
		if(this.multiple) valStart = 0;
		for(var i=valStart;i<arguments.length;i++){
			dataNode = 0;
			if(arguments[i].constructor == Array) dataNode = this.getDataNode(arguments[i]);
			else{
				valArr = String(arguments[i]).split(this.separator);
				if(valArr.length > 1) dataNode = this.getDataNode(valArr);
				else {
					dataLoc = new Array();
					this._getDataNodeFromValue(arguments[i],this.data,dataLoc);
					dataLoc.reverse();
					dataNode = this.getDataNode(dataLoc);
				}
			}
			
			if(typeof dataNode == 'object'){
				selClassName = this._gDef(dataNode.selectedClassName,this.node.selectedClassName);
				if(selClassName != '') $acn($(this.contId+'.'+dataNode.location.join('.')).firstChild,selClassName);
				this.selection[this.selection.length] = dataNode;
			}
		}
	},
	_expandTreeData: function(data){
		var tempData = new Object();
		for(var i=0;i<data.length;i++){
			if(typeof data[i] != 'object'){
				tempData = {html: ''+$u.s.tran(data[i],['<','>'],['&lt;','&gt;']), value: ''+data[i]};
				$u.o.assign(tempData,this._defaultNode,true);
				data[i] = tempData;
			} else{
				if(typeof data[i].value != 'undefined') data[i].defaultValue = false;
				$u.o.assign(data[i],this._defaultNode,true);
				if(data[i].value == '' && data[i].html != '') data[i].value = data[i].html;
				else if(data[i].html == '' && data[i].value != '') data[i].html = $u.s.tran(data[i].value,['<','>'],['&lt;','&gt;']);
				if(data[i].children.constructor == Array) data[i].children = this._expandTreeData(data[i].children);
			}
			
			if(i==data.length-1) data[i].isLast = true;
			else data[i].isLast = false;
		}
		return data;
	},
	_getPrevVisDataNode: function(dataNode){
		var dataLoc = new Array();
		for(var i=0;i<dataNode.location.length;i++) dataLoc[i] = dataNode.location[i];
		if(dataLoc[dataLoc.length-1] == 0){
			dataLoc.pop();
			return this.getDataNode(dataLoc);
		} else{
			dataLoc[dataLoc.length-1]--;
			var newDataNode = this.getDataNode(dataLoc);
			while(newDataNode.expanded){
				dataLoc.push(newDataNode.children.length-1);
				newDataNode = this.getDataNode(dataLoc);
			}
			return newDataNode;
		}
	},
	_getNextVisDataNode: function(dataNode){
		var dataLoc = new Array();
		for(var i=0;i<dataNode.location.length;i++) dataLoc[i] = dataNode.location[i];
		if(dataNode.isLast && !dataNode.expanded){
			// find the next child of the parent, or failing that of the parents parent...
			dataLoc.pop();
			if(dataLoc.length == 0) return false;
			var newDataNode = this.getDataNode(dataLoc);
			while(newDataNode.isLast){
				dataLoc.pop();
				if(dataLoc.length == 0) return false;
				newDataNode = this.getDataNode(dataLoc);
			}
			dataLoc[dataLoc.length-1]++;
			return this.getDataNode(dataLoc);
		} else{
			if(dataNode.expanded){
				dataLoc[dataLoc.length] = 0;
				return this.getDataNode(dataLoc);
			} else{
				dataLoc[dataLoc.length-1]++;
				return this.getDataNode(dataLoc);
			}
		}
	},
	_getDataNodeFromValue: function(value,data,dataLoc){
		var dataNode = 0;
		for(var i=0;i<data.length;i++){
			if(data[i].value == value){
				dataLoc[0] = i;
				break;
			}
			
			if(data[i].children.constructor == Array) this._getDataNodeFromValue(value,data[i].children,dataLoc);
			if(dataLoc.length > 0){
				dataLoc.push(i);
				break;
			}
		}
	},
	_getDataNodeValue: function(dataNode){
		if(dataNode.defaultValue){
			var valDataNode = new Object();
			var valDataLoc = new Array();
			var curValue = '';
			for(var i=0;i<dataNode.location.length;i++) valDataLoc[i] = dataNode.location[i];
			for(var i=valDataLoc.length-1;i>=0;i--){
				valDataNode = this.getDataNode(valDataLoc);
				curValue = $if(i!=0,this.separator,'')+valDataNode.value+curValue;
				valDataLoc.pop();
			}
			return curValue;
		} else{
			return dataNode.value;
		}
	},
	_generateHTMLNodes: function(parentNodeLocs,parentNodeLineImages,data,expanded,branchClassName){
		var ulNode = document.createElement('ul');
		var liNode = new Object();
		var divNode = new Object();
		var buttonNode = new Object();
		var tempNode = new Object();
		var tempNodeloc = new Array();
		var tempLineImages = new Array();
		var joinedParentLocs = parentNodeLocs.join('.');
		var baseId = '';
		var isLast = false;
		var curIcon = '';
		
		ulNode.className = this._gDef(branchClassName,this.branch.className);
		ulNode.style.margin = '0px';
		ulNode.style.padding = '0px';
		ulNode.style.listStyle = 'none';
		if(!expanded) ulNode.style.display = 'none';
		ulNode.unselectable = 'on';
		for(var i=0;i<data.length;i++){
			baseId = $if(joinedParentLocs!='',this.contId+'.'+joinedParentLocs+'.'+i,this.contId+'.'+i);
			
			liNode = document.createElement('li');
			liNode.style.margin = '0px';
			liNode.style.padding = '0px';
			liNode.id = baseId;
			liNode.setAttribute('A5AJAXTreeNodeLocation',$if(joinedParentLocs!='',joinedParentLocs+'.'+i,i))
			liNode.unselectable = 'on';
			
			divNode = document.createElement('div');
			divNode.className = this._gDef(data[i].className,this.node.className);
			divNode.style.whiteSpace = 'nowrap';
			divNode.unselectable = 'on';
			
			// content of node
			// establish location in array
			if(i == data.length-1) isLast = true;
			// create indent images
			for(var j=0;j<parentNodeLineImages.length;j++){
				tempNode = document.createElement('img');
				tempNode.src = parentNodeLineImages[j];
				tempNode.style.verticalAlign = 'middle';
				tempNode.align = 'absmiddle';
				divNode.appendChild(tempNode);
			}
			
			// the button part of the node
			buttonNode = document.createElement('a');
			buttonNode.tabIndex = 1;
			buttonNode.href = "#";
			$e.add(buttonNode,'mouseup',this._clickNode,this);
			buttonNode.className = this._gDef(data[i].labelClassName,this.node.labelClassName);
			buttonNode.id = baseId+'.LABEL';
			buttonNode.unselectable = 'on';
			
			
			// handle branch or leaf
			if(typeof data[i].children == 'object' || typeof data[i].children == 'string'){
				// has children - is branch
				
				if(data[i].children.constructor != Array) data[i].expanded = false;
				
				tempNode = document.createElement('img');
				if(data[i].expanded){
					curIcon = this._gDef(data[i].expandedIcon,this.node.expandedIcon);
					if(i==0 && parentNodeLocs.length == 0) tempNode.src = this._gDef(data[i].expandedImage,this.node.branch.firstExpandedImage);
					else if(isLast) tempNode.src = this._gDef(data[i].expandedImage,this.node.branch.lastExpandedImage);
					else tempNode.src = this._gDef(data[i].expandedImage,this.node.branch.expandedImage);
				} else{
					curIcon = this._gDef(data[i].collapsedIcon,this.node.collapsedIcon);
					if(i==0 && parentNodeLocs.length == 0) tempNode.src = this._gDef(data[i].collapsedImage,this.node.branch.firstCollapsedImage);
					else if(isLast) tempNode.src = this._gDef(data[i].collapsedImage,this.node.branch.lastCollapsedImage);
					else tempNode.src = this._gDef(data[i].collapsedImage,this.node.branch.collapsedImage);
				}
				
				if(this.node.branch.collapsedHoverImage != '' || data[i].collapsedHoverImage != ''){
					$e.add(tempNode,'mouseover',this._nodeImageMouseOver,this);
					$e.add(tempNode,'mouseout',this._nodeImageMouseOut,this);
				}
				
				tempNode.style.verticalAlign = 'middle';
				tempNode.align = 'absmiddle';
				$e.add(tempNode,'mouseup',this._clickToggleBranch,this);
				divNode.appendChild(tempNode);
				
				// interior of button part of node
				
				if(curIcon != ''){
					buttonNode.innerHTML = '<img id="'+baseId+'.LABELICON" src="'+curIcon+'" style="border: none" align="absmiddle" /> '+data[i].html;
				} else{
					buttonNode.innerHTML = data[i].html;
				}
				
				divNode.appendChild(buttonNode);
				
				// do branch
				if(data[i].children.constructor == Array){
					if(parentNodeLocs.length == 0){
						tempNodeLocs = new Array();
						tempLineImages = new Array();
					} else{
						tempNodeLocs = parentNodeLocs.concat([]);
						tempLineImages = parentNodeLineImages.concat([]);
					}
					tempNodeLocs[tempNodeLocs.length] = i;
					tempLineImages[tempLineImages.length] = $if(isLast,this.branch.nullImage,this.branch.lineImage);
					
					liNode.appendChild(divNode);
					liNode.appendChild(this._generateHTMLNodes(tempNodeLocs,tempLineImages,data[i].children,data[i].expanded,data[i].branchClassName));
				} else liNode.appendChild(divNode);
			} else{
				// no children - is leaf
				tempNode = document.createElement('img');
				if(i==0 && parentNodeLocs.length == 0) tempNode.src = this._gDef(data[i].image,this.node.leaf.firstImage);
				else if(isLast) tempNode.src = this._gDef(data[i].image,this.node.leaf.lastImage);
				else tempNode.src = this._gDef(data[i].image,this.node.leaf.image);
				tempNode.style.verticalAlign = 'middle';
				tempNode.align = 'absmiddle';
				divNode.appendChild(tempNode);
				// interior of button part of node
				curIcon = this._gDef(data[i].icon,this.node.icon);
				if(curIcon != ''){
					buttonNode.innerHTML = '<img id="'+baseId+'.LABELICON" src="'+curIcon+'" style="border: none" align="absmiddle" /> '+data[i].html;
				} else{
					buttonNode.innerHTML = data[i].html;
				}
				divNode.appendChild(buttonNode);
				liNode.appendChild(divNode);
			}
			
			// append node
			ulNode.appendChild(liNode);
		}
		return ulNode;
	},
	_clickToggleBranch: function(e,classInstance){
		var liEle = this.parentNode.parentNode;
		var dataLocArr = String(liEle.getAttribute('A5AJAXTreeNodeLocation')).split('.');
		for(var i=0;i<dataLocArr.length;i++) dataLocArr[i] = Number(dataLocArr[i]);
		var dataNode = classInstance.getDataNode(dataLocArr,false);
		classInstance._toggleBranch(dataNode,true);
	},
	_toggleBranch: function(dataNode){
		if(dataNode.children.constructor != Array){
			if(dataNode.dynamicDataHandle.constructor == Function || this.dynamicDataHandle.constructor == Function){
				if(dataNode.dynamicDataHandle.constructor == Function) var resData = dataNode.dynamicDataHandle(dataNode);
				else var resData = this.dynamicDataHandle(dataNode);
				if(resData.constructor == Array){
					this.populateNode(dataNode.location,resData);
					if(dataNode.onExpand.constructor == Function) dataNode.onExpand(dataNode);
					else if(this.onNodeExpand.constructor == Function) this.onNodeExpand(dataNode);
				}
			} else{
				var curValue = this._getDataNodeValue(dataNode);
				var dataURL = '';
				if(typeof dataNode.children == 'object'){
					dataURL = dataNode.children.url;
					if(dataURL == '') dataURL = this.dynamicDataURL;
					if(dataURL != '') new $a.simple(dataNode.children.url,{data: $if(dataNode.children.data,dataNode.children.data+'&','')+'A5AJAXTreeNodeLoaction=['+dataNode.location.join(',')+']&A5AJAXTreeNodeValue='+curValue, handle: this._responseHandle, handleContext: this})
				} else{
					dataURL = ''+dataNode.children;
					if(dataURL.substr(0,1) == '?') dataURL = this.dynamicDataURL;
					if(dataURL != '') new $a.simple(dataURL,{data: 'A5AJAXTreeNodeLoaction=['+dataNode.location.join(',')+']&A5AJAXTreeNodeValue='+curValue, handle: this._responseHandle, handleContext: this})
				}
				$(this.contId+'.'+dataNode.location.join('.')+'.LABEL').innerHTML = this.loadingMessage;
			}
			var iNode = $(this.contId+'.'+dataNode.location.join('.')+'.LABEL').previousSibling;
			
			if(arguments[1]){
				if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.firstExpandedHoverImage,dataNode.expandedImage,this.node.branch.firstExpandedImage);
				else if(dataNode.isLast) iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.lastExpandedHoverImage,dataNode.expandedImage,this.node.branch.lastExpandedImage);
				else iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.expandedHoverImage,dataNode.expandedImage,this.node.branch.expandedImage);
			} else{
				if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.firstExpandedImage);
				else if(dataNode.isLast) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.lastExpandedImage);
				else iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.expandedImage);
			}
			
			dataNode.expanded = true;
		} else{
			var iNode = $(this.contId+'.'+dataNode.location.join('.')+'.LABEL').previousSibling;
			var bNode = $(this.contId+'.'+dataNode.location.join('.')).lastChild;
			while(!bNode.tagName){
				bNode = bNode.previousSibling;
			}
			
			if(bNode.style.display == 'none'){
				if(arguments[1]){
					if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.firstExpandedHoverImage,dataNode.expandedImage,this.node.branch.firstExpandedImage);
					else if(dataNode.isLast) iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.lastExpandedHoverImage,dataNode.expandedImage,this.node.branch.lastExpandedImage);
					else iNode.src = this._gDef(dataNode.expandedHoverImage,this.node.branch.expandedHoverImage,dataNode.expandedImage,this.node.branch.expandedImage);
				} else{
					if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.firstExpandedImage);
					else if(dataNode.isLast) iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.lastExpandedImage);
					else iNode.src = this._gDef(dataNode.expandedImage,this.node.branch.expandedImage);
				}
				
				var curIcon = this._gDef(dataNode.expandedIcon,this.node.expandedIcon);
				if(curIcon != ''){
					if($(this.contId+'.'+dataNode.location.join('.')+'.LABELICON')){
						$(this.contId+'.'+dataNode.location.join('.')+'.LABELICON').src = curIcon;
					}
				}
					
				bNode.style.display = 'block';
				dataNode.expanded = true;
				if(dataNode.onExpand.constructor == Function) dataNode.onExpand(dataNode);
				else if(this.onNodeExpand.constructor == Function) this.onNodeExpand(dataNode);
			} else{
				if(arguments[1]){
					if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.collapsedHoverImage,this.node.branch.firstCollapsedHoverImage,dataNode.collapsedImage,this.node.branch.firstCollapsedImage);
					else if(dataNode.isLast) iNode.src = this._gDef(dataNode.collapsedHoverImage,this.node.branch.lastCollapsedHoverImage,dataNode.collapsedImage,this.node.branch.lastCollapsedImage);
					else iNode.src = this._gDef(dataNode.collapsedHoverImage,this.node.branch.collapsedHoverImage,dataNode.collapsedImage,this.node.branch.collapsedImage);
				} else{
					if(dataNode.location[dataNode.location.length-1] == 0 && dataNode.location.length == 1) iNode.src = this._gDef(dataNode.collapsedImage,this.node.branch.firstCollapsedImage);
					else if(dataNode.isLast) iNode.src = this._gDef(dataNode.collapsedImage,this.node.branch.lastCollapsedImage);
					else iNode.src = this._gDef(dataNode.collapsedImage,this.node.branch.collapsedImage);
				}
				
				var curIcon = this._gDef(dataNode.collapsedIcon,this.node.collapsedIcon);
				if(curIcon != ''){
					if($(this.contId+'.'+dataNode.location.join('.')+'.LABELICON')){
						$(this.contId+'.'+dataNode.location.join('.')+'.LABELICON').src = curIcon;
					}
				}
				
				bNode.style.display = 'none';
				dataNode.expanded = false;
				
				if(dataNode.onCollapse.constructor == Function) dataNode.onCollapse(dataNode);
				else if(this.onNodeCollapse.constructor == Function) this.onNodeCollapse(dataNode);
			}
		}
	},
	_selectNode: function(dataNode){
		var curValue = [];
		var selClassName = '';
		if(this.multiple && (this._keyWatch.ctrl || this._keyWatch.shift)){
			var addToSel = true;
			for(var i=0;i<this.selection.length;i++){
				if(this.selection[i].location.join('.') == dataNode.location.join('.')){
					selClassName = this._gDef(this.selection[i].selectedClassName,this.node.selectedClassName);
					if(selClassName != '') $rcn($(this.contId+'.'+this.selection[i].location.join('.')).firstChild,selClassName);
					this.selection.splice(i,1);
					addToSel = false;
					break;
				}
			}
			if(addToSel){
				selClassName = this._gDef(dataNode.selectedClassName,this.node.selectedClassName);
				if(selClassName != '') $acn($(this.contId+'.'+dataNode.location.join('.')).firstChild,selClassName);
				this.selection[this.selection.length] = dataNode;
			}
		} else{
			this._deselectAll();
			selClassName = this._gDef(dataNode.selectedClassName,this.node.selectedClassName);
			if(selClassName != '') $acn($(this.contId+'.'+dataNode.location.join('.')).firstChild,selClassName);
			this.selection[0] = dataNode;
		}
		
		for(var i=0;i<this.selection.length;i++){
			curValue[i] = this._getDataNodeValue(this.selection[i])
		}
		this.value = curValue;
		if(this.inputId != '') $(this.inputId).value = curValue.join('\n');
		
		if(dataNode.onSelect.constructor == Function) dataNode.onSelect(dataNode);
		else if(this.onNodeSelect.constructor == Function) this.onNodeSelect(dataNode);
	},
	_deselectAll: function(){
		var oldDataNode = new Object();
		for(var i=0;i<this.selection.length;i++){
			oldDataNode = this.selection[i];
			if(typeof oldDataNode == 'object'){
				selClassName = this._gDef(oldDataNode.selectedClassName,this.node.selectedClassName);
				if(selClassName != '') $rcn($(this.contId+'.'+oldDataNode.location.join('.')).firstChild,selClassName);
				
			}
		}
		this.selection = new Array();
	},
	_nodeImageMouseOver: function(e,classInstance){
		var liEle = this.parentNode.parentNode;
		var dataLocArr = String(liEle.getAttribute('A5AJAXTreeNodeLocation')).split('.');
		for(var i=0;i<dataLocArr.length;i++) dataLocArr[i] = Number(dataLocArr[i]);
		var dataNode = classInstance.getDataNode(dataLocArr,false);
		if(dataNode.expanded){
			if(dataNode.location[dataNode.location.length-1]==0 && dataNode.location.length == 1) this.src = classInstance._gDef(dataNode.expandedHoverImage,classInstance.node.branch.firstExpandedHoverImage);
			else if(dataNode.isLast) this.src = classInstance._gDef(dataNode.expandedHoverImage,classInstance.node.branch.lastExpandedHoverImage);
			else this.src = classInstance._gDef(dataNode.expandedHoverImage,classInstance.node.branch.expandedHoverImage);
		} else{
			if(dataNode.location[dataNode.location.length-1]==0 && dataNode.location.length == 1) this.src = classInstance._gDef(dataNode.collapsedHoverImage,classInstance.node.branch.firstCollapsedHoverImage);
			else if(dataNode.isLast) this.src = classInstance._gDef(dataNode.collapsedHoverImage,classInstance.node.branch.lastCollapsedHoverImage);
			else this.src = classInstance._gDef(dataNode.collapsedHoverImage,classInstance.node.branch.collapsedHoverImage);
		}
	},
	_nodeImageMouseOut: function(e,classInstance){
		var liEle = this.parentNode.parentNode;
		var dataLocArr = String(liEle.getAttribute('A5AJAXTreeNodeLocation')).split('.');
		for(var i=0;i<dataLocArr.length;i++) dataLocArr[i] = Number(dataLocArr[i]);
		var dataNode = classInstance.getDataNode(dataLocArr,false);
		if(dataNode.expanded){
			if(dataNode.location[dataNode.location.length-1]==0 && dataNode.location.length == 1) this.src = classInstance._gDef(dataNode.expandedImage,classInstance.node.branch.firstExpandedImage);
			else if(dataNode.isLast) this.src = classInstance._gDef(dataNode.expandedImage,classInstance.node.branch.lastExpandedImage);
			else this.src = classInstance._gDef(dataNode.expandedImage,classInstance.node.branch.expandedImage);
		} else{
			if(dataNode.location[dataNode.location.length-1]==0 && dataNode.location.length == 1) this.src = classInstance._gDef(dataNode.collapsedImage,classInstance.node.branch.firstCollapsedImage);
			else if(dataNode.isLast) this.src = classInstance._gDef(dataNode.collapsedImage,classInstance.node.branch.lastCollapsedImage);
			else this.src = classInstance._gDef(dataNode.collapsedImage,classInstance.node.branch.collapsedImage);
		}
	},
	_clickNode: function(e,classInstance){
		$(classInstance.contId+'.FOCUSCATCHER').focus();
		var liEle = this.parentNode.parentNode;
		var dataLocArr = String(liEle.getAttribute('A5AJAXTreeNodeLocation')).split('.');
		for(var i=0;i<dataLocArr.length;i++) dataLocArr[i] = Number(dataLocArr[i]);
		var dataNode = classInstance.getDataNode(dataLocArr,false);
		
		classInstance._selectNode(dataNode);
		
		if(dataNode.onClick.constructor == Function) dataNode.onClick(dataNode);
		else if(classInstance.onNodeClick.constructor == Function) classInstance.onNodeClick(dataNode);
	},
	_keyPrevNode: function(){
		var oldDataNode = this.selection[this.selection.length-1];
		if(typeof oldDataNode == 'object'){
			if(oldDataNode.location.join('') != '0'){
				var dataNode = this._getPrevVisDataNode(oldDataNode);
				this._selectNode(dataNode);
				this.scrollToNode(dataNode);
			}
		} else{
			this._selectNode(this.getDataNode([0]));
		}
	},
	_keyNextNode: function(){
		var oldDataNode = this.selection[this.selection.length-1];
		if(typeof oldDataNode == 'object'){
			var dataNode = this._getNextVisDataNode(oldDataNode);
			if(typeof dataNode.location != 'undefined'){
				this._selectNode(dataNode);
				this.scrollToNode(dataNode);
			}
		} else{
			this._selectNode(this.getDataNode([0]));
		}
	},
	_keyBranchNode: function(){
		var oldDataNode = this.selection[this.selection.length-1];
		if(typeof oldDataNode == 'object'){
			if(oldDataNode.expanded == true){
				this._toggleBranch(oldDataNode);
			} else{
				var dataLoc = new Array();
				for(var i=0;i<oldDataNode.location.length-1;i++) dataLoc[i] = oldDataNode.location[i];
				if(dataLoc.length > 0) this._selectNode(this.getDataNode(dataLoc));
			}
		} else{
			this._selectNode(this.getDataNode([0]));
		}
	},
	_keyChildNode: function(){
		var oldDataNode = this.selection[this.selection.length-1];
		if(typeof oldDataNode == 'object'){
			if(oldDataNode.expanded == false && (typeof oldDataNode.children == 'object' || typeof oldDataNode.children == 'string')){
				this._toggleBranch(oldDataNode);
			} else if(typeof oldDataNode.children == 'object' || typeof oldDataNode.children == 'string'){
				var dataNode = this._getNextVisDataNode(oldDataNode);
				if(typeof dataNode.location != 'undefined'){
					this._selectNode(dataNode);
					this.scrollToNode(dataNode);
				}
			}
		} else{
			this._selectNode(this.getDataNode([0]));
		}
	},
	_keyEnter: function(){
		var dataNode = this.selection[this.selection.length-1];
		if(typeof dataNode == 'object'){
			if(typeof dataNode.children == 'object' || typeof dataNode.children == 'string') this._toggleBranch(dataNode);
			else{
				if(dataNode.onClick.constructor == Function) dataNode.onClick(dataNode);
				else if(this.onNodeClick.constructor == Function) this.onNodeClick(dataNode);
			}
		}
	},
	_rClick: function(e,classInstance){
		if(classInstance.onRightClick.constructor == Function){
			classInstance.onRightClick();
			e = $e.getEvent(e);
			$e.stopEvent(e);
			return false;
		}
	},
	_focus: function(e){
		if(this._hasFocus == false){
			$(this.contId+'.FOCUSCATCHER').style.top = $gpt($(this.contId))+'px';
			this._keyWatch.on();
			this._hasFocus = true;
			$e.add(document.documentElement,'click',this._blur,this,true);
			if(this.focusClassName != '') $acn($(this.contId),this.focusClassName);
			if(this.onFocus.constructor == Function) this.onBlur();
		}
		e = $e.getEvent(e);
		$e.stopEvent(e);
		return false;
	},
	_blur: function(){
		this._hasFocus = false;
		this._keyWatch.off();
		if(this.focusClassName != '') $rcn($(this.contId),this.focusClassName);
		$e.remove(document.documentElement,'click',this._blur);
		if(this.onBlur.constructor == Function) this.onBlur();
	},
	_responseHandle: function(obj){
		var resJSON = eval('('+obj.responseText+')');
		this.populateNode(resJSON.location,resJSON.data);
		
		var dataNode = this.getDataNode(resJSON.location);
		var baseId = this.contId+'.'+resJSON.location.join('.');
		var buttonNode = $(baseId+'.LABEL');
		var curIcon = this._gDef(dataNode.expandedIcon,this.node.expandedIcon);
		if(curIcon != ''){
			buttonNode.innerHTML = '<img id="'+baseId+'.LABELICON" src="'+curIcon+'" style="border: none" align="absmiddle" /> '+dataNode.html;
		} else{
			buttonNode.innerHTML = dataNode.html;
		}
		if(dataNode.onExpand.constructor == Function) dataNode.onExpand(dataNode);
		else if(this.onNodeExpand.constructor == Function) this.onNodeExpand(dataNode);
	},
	_gDef: function(val, dVal){
		for(var i=0;i<arguments.length;i++) if(arguments[i] != '') return arguments[i];
		return '';
	},
	_defaultNode: {
		html: '',
		value: '',
		children: 0,
		className: '',
		selectedClassName: '',
		labelClassName: '',
		branchClassName: '',
		icon: '',
		expandedIcon: '',
		collapsedIcon: '',
		image: '',
		expandedImage: '',
		collapsedImage: '',
		expandedHoverImage: '',
		collapsedHoverImage: '',
		onSelect: 0,
		onClick: 0,
		onExpand: 0,
		onCollapse: 0,
		dynamicDataHandle: 0,
		expanded: false,
		defaultValue: true
	}
}


