//=========================================================================================================
// File:		locations.js
// Purpose:	Java script specific to the DRW web site locations page
//				Controls display of the Google map and markers
//				Handles post code translation and map zooming
//	Author:	Bob HAwkes
// Date:		9th September 2009
// Version: 1.0
//=========================================================================================================

// Global variables
var map2;							// Handle for the map
var markers = new Array();		// Map markers as an array
var infoText = new Array();	// Contents of marker infor boxes. Corressponds to markers array.
var infoMarker;					// Marker that is currently showing info, or false
var xmlhttp;						// AJAX xmlhttp object for the post code server lookup.


//=========================================================================================================
// Function:	checkKeyPress	
// Purpose:		Called when a key is pressed in the post code input box.
//					Runs the post code search when the return key is pressed
// Parameters: e = key press event
// Returns:		Nothing
//=========================================================================================================
function checkKeyPress( e )
{
	if(window.event) // IE
	{
		var keynum = e.keyCode
	}
	else if(e.which) // Netscape/Firefox/Opera
	{
		var keynum = e.which
	}
	
	if( keynum == 13 )
	{
		btnPostCode_onclick();
		return false;
	}		
	return true; 
}


//=========================================================================================================
// Function:	mapOnClick
// Pupose:		Zoom map when clicked. 
//					(If info box opens map centere will shift to accomodate box.)
// Parameters: latlng = Google GLatlng object giving click location.
//								If on marker latlng gives the location the marker points to, 
//								otherwise it gices click location.
// returns:		Nothing
//=========================================================================================================
function mapOnClick( latlng )
{
	hideMessages();
	map2.setCenter( latlng, 8 );
} 


//=========================================================================================================
// Function:	Create marker	
// Pupose:		Adds a marker to the map.
//					Modfied version of Google code.
// Parameters: point 	= GLatlng position at which to put the marker
// 				infoHTML = HTML text to be shown in the info box
// Returns:		GMarker object 
//=========================================================================================================
function createMarker( lat, lng, infoHTML )
{
	var point = new GLatLng( lat, lng );
	var marker = new GMarker( point );
	idx = markers.push( marker ) - 1;
	infoText.push( infoHTML );
	GEvent.addListener( marker, "click", function() 
	{ 
		marker.openInfoWindowHtml( infoHTML );
		var loc = marker.getLatLng();
		map2.setCenter( loc, 8 );
		infoMarker = marker;
	} );
	map2.addOverlay( marker );
	return marker; 
}

//=========================================================================================================
// Function:	hideMessages
// Purpose:		Hides all error messages icluding the "no workshops in area" message.		
// Parameters: None 
// Returns:		Nothing
//=========================================================================================================
function hideMessages()
{
	document.getElementById( 'pErrorText' ).style.visibility = "hidden";
	document.getElementById( 'noworkshop' ).style.visibility = "hidden";
	
	// Return value here as this function is called from a link	
	return false;
}

//=========================================================================================================
// Function:	showInfoBox
// Purpose:		Displays the markers information box. The map will re-centre to fit the box in.		
// Parameters: markeridx = Index of the marker in the markers array 
// Returns:		Nothing
//=========================================================================================================
function showInfoBox( markeridx )
{
	if( idx < markers.length )
	{
		markers[markeridx].openInfoWindowHtml( infoText[markeridx] );
		infoMarker = markers[markeridx]; 
		document.frmPostCode.txtPostCode.focus();
		document.frmPostCode.txtPostCode.select();
	}
}

//=========================================================================================================
// Function:	zoomToLocation
// Pupose:		Moves the map to be centred at a new location
//					Zooms the map.
// Parameters: lat 	= latitude (float)
//					lng 	= longditude (float)
//					zoom	= Google zoom level (integer)
// Returns:		Nothing
//=========================================================================================================
function zoomToLocation( lat, lng, zoom )
{
	map2.setCenter(new GLatLng( lat, lng), zoom );
}	

//=========================================================================================================
// Function:	btnPostCode_onclick	
// Purpose:		Event handler for the post code search button.		
// Parameters: None
// Returns:		Nothing
//=========================================================================================================
function btnPostCode_onclick()
{
	var pcode = document.frmPostCode.txtPostCode.value;
	
	hideMessages();
	
	// Strip excessspace and convert to upper case
	pcode = cleanUpPostCode( pcode );

	// If box is empty do nothing
	if( pcode != "" )
	{
		// Verify that the text is a post code
		if( !validatePostCode( pcode ) )
		{
			// Display error message
			displayMessage( "This is not the correct format for a post code." );
			document.frmPostCode.txtPostCode.focus();
			document.frmPostCode.txtPostCode.select();
		}
		else
		{

			// Look up the equivalent LAt and Long and do whatever we want with them.
			postCodeAction( pcode );
	
		}
	}
}

//=========================================================================================================
// Function:	normalise
// Purpose:		Strips excess white space from a text string.
//					Removes leading and traing space. 
//					Reduces spaces within the string to a single space.		
// Parameters: None. Extends the String class.
// Returns:		The modified string
//=========================================================================================================
String.prototype.normalise = function() 
{
	return this.replace(/^\s+|\s+$/g, '').replace(/\s{2,}/g, ' ');
};

