|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml"> |
|
<head> |
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
|
<title>Google Maps • Check Address</title> |
|
|
|
<link rel="stylesheet" href="checkaddress.css" type="text/css" |
|
media="screen, projection" title="Main Stylesheet" charset="utf-8" /> |
|
|
|
<script src="prototype.js" type="text/javascript" language="javascript" |
|
charset="utf-8"></script> |
|
|
|
<script src="http://maps.google.com/maps?file=api&v=2&key=<INSERT API KEY HERE>" |
|
type="text/javascript"></script> |
|
|
|
<script type="text/javascript" language="javascript" charset="utf-8"> |
|
// <![CDATA[ |
|
// Google maps variables |
|
objMap = undefined; |
|
objGeo = new GClientGeocoder(); |
|
|
|
// Place information |
|
objCurrentLocation = undefined; |
|
intCurrentPlacemark = undefined; |
|
|
|
// Special variables |
|
document.debug = false; // Whether to be verbose. |
|
document.googleExtended = false; // True when google maps is big. |
|
|
|
// This is where everything happens. It initializes google maps, |
|
// and then sets an observer. The observer performs the bulk of the |
|
// work, geocoding the address and passing it off to the proper |
|
// functions. |
|
Event.observe(window, 'load', function() |
|
{ |
|
// When this button is clicked perform the necessary actions to |
|
// get google maps running with the given address. |
|
Event.observe('addressSubmit', 'click', function(event) |
|
{ |
|
// Stop further execution |
|
Event.stop(event); |
|
|
|
new Effect.BlindDown('googleMapSlider', { |
|
afterFinish: function(){ |
|
// Load google maps. |
|
googleInit(); |
|
|
|
// Debug |
|
if (document.debug) alert('Address Submitted'); |
|
|
|
// Initialize with the given string |
|
googleStringInit($('addressString').value); |
|
}}); |
|
}); |
|
|
|
// Toggle the size of the map. This shows and hides the |
|
// similar addresses box as well. |
|
Event.observe('toggleMapSize', 'click', function(event){ |
|
// Stop the event |
|
Event.stop(event); |
|
|
|
// Toggle the effects. Note that scaleContent is important |
|
// here. Without it, everything inside would have their |
|
// sizes changed as well. |
|
if (document.googleExtended) { |
|
// Expand the google maps box |
|
new Effect.Scale('googleMapContainer', 70, |
|
{scaleMode: {originalHeight: 600, |
|
originalWidth: 600}, |
|
scaleContent: false |
|
}); |
|
} else { |
|
// Contract the box |
|
new Effect.Scale('googleMapContainer', 150, |
|
{scaleMode: {originalHeight: 400, |
|
originalWidth: 400}, |
|
scaleContent: false |
|
}); |
|
} |
|
|
|
// Slide the panel out or in |
|
// Scale content here is important. |
|
new Effect.toggle('googleMapAddresses', |
|
'blind', |
|
{scaleX: true, |
|
scaleY: true, |
|
scaleContent: false, |
|
afterFinish: function() |
|
{ |
|
// After the effect finishes, we need to contract the |
|
// google maps box. |
|
document.googleExtended = (document.googleExtended) |
|
? false |
|
: true; |
|
|
|
// Initialize google maps again |
|
googleInit(); |
|
|
|
// Redo the placemark |
|
if(typeof(intCurrentPlacemark) != 'undefined') |
|
googlePromptPlacemark(intCurrentPlacemark); |
|
}}); |
|
}); |
|
}); |
|
|
|
/** |
|
* Turn a string to a geo object, setup google maps and |
|
* turn the placemarks into listened urls. |
|
* |
|
* @param string strAddress The address to use. |
|
*/ |
|
function googleStringInit(strAddress) |
|
{ |
|
// Call the google maps function passing in our address |
|
addressToJson(strAddress, function(objData) |
|
{ |
|
// Debug |
|
if (document.debug) alert('Address recieved.'); |
|
|
|
// Make the data available to the other functions even |
|
// if the status is not 200. |
|
objCurrentLocation = objData; |
|
intCurrentPlacemark = 0; |
|
|
|
// Check the status code |
|
if (!objData || objData.Status.code != 200) { |
|
// Debug |
|
if (document.debug) alert('Status: ' + objData.Status.code); |
|
|
|
// Tell them whats up and prevent further execution |
|
if (!objData.Placemark || objData.Placemark.length <= 0) { |
|
// Explode the string by spaces |
|
var arrAddress = strAddress.split(' '); |
|
|
|
// Pop an element off |
|
arrAddress.pop(); |
|
|
|
// Check the length to make sure we have a minimum |
|
if (arrAddress.length > 2) { |
|
// Join it back together and run this again |
|
return googleStringInit(arrAddress.join(' ')); |
|
} else { |
|
alert('The address you have given is not valid.'); |
|
} |
|
} else { |
|
var strAlert = 'The address you have entered was not valid, however' |
|
+ ' suggested addresses have been found.'; |
|
|
|
alert(strAlert); |
|
} |
|
} |
|
|
|
// Debug |
|
if (document.debug) alert(objData.Placemark.length + ' Address(es) found.'); |
|
|
|
// Center the area |
|
googleCenter(objData, intCurrentPlacemark); |
|
|
|
// Generate the marker and have another callback to handle |
|
// that information. |
|
generatePromptMarker(objData, intCurrentPlacemark, promptCallback); |
|
|
|
// Generate the address elements |
|
generateAddressElements(objData); |
|
|
|
// Setup the listeners for the elements generated above |
|
addressListeners(); |
|
}); |
|
} |
|
|
|
/** |
|
* Get the globally set data, and display a marker prompt |
|
* with the given placemark. This changes the global placemark |
|
* on call. |
|
* |
|
* @param int intPlacemark The placemark to use. |
|
*/ |
|
function googlePromptPlacemark(intPlacemark) |
|
{ |
|
// Shorten the global data |
|
var objData = objCurrentLocation; |
|
|
|
// Update the global placemark |
|
intCurrentPlacemark = intPlacemark; |
|
|
|
// Check the status code. Silently return, they have already |
|
// been notified that there is no address. |
|
if ((!objData || objData.Status.code != 200) && objData.Placemark.length <= 0) |
|
return; |
|
|
|
// Debug |
|
if (document.debug) alert('Loading placemark ' + intPlacemark); |
|
|
|
// Center the area |
|
googleCenter(objData, intPlacemark); |
|
|
|
// Generate the marker |
|
generatePromptMarker(objData, intPlacemark, promptCallback); |
|
} |
|
|
|
/** |
|
* Center a point on the map. Essentially just calls set center. |
|
* with the given placemarks coordinates. |
|
* |
|
* @param GClientGeocoder objData The geocoder object. |
|
* @param int intPlacemark The placemark to center. |
|
*/ |
|
function googleCenter(objData, intPlacemark) |
|
{ |
|
// Shorten the placemark |
|
objPlace = objData.Placemark[intPlacemark].Point.coordinates; |
|
|
|
// Make the point |
|
objPoint = new GLatLng(objPlace[1], objPlace[0]); |
|
|
|
// Set the center of the map |
|
objMap.setCenter(objPoint, 17); |
|
} |
|
|
|
/** |
|
* Initialize Google maps. |
|
* |
|
* @param HtmlElement objElement An optional element to use for the map. |
|
*/ |
|
function googleInit(objElement) |
|
{ |
|
// Default element |
|
if (typeof(objElement) == 'undefined') |
|
objElement = $('googleMapContainer'); |
|
|
|
// Check if google maps has already been loaded and if it has |
|
// been, call the unloader. |
|
if (objMap instanceof GMap2) GUnload(); |
|
|
|
// Initialize google maps |
|
objMap = new GMap2(objElement); |
|
|
|
// Disable dragging |
|
objMap.disableDragging(); |
|
} |
|
|
|
/** |
|
* Add addresses to an HTML unordered list. Call addressListeners |
|
* so assign listeners to these elements. This is for control. |
|
* |
|
* @param GClientGeocoder objData The data retrieved from Google. |
|
*/ |
|
function generateAddressElements(objData, objElement) |
|
{ |
|
// Debug |
|
if (document.debug) alert('Generating address links.'); |
|
|
|
// Default element |
|
if(typeof(objElement) == 'undefined') |
|
objElement = $('googleMapAddressList'); |
|
|
|
// Remove everything from the given element |
|
objElement.innerHTML = ''; |
|
|
|
// Shorten the placemark |
|
objPlace = objData.Placemark; |
|
|
|
// Loop through the data |
|
for (var i=0;i<objPlace.length;i++) { |
|
// Make an element |
|
var strHtml = '<li><a href="#" rel="' + i + '">' + objPlace[i].address + '</a></li>'; |
|
|
|
// Insert the element at the bottom of the list |
|
new Insertion.Bottom(objElement, strHtml); |
|
} |
|
} |
|
|
|
/** |
|
* Add listeners to each of the addresses in the proper section. |
|
* |
|
* @param string strElements The string of elements for the $$ function. |
|
*/ |
|
function addressListeners(strElements) |
|
{ |
|
// Default elements |
|
if(typeof(strElements) == 'undefined') |
|
strElements = '#googleMapAddressList li a'; |
|
|
|
// Get the array of each element |
|
objElements = $$(strElements); |
|
|
|
// Debug |
|
if (document.debug) alert(objElements.length + ' Element(s) found for listen.'); |
|
|
|
// Loop through them |
|
for (var i=0;i<objElements.length;i++) { |
|
// Check to make sure it hasn't already got a listener |
|
if(!objElements[i].hasClassName('listening')) { |
|
// Add the class name |
|
objElements[i].addClassName('listening'); |
|
|
|
// Add the listener |
|
Event.observe(objElements[i], 'click', function(event) |
|
{ |
|
// Stop the event |
|
Event.stop(event); |
|
|
|
// Get the calling element |
|
var objElement = $(Event.element(event)); |
|
|
|
// Call the google center function with the placemark |
|
// as the rel. |
|
googlePromptPlacemark(objElement.rel); |
|
}); |
|
} |
|
} |
|
} |
|
|
|
/** |
|
* Turn an address into a JSON object and hand it to the callback |
|
* function. This pretty much calls getLocations and calls it good |
|
* at the moment. |
|
* |
|
* @param string strValue The address string to handle. |
|
* @param object objCallback The function to callback to, passes one param. |
|
* @return void |
|
*/ |
|
function addressToJson(strValue, objCallback) |
|
{ |
|
objGeo.getLocations(strValue, objCallback); |
|
} |
|
|
|
/** |
|
* Generate a marker that prompts the user for the correct address. |
|
* |
|
* @param GClientGeocoder objData The Geocoder JSON object. |
|
* @oaran int intPlace The placemark to show. |
|
* @param object objCallback The callback with a boolean param of yes/no. |
|
* @return void |
|
*/ |
|
function generatePromptMarker(objData, intPlace, objCallback) |
|
{ |
|
// Setup the placemark |
|
objPlace = objData.Placemark[intPlace]; |
|
|
|
// Debug |
|
if (document.debug) alert('Forming marker prompt.'); |
|
|
|
// Set to true when the callback is to be run |
|
boolCallback = false; |
|
|
|
// Form the HTML to go inside the Google Bubble. |
|
var strHtml = '<br /><b>' + objPlace.address + '</b><br /><br />' |
|
+ 'Is this the correct address?<br />' |
|
+ '<a href="#" id="markerPromptYes">Yes</a> / ' |
|
+ '<a href="#" id="markerPromptNo">No</a>'; |
|
|
|
// Make the point the marker will touch |
|
var objPoint = new GLatLng(objPlace.Point.coordinates[1], |
|
objPlace.Point.coordinates[0]); |
|
|
|
// Make the point at that marker |
|
var objMarker = new GMarker(objPoint); |
|
|
|
// Add the marker to the map |
|
objMap.addOverlay(objMarker); |
|
|
|
// Add the HTML to the marker |
|
objMarker.openInfoWindowHtml(strHtml, { |
|
'noCloseOnClick': true |
|
}); |
|
|
|
// If the info window's close button is pressed |
|
GEvent.addListener(objMarker, 'infowindowclose', function(){ |
|
// Debug |
|
if (document.debug) alert('User closed the info window.'); |
|
|
|
// Close the marker |
|
objMap.removeOverlay(objMarker); |
|
|
|
// Call the callback |
|
if (boolCallback) objCallback(false); |
|
}); |
|
|
|
// Observe the yes/no buttons |
|
Event.observe('markerPromptYes', 'click', function(event){ |
|
// Stop the event |
|
Event.stop(event); |
|
|
|
// Debug |
|
if (document.debug) alert('User selected the "yes" link.'); |
|
|
|
// The callback is to run |
|
boolCallback = true; |
|
|
|
// Close the info window |
|
objMarker.closeInfoWindow(); |
|
|
|
// Call the callback |
|
objCallback(true); |
|
}); |
|
|
|
Event.observe('markerPromptNo', 'click', function(event){ |
|
// Stop the event |
|
Event.stop(event); |
|
|
|
// Debug |
|
if (document.debug) alert('User selected the "no" link.'); |
|
|
|
// The callback is to run |
|
boolCallback = true; |
|
|
|
// Close the info window |
|
objMarker.closeInfoWindow(); |
|
|
|
// Call the callback |
|
objCallback(false); |
|
}); |
|
} |
|
|
|
/** |
|
* A callback function for {@link generatePromptMarker}. |
|
* |
|
* @param bool boolOutcome If the users address was correct or not. |
|
* @return void |
|
*/ |
|
function promptCallback(boolOutcome) |
|
{ |
|
new Effect.BlindUp('googleMapSlider', { |
|
afterFinish: function(){ |
|
// If the user selected "yes" |
|
if (boolOutcome) { |
|
// Debug |
|
var strDebug = '"' + objCurrentLocation.Placemark[intCurrentPlacemark].address |
|
+ '" was chosen as the correct address.'; |
|
|
|
if (document.debug) alert(strDebug); |
|
|
|
alert('You have sucessfully validated your address!'); |
|
} else { |
|
// This is called when the user moves to another placemark |
|
// as well, so alerting without additional checks is not |
|
// advised. |
|
} |
|
}}); |
|
} |
|
|
|
/** |
|
* If the user chooses to continue anyways, additional things need |
|
* to happen. |
|
* |
|
* @param string strAddress The address to parse. |
|
* @return void |
|
*/ |
|
function continueAnyways() |
|
{ |
|
// Debug |
|
if (document.debug) alert('User has chosen to continue anyways.'); |
|
} |
|
|
|
// Things to happen on page unload. Google suggests that GUnload be |
|
// called here to prevent memory leaks. |
|
Event.observe(window, 'unload', function() |
|
{ |
|
// Unload Google Maps |
|
GUnload(); |
|
}); |
|
// ]]> |
|
</script> |
|
</head> |
|
<body> |
|
<h1>Address Validation</h1> |
|
|
|
<div id="fakeForm" class="padded"> |
|
<label for="addressString">Address</label> |
|
<input type="text" name="addressString" id="addressString" style="width:300px;" /> |
|
<input type="submit" name="addressSubmit" id="addressSubmit" value="Validate" /> |
|
</div> |
|
|
|
<div id="googleMapSlider"> |
|
<div id="toggleMapSize">Toggle Map Size</div> |
|
|
|
<div id="googleMapAddresses"> |
|
<h1>Similar Addresses</h1> |
|
<hr noshade="noshade" width="100%" /> |
|
<ul id="googleMapAddressList"></ul> |
|
</div> |
|
|
|
<div id="googleMapContainer"></div> |
|
|
|
<div id="googleMapFooter"></div> |
|
</div> |
|
|
|
<script type="text/javascript" language="javascript" charset="utf-8"> |
|
// <![CDATA[ |
|
$('googleMapSlider').style.display = 'none'; |
|
// ]]> |
|
</script> |
|
</body> |
|
</html> |