	//TODO: this class is becoming completely interlocked with Searchwidget - need to undo - UNDO DAMNIT!!

	var log = MochiKit.Logging.logDebug;

	Search = function () {

    this.map;
//    this.ui = uiExtension;

    this.HELPER_PATH = "/mapp/handleMAppRequests.php";
    this.HELPER_CLASS = "propertyLoader";


		//bind the methods to this instance
		MochiKit.Base.bindMethods(this);

		//init the options
		//******
		this.options = [];
		this.parameters = [];

		this.matchesShown = 0;
		this.selectedMatch = 0;
		this.searchConstraint = '';

    this.id=[];
		this.hiddenResults = new Array();
		this.results = new Array();
		this.extendedData = new Array();
    }


Search.prototype.init = function(mapp){

    this.map = mapp.getMap();    
    var me = this;
    GEvent.addListener(this.map, "click",
        function()
        {
          me.hideMatches();
        }
      );
    this.controller = mapp;
}


Search.prototype.turnOn = function(id, options){
		//this.searchComm = new boa.commLayerExt();
		//******

		//make sure we have an initialised set of options
		if (typeof options != 'undefined')
		{
			this.options = options;
		}

		this.initialiseRemainingOptions();

		this.searchType = this.options.defaultSearchType;
		this.citiesOnly = this.options.citiesOnly;
		this.withContent = this.options.withContent;

		//node creation
		//******
		this.domNode = $(id);

		this.resultsContainer = this.options.resultsContainer;
		this.form = $(this.options.formId);
		this.hiddenResultNode = $(this.options.hiddenResultNodeId);
		//******

		//set up the width
		if(!this.options.resultsWidth)
		{
			this.options.resultsWidth = MochiKit.Style.elementDimensions(this.domNode).w;
		}

		//init search strings
		//******
		this.searchStringList = [];
		this.searchString = '';
		this.oldSearchString = this.searchString;
		//******

		//make sure browser doesn't interfere
		setNodeAttribute(this.domNode, 'autocomplete', 'off');

		//init the connections with the keys if applicable
		// need to have both types for capturing enter keys succesfully
		this.keyUp = connect(this.domNode, 'onkeyup', this.checkKeyPressed);
		this.keyDown = connect(this.domNode, 'onkeydown', this.checkKeyPressed);

		this.enabled = true;

		//connect the clear
		if (this.options.focusListener)
		{
			connect(this.domNode, "onclick", this.options.focusListener);
		}

//    connect(this.map, "onclick", this, this.hideMatches);
    connect("mapSearchInput", "onclick", this, this.hideMatches);

		//set up the blur functionality
		connect(this.domNode, "onblur", this.lostFocus);
    this.hideMatches();
	}


  Search.prototype.updateInitialState = function()
  {

  }
	/**
	 * Toggle on or off
	 */
	Search.prototype.togglePower = function(state)
	{
		//check if any particular state has been chosen and return if that state
		// is already selected
		if (typeof state != "undefined" && state == true)
		{
			if (this.enabled)
			{
				return;
			}
		}
		else
		{
			if (!this.enabled)
			{
				return;
			}
		}

		//toggle the state
		if (this.enabled)
		{
			disconnect(this.keyUp);
			disconnect(this.keyDown);
			this.enabled = false;
		}
		else
		{
			this.keyUp = connect(this.domNode, 'onkeyup', this.checkKeyPressed);
			this.keyDown = connect(this.domNode, 'onkeydown', this.checkKeyPressed);
			this.enabled = true;
		}
	}

	/**
	 * Takes the passed in options and initialises anything not set to the
	 * defaults.
	 */
	Search.prototype.initialiseRemainingOptions = function()
	{
		//TODO: finish this!

		//set up the number of chars entered needed for a trigger
		if (typeof this.options.minCharsForSearch == "undefined")
		{
			this.options.minCharsForSearch = 3;
		}

		//set up the searchTrigger
		if (typeof this.options.searchTrigger == "undefined")
		{
			this.options.searchTrigger = "onkeyup";
		}

		//list extensions should be off
		if (typeof this.options.listExtension == "undefined")
		{
			this.options.listExtension = {allow: false};
		}

		//the max number of results should be 100
		if (typeof this.options.maxResultsShown == "undefined")
		{
			this.options.maxResultsShown = 10;
		}

		//the default search type is for locations
		if (typeof this.options.defaultSearchType == "undefined")
		{
			this.options.defaultSearchType = "searchLocations";
		}

		//the search limit notice should be on
		if (typeof this.options.showListLimitNotice == "undefined")
		{
			this.options.showListLimitNotice = true;
		}

		//extended tabs should be off
		if (typeof this.options.extendedTabs == "undefined")
		{
			this.options.extendedTabs = {load: false};
		}

		//there should be no listeners
		if (typeof this.options.listener == "undefined")
		{
			this.options.listener = {load: false};
		}

		//set the default language to en
		if (typeof this.options.searchLanguage == "undefined")
		{
			this.options.searchLanguage = "en";
		}
	}

	Search.prototype.checkKeyPressed = function(evt)
	{
		var key = evt.key().code;
		this.searchStringList = this.domNode.value.split(',');
		this.searchString = this.searchStringList[0];

		//if the search trigger is not key based, then return
		if (this.matchesShown == 0 && this.options.searchTrigger == "external" && key != 13)
		{
			return;
		}

		//if the user has hit the enter key and the search trigger is external
		// then just start the search and return
		if (this.matchesShown == 0 && this.options.searchTrigger == "external" && key == 13 && evt.type() == "keydown")
		{
			this.getResults();

			//the stopping of the propagation needs to be the last method call
			evt.stop();

			return false;
		}

		if(key == 9 || key == 13) //enter or tab
		{
			if (evt.type() == 'keydown' && this.matchesShown)
			{
				var choice = this.selectedMatch;
				this.lastSelectedMatch = this.selectedMatch;
				this.completeSelected();

				//if they have hit enter on a choice then call the listener
				var extendedData = this.getSelectedMatchExtendedData();
		
				signal(this.controller, "zoomTo_request", extendedData);	
			}

			evt.stop();

			return false;
		}

		// remove any hidden result value when input is altered
		if (this.hiddenResultNode)
		{
			this.hiddenResultNode.value = '';
		}

		if(this.matchesShown && key)
		{
			if((key == 40 || key == 39)) //arrow down or arrow right
			{
				if(evt.type() == 'keydown')
				{
					this.changeSelectedMatch(1);
				}
			}
			else if((key == 38 || key == 37)) //arrow up or arrow left
			{
				if(evt.type() == 'keydown')
				{
					this.changeSelectedMatch(-1);
				}
			}
			else if(this.searchString.length >= this.options.minCharsForSearch && evt.type() == 'keyup')
			{
				//they have typed in some letters, so do a search - should prob identify key ranges of chars
				this.startGetResults();
			}
			else if(this.searchString.length < this.options.minCharsForSearch && key == 8)
			{
				this.hideMatches();
			}

			return true;
		}
		else if(this.searchString.length >= this.options.minCharsForSearch && evt.type() == 'keyup')
		{
			this.startGetResults();
		}
		else
		{
			this.hideMatches();
		}

		return true;
	}

	Search.prototype.changeSelectedMatch = function(num)
	{
		//if a result exists with the given match, then change its class
		if ($(this.domNode.id + 'result' + this.selectedMatch))
		{
			removeElementClass(this.domNode.id+'result'+this.selectedMatch, this.options.selectedResultClass);
		}

		//if the user tries to go beyond the end of the list
		// set their position to the end of the list
		if(this.matchesShown-1 < this.selectedMatch + num)
		{
			this.selectedMatch = this.matchesShown-1;
		}
		else if(this.selectedMatch + num < 0)
		{
			//if the user tries to go before the first item
			this.selectedMatch = 0;
		}
		else
		{
			//otherwise, its a normal movement
			this.selectedMatch += num;
		}

		addElementClass(this.domNode.id+'result'+this.selectedMatch, this.options.selectedResultClass);
	}

	Search.prototype.startGetResults = function()
	{
		if(this.timed)
		{
			this.timed.cancel();
		}

		this.timed = MochiKit.Async.callLater(0.3, this.getResults);
	}

	Search.prototype.getResults = function()
	{
		//if the search trigger isnt a key stroke then we need to get the current
		// search term, as usually it is set in the key stroker listener
		if (this.options.searchTrigger != "onkeyup")
		{
			this.searchStringList = this.domNode.value.split(',');
			this.searchString = this.searchStringList[0];
		}

		//send through the search categories needed if tabs are loaded
		var searchCategories = [];

		if (this.options.extendedTabs && this.options.extendedTabs.load == true)
		{
			if (this.options.extendedTabs.tabList.properties)
			{
				searchCategories.push('properties');
			}

			if (this.options.extendedTabs.tabList.locations)
			{
				searchCategories.push('locations');
			}

			if (this.options.extendedTabs.tabList.users)
			{
				searchCategories.push('users');
			}

			if (this.options.extendedTabs.tabList.barsRest)
			{
				searchCategories.push('barsRest');
			}

			if (this.options.extendedTabs.tabList.todo)
			{
				searchCategories.push('todo');
			}
		}

		//if no tabs are active, push the locations
		if (searchCategories.length == 0)
		{
			searchCategories.push('locations');
		}

		this.parameters[0] = searchCategories;
		this.parameters[1] = this.searchString;
		this.parameters[2] = this.options.searchLanguage;
		this.parameters[3] = this.searchConstraint;
		this.parameters[4] = typeof this.poiConstraintCat != "undefined" ? this.poiConstraintCat : '';
		this.parameters[5] = this.options.citiesOnly;
		this.parameters[6] = this.options.withContent;
		if(this.options.withCityLink) this.parameters[7] = this.options.withCityLink;

		if(this.searchString != this.oldSearchString && this.searchString.length >= this.options.minCharsForSearch)
		{
			this.sendSearchRequest();
		}

		this.oldSearchString = this.searchString;
	}

	Search.prototype.showMatches = function(response)
	{
		response = eval("(" + response.responseText + ")");

		//check the response, if empty, run the fallback
		if (parseInt(response.itemCount) == 0)
		{
			if (this.options.emptyResultsFallback)
			{
				this.options.emptyResultsFallback();
				return;
			}
		}

		//get the results
		//var resultsObject = response.getValue('results');

        	for (var i in response.items.results)
        	{
                	this.results.push(response.items.results[i]);
        	}

		//alert('results length : ' + this.results.length);

		//check the results, if empty, run the fallback
		if (this.results.length == 0)
		{
			if (this.options.emptyResultsFallback)
			{
				this.options.emptyResultsFallback();
				return;
			}
		}

		//alert('test');

		//get the category counts and check to see if we have results for any
		// of the categories
		var categoryCounts = response.items.categoryCounts;

		//alert(response.items);

		if (this.results.length > 0 || categoryCounts.locations > 0)
		{
			//alert('arg');

			//if there was a results listener, kick it off
			if (this.options.resultsListener)
			{
				this.options.resultsListener();
			}

			if(!(this.results.length == 1 && this.results[0] == this.searchString))
			{
				var rows = new Array();
				this.matchesShown = Math.min(this.results.length, this.options.maxResultsShown);

				//alert('about to test matches');

				for(i = 0; i < this.matchesShown; i++)
				{
					//alert('matches');

					//if they have loaded extended data, store it here for retrieval
					// later through getExtendedData
					if (typeof this.results[i].extendedData != "undefined")
					{
						this.extendedData[i] = this.results[i].extendedData;
						this.extendedData[i].point = new  GLatLng( this.results[i].extendedData.lat,  this.results[i].extendedData.lng);
						this.extendedData[i].id = this.results[i].idEntities;
						this.extendedData[i].title = this.results[i].displayText;
						this.extendedData[i].searchresult=true;
						this.id[i]  = this.results[i].idEntities;
					}
					else
					{
						this.extendedData[i] = '';
						this.id[i]='';
					}

					//TODO: this.results[i].idEntities is undefined
					this.hiddenResults[i] = this.results[i].idEntities;
					this.results[i] = this.results[i].displayText;
					//alert(this.results[i]);

					var alt = '';
					var title = '';

					switch (this.extendedData[i].type)
					{
						case 'property':
							alt = "Hostel: " + this.results[i];
							title = this.results[i];
							break;

						case 'city':
							alt = "City: " + this.results[i];
							title = this.results[i] + " ("+this.extendedData[i].NumProperties+" B&B's)";
							break;

						case 'country':
							alt = "Country:" + this.results[i];
							title = this.results[i];
							break;   
					}
              
					if(i == this.selectedMatch)
					{
						//addElementClass(this.domNode.id+'result'+this.selectedMatch, this.options.selectedResultClass);
					
						var link = A({"title":alt, "class": "searchLink searchLinkType" + this.extendedData[i].type + " " +  this.options.selectedResultClass, 'id': this.domNode.id + "result" + i}, title);
						connect(link, 'onclick', this.onResultClick);

						var newCell = DIV({"class": "resultDiv"}, link);
						rows[i] = newCell;
					}
					else
					{
						var link = A({"title":alt, "class": "searchLink searchLinkType" + this.extendedData[i].type, 'id': this.domNode.id + "result" + i}, title);
						connect(link, 'onclick', this.onResultClick);

						var newCell = DIV({"class": "resultDiv"}, link);
						rows[i] = newCell;
					}
				}

				//show any extra rows that have been passed through
				if (this.options.listExtension.allow == true && MochiKit.DOM.$(this.options.listExtension.node))
				{
					var listExtensionNodes = [];

					for(var x = 0; x < this.options.listExtension.listData.length; x++)
					{
						var link = A({"class": "searchLink"}, this.options.listExtension.listData[x].html);

						var newCell = DIV({"class": "resultDiv"}, link);
						listExtensionNodes[x] =  newCell;

						connect(listExtensionNodes[x], "onclick", this.hideMatches);

						if (typeof this.options.listExtension.listData[x].listener != "undefined")
						{
							connect(listExtensionNodes[x], "onclick", this.options.listExtension.listData[x].listener);
						}
					}

					MochiKit.DOM.replaceChildNodes(this.options.listExtension.node, listExtensionNodes);
				}

				//show the limit notice
				if (this.options.showListLimitNotice && this.results.length > this.matchesShown)
				{
					var link = A({"class": "searchLink searchLinkTypeMore"}, 'More results found, please narrow your search.');
					var newCell = DIV({"class": "resultDivMore", 'id': this.domNode.id+'_moreResults', 'style':'font-style:italic; color:black; cursor: pointer;'}, link);
					rows[++i] = newCell;
				}

				replaceChildNodes(this.resultsContainer, rows);

				//alert("results built");

				MochiKit.Style.setStyle(this.options.mainResultsContainer, {"display": "block"});
				//shimmyShim($(this.resultsContainer));
			}
			else
			{
				this.results = new Array();
			}
		}
		else if(this.matchesShown)
		{
			this.hideMatches();
		}
		
		this.results = new Array();
		//alert('sdfsdfdffffffffffff');
	}

	/**
	 * Manages the fallback scenario where the default search has no results,
	 * but there are results in other tabs
	 */
	Search.prototype.manageTabFallback = function(categoryCounts)
	{
		//TODO: this method is completely redundant and needs to be refactored

		switch (this.searchType)
		{
			case 'searchLocations':

				if (categoryCounts.locations == 0)
				{
					var ignoreTab = 'searchLocations';
					this.findTabFallback(ignoreTab, categoryCounts);
				}

				break;

			case 'searchProperties':

				if (categoryCounts.properties == 0)
				{
					var ignoreTab = 'searchProperties';
					this.findTabFallback(ignoreTab, categoryCounts);
				}

				break;
				
			case 'searchUsers':
			
				if (categoryCounts.users == 0)
				{
					var ignoreTab = 'searchUsers';
					this.findTabFallback(ignoreTab, categoryCounts);
				}
				
				break;
				
			case 'searchPOI':
			
				if (categoryCounts.barsRest == 0 || categoryCounts.todo == 0)
				{
					var ignoreTab = 'searchPOI';
					this.findTabFallback(ignoreTab, categoryCounts);
				}
				
				break;			

			default:
				break;
		}
	}

	/**
	 * Finds a tab to fall back to if one exists
	 */
	Search.prototype.findTabFallback = function(ignoreTab, categoryCounts)
	{
		//TODO: need to change the external tab dependencies with a hook

		if (ignoreTab != 'searchUsers' && this.options.extendedTabs.tabList['users'] && categoryCounts.users > 0)
		{
			if (this.options.extendedTabs.tabList['users'].autoSelectListener)
			{
				this.options.extendedTabs.tabList['users'].autoSelectListener();
			}

			this.changeSearchType('searchUsers');
		}
		else if (ignoreTab != 'searchProperties' && this.options.extendedTabs.tabList['properties'] && categoryCounts.properties > 0)
		{
			if (this.options.extendedTabs.tabList['properties'].autoSelectListener)
			{
				this.options.extendedTabs.tabList['properties'].autoSelectListener();
			}

			this.changeSearchType('searchProperties');
		}
		else if (ignoreTab != 'searchLocations' && this.options.extendedTabs.tabList['locations'] && categoryCounts.locations > 0)
		{
			if (this.options.extendedTabs.tabList['locations'].autoSelectListener)
			{
				this.options.extendedTabs.tabList['locations'].autoSelectListener();
			}

			this.changeSearchType('searchLocations');
		}
		else if (ignoreTab != 'searchPOI' && this.options.extendedTabs.tabList['barsRest'] && categoryCounts.barsRest > 0)
		{
			if (this.options.extendedTabs.tabList['barsRest'].autoSelectListener)
			{
				this.options.extendedTabs.tabList['barsRest'].autoSelectListener();
			}

			this.changeSearchType('searchPOI', 2);
		}
		else if (ignoreTab != 'searchPOI' && this.options.extendedTabs.tabList['todo'] && categoryCounts.todo > 0)
		{
			if (this.options.extendedTabs.tabList['todo'].autoSelectListener)
			{
				this.options.extendedTabs.tabList['todo'].autoSelectListener();
			}

			this.changeSearchType('searchPOI', 5);
		}
	}

	/**
	 * Check to see if we can load the tab with the name provided
	 * @param array tabs The array of tabs that should be connected to the parent div
	 * @param array categoryCounts The list of counts which have been found for
	 * each category search
	 * @param string tabName The name of the tab to load (attempt)
	 * @param integer/undefined poiNumber If this is passed in, we need to use it
	 * as part of the connection to changeSearchType call so it knows which to change.
	 */
	Search.prototype.loadTabExtension = function(tabs, categoryCounts, tabName, poiNumber)
	{
		if (this.options.extendedTabs.tabList[tabName] && categoryCounts[tabName] > 0)
        {
        	var imageIcon = IMG({"src": this.options.extendedTabs.tabList[tabName].icon,
        							"alt": this.options.extendedTabs.tabList[tabName].alt,
        							"title": this.options.extendedTabs.tabList[tabName].title});
        	var text = SPAN({"class": "resultsTabTxt"}, categoryCounts[tabName]);

        	if (typeof this.selectedTab == "undefined")
        	{
        		this.selectedTab = tabName;
        	}

        	var tabClass = "resultsTabBox";

        	if (this.selectedTab == tabName)
        	{
        		tabClass = "resultsTabBoxOn";
        	}

        	var newTab = DIV({'class': tabClass, "id": tabName + "Tab"}, imageIcon, text);

        	poiNumber = poiNumber != "undefined" ? poiNumber : -1;
        	connect(newTab, "onclick", MochiKit.Base.partial(this.tabClicked, tabName, poiNumber));

        	tabs.push(newTab);
        }
	}

	/**
	 * Called when a tab has been clicked..obviously only used if the extended
	 * tabs have been loaded.
	 * @param string tabName The name of the tab that has been clicked
	 * @param integer poiNumber The number of the poi if set....need to remove/change
	 */
	Search.prototype.tabClicked = function(tabName, poiNumber)
	{
		//set the current tab
		this.selectedTab = tabName;

		if (typeof poiNumber != -1)
    	{
    		this.changeSearchType(this.options.extendedTabs.tabList[tabName].controllerAction, poiNumber);
    	}
    	else
    	{
    		this.changeSearchType(this.options.extendedTabs.tabList[tabName].controllerAction);
    	}

    	if (this.options.extendedTabs.tabList[tabName].listener)
    	{
    		this.options.extendedTabs.tabList[tabName].listener();
    	}
	}

	/**
	 * Change the search type for this Search widget
	 * @param integer searchType The type of search to switch to
	 */
	Search.prototype.changeSearchType = function(searchType, poi)
	{
		//check to see if this is for poi's and if so, update the poi constraint
		if (typeof poi != "undefined" && typeof poi != "object")
		{
			var oldPoi = this.poiConstraintCat;
			this.poiConstraintCat = poi;
			this.parameters[4] = poi;
		}
		else
		{
			this.poiConstraintCat = '';
		}

		//make sure the user isn't just clicking the same search tab over and over
		if (this.searchType != searchType || (typeof this.poiConstraintCat != "" && oldPoi != poi))
		{
			this.searchType = searchType;

			//we need to make this check as someone may enter 1 or 2 chars and then
			// change the search type...in this case, we don't want to initialise
			// a new search
			var searchString = new String(this.domNode.value);

			//must be at least 3 chars
			if (searchString.length >= this.options.minCharsForSearch)
			{
				this.sendSearchRequest();
			}
		}
	}

	/**
	 * This function allows us to pass through search constraints to the
	 * controller
	 * @param integer locationId The id of the destination to tie the following
	 * searches to.
	 */
	Search.prototype.updateSearchConstraint = function(locationId)
	{
		this.searchConstraint = locationId;
	}

	/**
	 * Get the hidden id that is set when a user selects something from the list
	 */
	Search.prototype.getChoiceId = function()
	{
		return this.hiddenResultNode.value;
	}

	/**
	 * Sends a new search request and cancels the last
	 */
	Search.prototype.sendSearchRequest = function()
	{
		if (this.options.searchStartedListener)
		{
			this.options.searchStartedListener();
		}

	/*	this.searchComm.setController('BooSearchController');
		this.searchComm.setAction(this.searchType);
		this.searchComm.setParameters(this.parameters);
		this.searchComm.setCallbacks(this.showMatches, this.hideMatches);
		this.searchComm.sendRequest();*/

		this.searchType = this.searchType != 'search' && this.searchType != 'searchCitiesAndCountries' ? 'search' : this.searchType;

		var params =
		{
			"parameters":
			{
				"plugin": 'regionalControls',
				"action": this.searchType,
				"searchData": this.searchString,
				"citiesOnly": (this.options.citiesOnly && this.options.citiesOnly == true) ? true : false
			}
		};

		var defer = Utility.doSimpleXHRPost('/handleMAppRequests.php', params);

		defer.addCallbacks(this.showMatches,this.hideMatches);
	}

	Search.prototype.completeSelected = function()
	{

		if(this.results[this.selectedMatch])
		{
			this.domNode.value = this.results[this.selectedMatch];
			if(this.extendedData[this.selectedMatch])
			{
				this.extendedData['current'] = this.extendedData[this.selectedMatch];
			}
		}

		if(this.hiddenResults[this.selectedMatch])
		{
			//this.hiddenResultNode.value = this.hiddenResults[this.selectedMatch];
		}

		this.selectedMatch = 0;
		this.hideMatches();
		this.postCompleteSelected();
	}
	
	Search.prototype.postCompleteSelected = function()
	{
	}

	Search.prototype.hideMatches = function()
	{
		MochiKit.Style.setStyle(this.options.mainResultsContainer, {"display": "none"});


//		MD.replaceChildNodes(MD.$(this.options.resultsContainer));


		if (this.options.extendedTabs && this.options.extendedTabs.load == true)
		{
			replaceChildNodes($(this.options.extendedTabs.container));
		}

		if(this.matchesShown)
		{
			disconnect(this.resultsMouseOver);
			disconnect(this.resultsMouseOut);

			this.matchesShown = 0;
			this.searchString = '';
			this.oldSearchString = '';
		}

	}

	Search.prototype.onResultClick = function(evt)
	{
		this.selectedMatch = parseInt(evt.target().id.replace(this.domNode.id + 'result', ''));
		this.lastSelectedMatch = this.selectedMatch;

    if (this.extendedData[this.lastSelectedMatch].type=="city"){
      signal(this.controller, "newcityidfromsearch", this.id[this.lastSelectedMatch]);
    }
		if(evt.target().tagName == 'A' && evt.target().id != this.domNode.id + '_moreResults')
		{
			this.completeSelected();


	//		MochiKit.Signal.signal(this.controller, "search", this.getSelectedMatchExtendedData());

        var extendedData = this.getSelectedMatchExtendedData();

        if (this.extendedData[this.lastSelectedMatch].type=="property"){
          signal(this.controller, "propertybubble_request",  extendedData);
        }
        else {
          signal(this.controller, "zoomTo_request", extendedData);
        }
		}
//		alert('bbb')
	}

	/**
	 * When the user clicks away from the component, we need to take action.
	 */
	Search.prototype.lostFocus = function()
	{
		//TODO: refactor focus loss in here
    //this.hideMatches();

	}

	/**
	 * This method returns the extended data, if any, provided via the callback
	 * for a particular search. This method is a means of handling extra information
	 * which the Search does not need to be aware of.
	 */
	Search.prototype.getSelectedMatchExtendedData = function()
	{
		if (typeof this.extendedData[this.lastSelectedMatch] != "undefined")
		{
			return this.extendedData[this.lastSelectedMatch];
		}

		return false;
	}
