		// needs setting before any ajax request can take place
		// set with setUpFormHandler(...)
		var ajaxUrl = null;
//		var searchFormName = null;

		var registeredForms = new Array();
		var registeredFormInd = 0;
		
		var searchBoxDefaultValue = "";


		function removeAllFormListeners() {
			for ( var i = 0; i < registeredForms.length; i++) {
//				alert("Removing: " + registeredForms[i]);
				Event.stopObserving(registeredForms[i], 'submit', performAjaxSearch);			
			}
		}

		function positionAndShowPopUp(formName) {
			if (formName != 'quickSearchForm') {
			    var posOfSearchBox = $($(formName).searchForLocation).cumulativeOffset().top;
				var heightOfDisambiguationPopUp = $(formName + 'DisambiguationPopUp').getHeight();

				var yOfDisambiguationPopUp = posOfSearchBox - 200 - heightOfDisambiguationPopUp;

				$(formName + 'DisambiguationPopUp').style.top = "" + yOfDisambiguationPopUp + "px";
			}
			$(formName + 'DisambiguationPopUp').show();
		}

		// I wonder if this could be done with zone updating, could use 
		// tapestry expansions and pagelinks then, but not sure how it would work with
		// the form submission capture
		function showDisambiguationPopUp(result) {
			$(result.searchFormName + 'DisambiguationPopUpSearchedFor').innerHTML = result.searchedFor;


			var html = 'Did you mean:	<br /><br />';
			for (var i = 0; i < result.results.length; i++) {
				html += '<div class="arrow_link"><a href="javascript:submitWithDisambiguation(\'' + result.searchFormName + '\',\'' + result.results[i].urlTag + '\')">'
				+ result.results[i].name
				+ '</a></div>\n'; //  (' + result.results[i].lat + ', ' + result.results[i].long + ')<br/>\n';
			}
			html += '<br />\nNone of the above';

			$(result.searchFormName + 'DisambiguationPopUpResults').innerHTML = html;

			positionAndShowPopUp(result.searchFormName);

		}

		function showDisambiguationPopUpSimpleMsg(result, msg) {
			$(result.searchFormName + 'DisambiguationPopUpSearchedFor').innerHTML = result.searchedFor;

			$(result.searchFormName + 'DisambiguationPopUpResults').innerHTML = '<br />' + msg;

			positionAndShowPopUp(result.searchFormName);
		}

		function showDisambiguationPopUpNoText(searchFormName) {
			$(searchFormName + 'DisambiguationPopUpSearchedFor').innerHTML = '';
			$(searchFormName + 'DisambiguationPopUpResults').innerHTML = '<br />Please enter a search term or select a hotel from the dropdown';

			positionAndShowPopUp(searchFormName);
		}

		function submitWithDisambiguation(searchFormName, locationUrlTag) {

			$(searchFormName).locationIdOrPostCode.setValue(locationUrlTag);
			// then submit form to go to the search page
			submitFormWithOutJS(searchFormName);
		}

		function submitFormWithOutJS(searchFormName) {
//			alert('try without ajax');
			removeAllFormListeners();

//			alert("onRequestPossibleLocationsSuccess: " + searchFormName + ".locationIdOrPostCode" + $(searchFormName).locationIdOrPostCode.getValue());

			$(searchFormName).submit();
		}

