var autoCompleteControl			= function( )
{
	var	self					= this ;
	
	self.base					= baseClass ;
	self.base( ) ;
	
	var baseInitalise			= self.initalise ;
	self.name					= "Auto Complete Control" ;
	
	self.delimter				= ";" ;
	self.valueArray				= self.delimter.split( self.delimter ) ;
	self.lastValue				= "" ;
	self.lastProcessedValue		= "" ;
	self.minimumEntryLength		= 3 ;
	self.url					= "" ;
	self.imageSource			= 'hourglas.gif' ;
	self.errorImageSource		= 'error.gif' ;
	
	self.itemName				= "Item" ;
	self.updateTimer			= null ;
	self.enableAutomaticNewCreation	= false ;

	self.isDone					= true ;
	self.useButtonEventFiring	= false ;
	self.useWebservice			= false ;
	self.useDisplayQueryImage	= true ;
	self.hasErrors				= false ;

	self.autoCompleteControl	= null ;
	self.displayControl			= null ;
	self.valueControl			= null ;
	self.imageControl			= null ;
	self.goButtonControl		= null ;
	
	self.http					= null ;
	self.isDebugMode			= false ;
	
	self.onGetSoapEnvelope		= function( value ){ return "" ; } ;
	self.onGetPostData        = function( value ){ return "" ; } ;
	
	self.getAjaxResult			= function( searchString )
	{
		self.lastValue			= self.displayControl.value; 
		if ( searchString.length >= self.minimumEntryLength && self.lastProcessedValue != searchString && self.isDone == true && ( !self.useButtonEventFiring || ( self.useButtonEventFiring && self.goButtonControl.value == "go" ) ) )
		{
			self.lastProcessedValue		= self.displayControl.value ;
			self.isDone			= false;
			// cache buster
			var randomNumber	= parseFloat( Math.random() * 99999999 ) ;
			self.http			= getHTTPObject( ) ;
			self.http.onreadystatechange		= self.handleHttpResponse ;
			if ( self.useWebservice )
			{
				self.http.open( "POST" , self.url , true ) ;
				self.http.setRequestHeader( "MessageType" , "CALL" ) ;
				self.http.setRequestHeader( "Content-Type" , "text/xml" ) ;
				self.http.send( self.getSoapEnvelope( self.lastValue ) );
			}
			else if( self.usePostBack )
			{
				self.http.open( "POST" , self.url + "/" + self.member, true ) ;
				self.http.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
				self.http.send( self.getPostData( self.lastValue ) ) ;
			}
			else
			{
			  self.http.open( "GET" , self.url + "/" + self.member + "?" + self.getPostData( self.lastValue ), true );
			  self.http.send( null );
			}
			return true ;
		}
		else if ( searchString.length < 1 && self.minimumEntryLength == true ) 
		{
			self.valueArray		= ";".split( ";" ) ;
			self.autoCompleteControl.close( ) ;
			self.isDone			= true; 
			document.body.style.cursor = 'auto' ; 
			self.displayControl.style.cursor = 'auto'; 
		}
		else if ( self.useButtonEventFiring )
		{
			self.autoCompleteControl.close( ) ;
		}
		return false ;
	} ;
	
	self.handleHttpResponse		= function( )
	{
		if ( self.http.readyState == 4 || self.http.readyState == 'complete' )
		{
			var strResponse = self.http.responseText ;
			switch ( self.http.status )
			{
				case 404 : // Page-not-found error
					alert( 'Error: Not Found. The requested function could not be found.' ) ;
					self.isDone	= true ; 
					break ;
				case 500 : // Display results in a full window for server-side errors
					self.handleFullPageError( strResponse ) ;
					break ;
				default:
					if ( strResponse.toLowerCase().indexOf( "the service you requested is unavailable at this time" ) > -1) 
					{ 
						self.handleFullPageError( strResponse ) ;
					} 
					else if ( strResponse.toLowerCase().indexOf( "the page you were looking for could not be found" ) > -1) 
					{ 
						alert( 'Error: Not Found. The requested function could not be found.' ) ; 
						self.isDone	= true; 
					} 
					else 
					{ 
						if ( strResponse.indexOf( "<?xml" ) < 0 ) 
						{ 
							// 
						} 
						else
						{ 
						  if(self.useWebService)
							  strResponse		= self.http.responseXML.documentElement.childNodes[ 0 ].childNodes[ 0 ].childNodes[ 0 ].childNodes[ 0 ].nodeValue ;
							else
							  strResponse		= self.http.responseXML.documentElement.childNodes[ 0 ].nodeValue ;
						} 
						self.processResponse( strResponse ) ;
					} 
					break ;
			} 
		} 
		return true ;
	} ;

	self.handleFullPageError 	= function ( errorMessage )
	{ 
		if ( self.isDebugMode == true ) 
		{ 
			self.autoCompleteControl.setOptions( self.delimter.split( self.delimter ) ) ;
			if ( self.useDisplayQueryImage )
			{
				self.imageControl.src				= self.errorImageSource ;
				document.body.style.cursor			= 'auto' ;
				self.displayControl.style.cursor	= 'auto' ;
			}
			self.hasErrors		= true; 
			var errorWin ;
			// Create new window and display error 
			try
			{
				errorWin = window.open( '' , 'errorWin' ); 
				errorWin.document.body.innerHTML = errorMessage; 
			} 
			// If pop-up gets blocked, inform user
			catch ( e ) 
			{
				alert( 'An error occurred, but the error message cannot be displayed because of your browser\'s pop-up blocker.\nPlease allow pop-ups from this Web site.' ) ;
				alert( strIn ) ; 
			} 
		} 
		else 
		{ 
			alert( 'Error: There was an error processing your request.' ) ;
		} 
		return false ;
	} ;
	
	// This should be overriden with some external 
	self.getSoapEnvelope		= function( value )
	{
		return					self.onGetSoapEnvelope( value )  ; 
	} ;
	
	self.getPostData        = function( value )
	{
	  return          self.onGetPostData( value ) ;
	} ;
	
	self.processResponse		= function( response )
	{
		if ( response.length == 0 )
		{
			self.valueArray		= self.delimter.split( self.delimter ) ;
		}
		else
		{
			self.valueArray		= response.split( self.delimter ) ;
		}
		self.isDone				= true ;
		self.updateArray( ) ; 
	} ;
	
	self.updateArray			= function( )
	{
		if ( self.hasErrors )
		{
			clearTimeout( self.updateTimer ) ;
			self.hasErrors		= false;
			self.isDone			= true;
		}
		else
		{ 
			self.autoCompleteControl.close( ) ;
			self.autoCompleteControl.setOptions( self.valueArray ) ;
			self.autoCompleteControl.open( ) ;
			if ( self.useDisplayQueryImage )
			{
				self.imageControl.style.visibility	= 'hidden' ;
				document.body.style.cursor			= 'auto' ;
				self.displayControl.style.cursor	= 'auto' ;
			}
			clearTimeout( self.updateTimer ) ;
			self.isDone			= true; 
			if ( self.lastValue != self.lastProcessedValue ) 
			{
				self.autoCompleteControl.close( ) ;
				self.autoCompleteControl.ongetoptions( ) ;
			}
		}
	} ;

	self.makeAutoComplete		= function( element , elementHid , array , sNew )
	{
		var self				= this ;
		var obj					= element ;
		obj.options				= array.sort( ) ;
		obj.size 				= 10 ;
		var div 				= document.createElement( 'SPAN' ) ;
		div.className			= "autoCompleteFrame" ;
		div.style.zIndex		= 30 ;
		element.autoComplete	= "off" ;
		element.setAttribute( "autocomplete" , "off" ) ;

		// Hack for IE else size dosn't work
		div.innerHTML			= '<select size="2"><option></option></select>' ;
		var select				= div.getElementsByTagName( 'SELECT' )[ 0 ] ;
		element.parentNode.insertBefore( div, element ) ;
		div.appendChild( element ) ;

		div.style.position		= 'relative' ;

		select.className		= "autoCompleteSelect" ;
		select.style.position	= 'absolute' ;
		select.style.top		= '22px' ;
		select.style.visibility	= 'hidden' ;
		select.style.zIndex		= 40 ;
		select.options.length	= 0 ;

		var option				= document.createElement( 'OPTION' ) ;
		select.appendChild( option ) ;
		
		addEvent( element,	'keyup',	function( e ){ obj.open( e ) ; } ) ;
		addEvent( element,	'keydown',	ElementKeyDown ) ;
		addEvent( element,	'dblclick',	function( ){ obj.open( null , true ) ; } ) ;
		addEvent( select,	'click',	SelectClick ) ;
		addEvent( select,	'keyup',	SelectKeyUp ) ;
		addEvent( document,	'click',	DocClick ) ;

		obj.name 				= element.name ;
		obj.element 			= element ;
		obj.elementHid 			= elementHid ;
		obj.select 				= select ;
		
		var formSubmitEvent		= null ;
		var isFormSubmitEventReset = false ;

		function DocClick( e )
		{
			if ( browser && browser.isSafari == false )
			{
				var el = e.target || e.srcElement ;
				var close		= true ;
				while( el.parentNode )
				{
					if( el == select || el == element )
					{
						return	true ;
					}
					el			= el.parentNode ;
				}
				obj.close( ) ;
			}
			return				true ;
		} ;

		function SelectKeyUp( e )
		{
			if ( e.keyCode == 13 )
			{
				SelectClick( ) ;
			}
		} ;

		function ElementKeyDown( e )
		{
			if ( e.keyCode == 40 && select.options.length > 0 )
			{
				select.focus( ) ;
			}
			if ( e.keyCode == 9 && select.options.length > 0 )
			{
				obj.close( ) ;
			}
		} ;

		function SelectClick( )
		{
			if ( select.value == "(*)~%" )
			{
				obj.close( ) ;
				addNew( element, elementHid, element.value ) ;
				return false ;
			}
			if ( select && select.options && select.options[ select.selectedIndex ] )
			{
				element.value		= select.options[ select.selectedIndex ].text ;
				elementHid.value = select.value + ";" + select.options[select.selectedIndex].text + ";" + select.options[select.selectedIndex].components;
				obj.close( ) ;
			}
			else
			{
				alert( "Cannot determine selected value" ) ;
				return false ;
			}
			obj.close( ) ;
			try
			{
				if( element.select )
				{
					element.select( ) ;
				}
			}
			catch( ex ) { }
			element.focus( ) ;
			// Tie in validator
			if( element.validate )
			{
				element.validate( ) ;
			}
		} ;

		obj.ongetoptions		= function( )
		{
		} ;

		obj.setOptions			= function( array )
		{
			obj.options			= array ;
		} ;
		obj.getOptions			= function( )
		{
			return				obj.options ;
		} ;	

		obj.close = function()
		{
			select.options.length	= 0 ;
			select.style.visibility	= 'hidden' ;
			if ( browser && browser.isSafari )
			{
				select.form.onsubmit = formSubmitEvent ; 
				isFormSubmitEventReset = true ;
			}
		} ;

		obj.open = function( e, open )
		{
			if ( browser && browser.isSafari && isFormSubmitEventReset == true )
			{
				formSubmitEvent		= select.form.onsubmit ;
				isFormSubmitEventReset = false ;
				select.form.onsubmit= function( ){ return false ; } ;
			}
			// On tab focus do not process
			if ( e && e.keyCode == 9 ) 
			{
				return false ;
			}
			
			var text			= element.value.toLowerCase( ) ;
			obj.ongetoptions( ) ;
			
			var matches			= obj.options ;

			
			if ( element.value.length > 0 && sNew )
			{
				matches[ matches.length ]	= "(*)~%" ;
				matches[ matches.length ]	= "Add New " + itemName ;
			}
			
			try
			{
				select.options.length		= 0 ;
			}
			catch( e ){}
		  if((open || text.length > 0) && matches.length % 3 == 0){
			  for(var i=0;i<matches.length;i+=3){
				  var oValue	= matches[i]
				  var oText	= matches[i+1]
				  var oComp = matches[i+2]
				  if (oValue.length > 0 || oText.length > 0){
					  var option			= document.createElement('OPTION')
					  option.innerHTML	= oText
					  option.value		= oValue
					  option.components = oComp
					  select.appendChild( option )
				  }
			  }
		  }

			select.selectedIndex			= -1 ;
			if ( select.options.length > 0 )
			{
				select.size = select.options.length > obj.size ? obj.size : (select.options.length > 1 ? select.options.length : 2) ;
				
				select.style.visibility		= 'visible' ;
				if ( div.scrollWidth > 0 )
				{
					select.style.width		= div.scrollWidth + 'px' ;
				}
				else if( div.offsetWidth > 0 )
				{
					select.style.width		= div.offsetWidth + 'px' ;
				}
			}
			else
			{
				obj.close( ) ;
			}

			if(e && e.keyCode == 13)
			{
				SelectClick( ) ;
			}
		} ;

		return obj;
	} ;

	self.initalise				= function( )
	{
		// Must set the response of this into a variable or the method will itself return true and not continue.
		var isOK		= baseInitalise( ) ;
		
		self.autoCompleteControl = self.makeAutoComplete( self.displayControl , self.valueControl , self.valueArray , self.enableAutomaticNewCreation ) ;
		if ( self.autoCompleteControl )
		{
			self.autoCompleteControl.size	= "20" ;
			self.autoCompleteControl.ongetoptions	= function( ) 
			{
				if ( self.useDisplayQueryImage )
				{
					self.imageControl.src				= self.imageSource ;
					self.imageControl.style.visibility	= 'visible' ;
					document.body.style.cursor			= 'wait' ;
					self.displayControl.style.cursor	= 'wait' ;
				}
				self.getAjaxResult( self.displayControl.value ) ;
			} ;
			isOK		= true ;
		}
		else
		{
			isOK		= false ;
		}
		
		return isOK ;
	} ;

	return true ;
} ;