//=========================================================================================================
// Function:	cleanUpPostCode	
// Pupose:		Tidies up the post code string entered by the user.
//					Removes excess white space. Converts to upper case. Reduces text to "outer" code only.		
// Parameters: str = The post code string to be tidied.
// returns:		The modified string
//=========================================================================================================
function cleanUpPostCode( str )
{
	// Strip excess white space. Make all upper case
	str = str.normalise();
	str = str.toUpperCase();

	// Strip off anything after first space
	var idx = str.indexOf( ' ' );
	if( idx != -1 )
	{
		str = str.substring( 0, idx );
	}
	
	return str;
}

//=========================================================================================================
// Function:	validatePostCode
// Pupose:		Verified that a string is in the correct format for a post code
// Parameters: str = the string to verify
// returns:		TRUE if the string is correctly formatted, else FALSE
//=========================================================================================================
function validatePostCode( str )
{
	var format = RegExp( '^([a-zA-Z]){1}([0-9][0-9]|[0-9]|[a-zA-Z][0-9][a-zA-Z]|[a-zA-Z][0-9][0-9]|[a-zA-Z][0-9]){1}$' );
	var result = format.test( str );
	return result;
}

//=========================================================================================================
// Function:	postCodeAction
// Pupose:		Send a request to the server to get the latitude and longditude that
//					corresspond to a post code. When response is received the required action is executed.
// Parameters: pcode = string containg the outer post code, e.g. "OX12"
// Returns:		Nothing
//=========================================================================================================
function postCodeAction( str )
{
	xmlhttp = GetXmlHttpObject();
	if( xmlhttp == null )
	{
	  alert ("Error! - Browser does not support AJAX");
	  return;
	}

	// Build query URL			
	var url="get-latlong.php" + "?postcode=" + str;
	
	// Send request
	xmlhttp.onreadystatechange = stateChanged;
	xmlhttp.open( "GET", url , true );
	xmlhttp.send( null );
}

//=========================================================================================================
// Function:	stateChanged
// Purpose:		AJAX response handler.
//					Carries out whatever is required when the server responds to a post code lookup.
// Parameters: None
// Returns:		Nothing
//=========================================================================================================
function stateChanged()
{
	if( xmlhttp.readyState == 4 )
	{
		var xmlDoc = xmlhttp.responseXML;
		//alert( "Response:" + xmlhttp.responseText );
  		var lat = xmlDoc.getElementsByTagName("latitude")[0].childNodes[0].nodeValue;
  		var lng = xmlDoc.getElementsByTagName("longditude")[0].childNodes[0].nodeValue;
  		var nearlat = xmlDoc.getElementsByTagName("nearlat")[0].childNodes[0].nodeValue;
  		var nearlng = xmlDoc.getElementsByTagName("nearlng")[0].childNodes[0].nodeValue;
		if( lat == 0 )
		{
			// Post code was not found in the database
			displayMessage( "Post code not found." );
		}			  		
  		else if( nearlat == 0 || nearlng == 0 )
  		{
			zoomToLocation( lat, lng, 8 )
			infoMarker.closeInfoWindow();
			document.getElementById( 'noworkshop' ).style.visibility = "visible";
  		}
  		else
  		{
	  		zoomToLocation( nearlat, nearlng, 8 );
	  		var markidx = findMarkerAtLatLng( nearlat, nearlng );
	  		if( markidx != -1 )
	  		{
	  			showInfoBox( markidx );
	  		}
		}
		
		document.frmPostCode.txtPostCode.focus();
		document.frmPostCode.txtPostCode.select();
  	}
}

//=========================================================================================================
// Function:	displayMessage	
// Purpose:		Displays a message in red under the post code box
// Parameters: msg = text string to display
// Returns:		Nothing
//=========================================================================================================
function displayMessage( msg )
{
			var errmsg = document.getElementById( 'pErrorText' )
			errmsg.style.color = "red";
			errmsg.style.visibility = "visible";
			errmsg.innerHTML = msg;

			// Messages all result from post code error so 
			// send user back to post code box
			document.frmPostCode.txtPostCode.focus();
			document.frmPostCode.txtPostCode.select();
}

//=========================================================================================================
// Function:	GetXmlHttpObject
// Pupose:		AJAX setup to handle incoonsistencied between older browers
// Parameters: None
// Returns:		Nothing
//=========================================================================================================
function GetXmlHttpObject()
{
	if (window.XMLHttpRequest)
	  {
	  // code for IE7+, Firefox, Chrome, Opera, Safari
	  return new XMLHttpRequest();
	  }
	if (window.ActiveXObject)
	  {
	  // code for IE6, IE5
	  return new ActiveXObject("Microsoft.XMLHTTP");
	  }
	
	return null;
}

//=========================================================================================================
// Function:	findMarkerAtLatLng	
// Pupose:		Find the marker at a specified geographic location in the markers array. 
// Parameters: lat = latitude (float)
//					lng = Longditude (float)
// Returns:		Index of the marker in the array or -1.
//=========================================================================================================
function findMarkerAtLatLng( lat, lng )
{
	// Search marker array
	for (var i = 0; i < markers.length; i++) 
	{
		var latlng = markers[i].getLatLng();
		var mlat = latlng.lat();
		var mlng = latlng.lng();
		if( (lat == mlat) && (lng == mlng) )
		{
			return i;
		}
	}
	
	return -1;
}