/*
		function gotoResultsPage(location) {
//			alert('goto results page');
			if (location.id == -1) window.location = "Results/" + location.postCode;
			else window.location = "Results/" + location.id;
		}
*/

		/**
		 * call back for the ajax request to show possible locations
		 * used when a user search returns more than one result,
		 * or if the returned result is different (e.g. spelling correction)
		 * possible status codes are
		 *
		 * noSearchText
		 * nothingFound
		 * singleResult
		 * multiResult
		 * error
		 */
		function onRequestPossibleLocationsSuccess(transport) {
//			alert("ok");

			// TODO seems to come here on not connect too
//			alert(transport.responseText);

//			showProperties(transport);

			if ((transport.responseText == null) || (transport.responseText == "")) {
				// then we can't much but remove the javascript and let the user submit again
				// without it
				removeAllFormListeners();
				return;
			}
	
			var result = transport.responseText.evalJSON();
			var searchFormName = result.searchFormName;

			if (result.status == "multiResult") {				
				showDisambiguationPopUp(result);
			}
			else if (result.status == "singleResult") {
				// place disambiguated location in hidden location field
				var location = result.results[0];
/*				if (location.id == -1) $(searchFormName).locationIdOrPostCode.setValue(location.postCode);
				else $(searchFormName).locationIdOrPostCode.setValue(location.id);

				// then submit form to go to the search page
				submitFormWithOutJS(searchFormName);*/
				submitWithDisambiguation(searchFormName, location.urlTag);
			}
			else if (result.status == "noSearchText") {
				// noSearchText, should never occur as we check before send, so we'll
				// assume a problem and submit form manually
				submitFormWithOutJS(searchFormName);
			}
			else if (result.status == "nothingFound") {
				showDisambiguationPopUpSimpleMsg(result, 'Nothing Found');
			}
			else {
				// msgs are just just for debug, might need codes so we can react
				// differently - But currently we just have one error state
//				alert(result.errorMsg);

				// try a non ajax submit
				submitFormWithOutJS(searchFormName);
			}
		}

		/**
		 * some kind of error has occured witht the ajax request
		 * have a go at a non ajax submission
		 */
		function onRequestPossibleLocationsFailure(failObject) {
//			alert("fail");
//			showProperties(failObject);
//			submitFormWithOutJS(searchFormName);

			// as we can't know which form caused the error we can just unregister the listeners
			// and let the user resubmit
			removeAllFormListeners();
		}


		/**
		 * for debug
		 */
		function showProperties(o) {
			var properties = "";

			for(att in o) {
				properties += att + ": " + o[att] + "\n";
			}
			
			alert(properties);
		}

		function performAjaxSearch(event) {
			var searchForm = event.target;

			// if a hotel drop is present and something is selected
			// do a normal submit and the logic on the server will send you to the correct place
//			alert(searchForm.hotel.getValue());	
			if ((searchForm.hotel != null) && ((searchForm.hotel.getValue() != ""))) {
				// this will allow the form to submit as normal, 
				// as we don't reach the Event.stop(...) below
				return;
			}

			// as above, but if the locationIdOrPostCode has been filled in
			// so pre-disambiguated
//			alert(searchForm.locationIdOrPostCode);
//			alert(searchForm.locationIdOrPostCode.getValue());
			if ((searchForm.locationIdOrPostCode != null) && ((searchForm.locationIdOrPostCode.getValue() != ""))) {
				return;
			}

//			alert("performAjaxSearch for " + searchForm.id);
//			showProperties(searchForm);


			// Stop the form submitting.
			// if a single result is returned, we'll redirect to the results page
		    Event.stop(event);

		    var searchTxt = searchForm.searchForLocation.getValue();
//			alert("searchTxt: " + searchTxt);

			if ((searchTxt == null) || (searchTxt == "") || (searchTxt.replace(/^\s+|\s+$/g, '').toLowerCase() == "enter town, location or postcode")) {
				showDisambiguationPopUpNoText(searchForm.id);
				return;
			}

			new Ajax.Request(ajaxUrl, {
				method: 'get',
				parameters: {searchForLocation: searchTxt, searchFormName: searchForm.id, resultsLimit: '10', userAction: 'finding'},
				onSuccess : onRequestPossibleLocationsSuccess,
				onFailure : onRequestPossibleLocationsFailure
				});
		}




//		function setUpFormHandler(searchFormName) {
//			alert("searchFormName: " + searchFormName);
//			Event.observe(searchFormName, 'submit', performAjaxSearch);
//		}


		/**
		 * To call from the page to set up url and event listener on the form
		 * and sets the url to submit ajax request too
		 */
		function setUpAjaxForLocationSearchForm(aUrl, searchFormName, searchBoxDefaultVal) {
			ajaxUrl = aUrl;
			searchBoxDefaultValue = searchBoxDefaultVal;
			registeredForms[registeredFormInd++] = searchFormName;

//			alert("ajaxUrl: " + ajaxUrl + ";  searchFormName: " + searchFormName);	
			Event.observe(searchFormName, 'submit', performAjaxSearch);
			
			
			
//			Event.observe(window, 'load', setUpFormHandler);
		}






      function onHotelDropDownChange(event) {
	      $($('hotelSearchForm').searchForLocation).setValue(searchBoxDefaultValue);
      }

      function onLocationBoxChange(event) {
	      $($('hotelSearchForm').hotel).setValue("");         
      }


	  function setUpLocationHotelChangeEvents(event) {
		  
	    if (($('hotelSearchForm')!= null) && 
	        ($('hotelSearchForm').hotel != null) && 
	        ($('hotelSearchForm').scriptable != null) && 
	        ($('hotelSearchForm').scriptable.value != "false")) 
	    {
		    Event.observe($('hotelSearchForm').searchForLocation, 'change', onLocationBoxChange);
		   	Event.observe($('hotelSearchForm').hotel, 'change', onHotelDropDownChange);
		}
	  }

Event.observe(window, 'load', setUpLocationHotelChangeEvents);