//function makeAutoComplete( element , elementHid , array, sNew){
//	
////	var obj					= this;
//	var obj					= element;
//	obj.options				= array.sort()
//	obj.size 				= 5;
//	var div 				= document.createElement('SPAN')
//	div.className			= "autoCompleteFrame"
//	div.style.zIndex		= 30;
//	element.autoComplete	= "off";
//	element.setAttribute("autocomplete","off")

//	// Hack for IE else size dosn't work
//	div.innerHTML			= '<select size="2"><option></option></select>'
//	var select				= div.getElementsByTagName('SELECT')[0]
//	element.parentNode.insertBefore( div, element )
//	div.appendChild(element)

//	div.style.position		= 'relative'

//	select.className		= "autoCompleteSelect"
//	select.style.position	= 'absolute';
//	select.style.top		= 22 +'px';
//	select.style.visibility	= 'hidden'
//	select.style.zIndex		= 40;
//	select.options.length	= 0;

//	var option = document.createElement('OPTION')
//	select.appendChild( option )		
//	
//	addEvent( element,	'keyup',	function(e){obj.ongetoptions()})
//	addEvent( element,	'keydown',	ElementKeyDown)
//	addEvent( element,	'dblclick',	function(){obj.open(null,true)})
//	addEvent( select,	'click',	SelectClick)
//	addEvent( select,	'keyup',	SelectKeyUp)
//	addEvent( document,	'click',	DocClick)

//	obj.name 				= element.id;
//	obj.element 			= element;
//	obj.elementHid 			= elementHid;
//	obj.select 				= select;

//	function DocClick(e){
//		var el = e.target || e.srcElement
//		var close			= true
//		while(el.parentNode){
//			if(el == select || el == element)
//				return true
//			el				= el.parentNode
//		}
//		obj.close()
//		return true
//	}

//	function SelectKeyUp(e){
//		if(e.keyCode == 13){
//			SelectClick();
//		}
//	}

//	function ElementKeyDown(e){
//		if(e.keyCode == 40 && select.options.length > 0){
//			select.focus();
//		}
//		if(e.keyCode == 9 && select.options.length > 0){
//			obj.close()
//		}
//	}

//	function SelectClick(){
//		if (select.value	== "(*)~%"){
//			obj.close();
//			addNew(element, elementHid, element.value);
//			return false;
//		}
//		element.value		= select.options[select.selectedIndex].text;
//		if(select.selectedIndex >= 0 && select.options.length > 0){
//			elementHid.value = select.value + ";" + select.options[select.selectedIndex].text + ";" + select.options[select.selectedIndex].components;
//		}
//		obj.close();
//		/*
//		I cannot be sure why, but this next function has no realy usefulness from what i can see.
//		Plus it breaks FireFox
//		*/
//		//element.select();
//		element.focus();
//		// Tie in validator
//		if(element.validate) element.validate();
//		return true;
//	}

//	obj.ongetoptions		= function(){

//	}

//	obj.setOptions			= function( array ){
//		obj.options			= array
//	}
//	obj.getOptions			= function(){
//		return obj.options;
//	}
//	

//	obj.close = function(){
//		select.options.length = 0;
//		select.style.visibility = 'hidden'
//	}

//	obj.open = function(e, open){
//		
//		// On tab focus do not process
//		if(e && e.keyCode == 9) return false

//		var text			= element.value.toLowerCase()
//		//obj.ongetoptions();
//		
//		var matches			= obj.options

//		
//		if (element.value.length > 0 && sNew) {
//			matches[matches.length] = "(*)~%";
//			matches[matches.length] = "Add New " + itemName;
//		}
//		
//		try
//		{
//  		select.options.length = 0;
//		}
//		catch( e ){}
//		if((open || text.length > 0) && matches.length % 3 == 0){
//			for(var i=0;i<matches.length;i+=3){
//				var oValue	= matches[i]
//				var oText	= matches[i+1]
//				var oComp = matches[i+2]
//				if (oValue.length > 0 || oText.length > 0){
//					var option			= document.createElement('OPTION')
//					option.innerHTML	= oText
//					option.value		= oValue
//					option.components = oComp
//					select.appendChild( option )
//				}
//			}
//		}

//		select.selectedIndex = -1;
//		if(select.options.length > 0){
//			select.size = select.options.length > obj.size ? obj.size : 
//							(select.options.length > 1 ? select.options.length : 2);
//			
//			select.style.visibility		= 'visible'
//			select.style.width			= (div.scrollWidth <= 0 ? '354px' : div.scrollWidth +'px')
//		}else{
//			obj.close()
//		}

//		if(e && e.keyCode == 13){
//			SelectClick();
//		}
//		return true;
//	}

//	return obj;
//}