Ecommerce Developer
 
 

APIs & Plug-ins

Develop a Store Finder with the Google Maps API, Part 3

 

Providing store location information is an important site feature for online purveyors that also sell from brick-and-mortar stores, so taking advantage of Google's powerful Maps JavaScript API is a great way to transform what might have been a static list of addresses into an interactive map application.

This article is part three of a tutorial mini-series created to demonstrate how to use PHP, JavaScript, XML, and other web languages to create a store locator application with the Google Maps API.

shows map form

In Part 1, I created a MySQL database, did some geocoding, and prepared an SQL query to find the nearest target store—in my example application, I am using Dutch Bros. coffee locations in my home state of Idaho.

In Part 2, I "fetched" the query's response, transformed it into XML, and began working on the JavaScript that will capture the user's address.

In this section of the series, I am going to capture the user-submitted address; initialize the Google Maps API; and geocode that address so that it can be sent to my PHP script as a longitude and latitude.

Step No. 8: Testing for Input and the API

In Step 7, I created a JavaScript file and added an event listener to watch for when the user clicks the "Go Dutch" button on my form.

show detail of the button

If this button is clicked, the event listener will fire a function called nearStepOne(), which will be the first of several functions required for this locator application. The nearStepOne() function has three tasks: (1) test for input, (2) test for the API and establish a connection if need be, (3) initiate another step if the API is already connected.

function nearStepOne(){
	//test for input
	cusLoc = document.getElementById('address');
	if(!cusLoc.value){
		var mess = 'Please enter an address';
		alert(mess);
	}
	
	//test for Google Maps API
	
	//offer alternative if Google Maps is Running
}

To test for input, I create a global variable named cusLoc. As you probably know, a global variable can be shared anywhere in my JavaScript file. This is important because other functions are going to need access to this information. I also want this variable inside of the function, since I want to reset it each time the user clicks the "Go Dutch" button, allowing for multiple inputs.

The global variable contains the value of the input form, which should be the address that the user is starting from when looking for the closest Dutch Bros. location.

Next, I use a conditional statement to learn if the input actually has a value. Using the "!" negates the value of the statement so that if(!cusLoc.value) might be read "if the customer location input field does not have a value set do the following."

In this case, that following action alerts the user that some input is required. There are actually a lot of actions you could take here such as updating the value field of the input or loading a message on page. For my application, I am simply opening an alert box.

Shows alert box

Next, I want to learn if the script has already connected to the Google Maps API. This may sound odd, but this is an important step. Imagine what would happen if a user entered an address, got some results, and then entered a second address. If I did not check to learn if a connection was already established, my script would add the Google Maps API a second time and potentially create all sorts of errors.

	//test for Google Maps API
	if(!mapsRunning){
		var script = document.createElement('script');
		script.src = 'http://maps.google.com/maps/api/js?sensor=false&callback=initalize';
		document.body.appendChild(script);
	}

In this conditional statement, I am using a flag called mapsRunning. In JavaScript, flags can be a great tool for determining if some action has already happened in your script. To make this flag work, I need to add it as a global variable higher in my script and set its value to false.

// flag for my Google Maps API implementation
var mapsRunning = false;

Later, after I have initialized (added) the Google Maps API, I will reset this flag to true. Thus, if I have not yet added the Google Maps API, mapsRunning will be false, if I have connected, mapsRunning will be true.

Now before I go too much further, some readers might be asking why I didn't just connect to the Google Maps API as soon as the page loaded. I absolutely could have. But if I have other features running on the same page as my store locator or if I am really worried about performance, there is no reason to load the API until it is requested.

Back to my code, the conditional statement could be read as "if the maps API is not running, do the following."

The "following" action is to create a script element, set that element's src value to the URL for the Google Maps API, and add that script element to the HTML page, just before the closing </body> tag.

In version 3, the Google Maps API no longer requires a developer key, but it does want to know if I will be using some sort of sensor to capture geo-location data from the user. If I were developing this app to run on an Android-powered phone, for example, I might get data from the GPS, but since I am building a desktop application, I set the sensor portion of the API URL to false. A sensor declaration is required, so be sure to include it.

http://maps.google.com/maps/api/js?sensor=false&callback=initalize

I also add a callback to a function named initalize().

Finally, if the Google Maps API is already on page, I jump ahead to a function called nearStepTwo.

else{
		nearStepTwo();
	}
	//offer alternative if Google Maps is Running

Here is the function in its entirety.

// flag for my Google Maps API implementation
var mapsRunning = false;

function nearStepOne(){
	//test for input
	console.log('this far');
	cusLoc = document.getElementById('address');
	if(!cusLoc.value){
		var mess = 'Please enter an address';
		alert(mess);
	}
	
	//test for Google Maps API
	if(!mapsRunning){
		var script = document.createElement('script');
		script.src = 'http://maps.google.com/maps/api/js?sensor=false&callback=initalize';
		document.body.appendChild(script);
	}
	else{
		nearStepTwo();
	}
	//offer alternative if Google Maps is Running
	
}

Step No. 9: Capture the User Submission and Geocode It

In nearStepOne(), I referenced two other functions initialize() and nearStepTwo(). Neither of these functions exist yet, so I need to get coding.

First, I'll write initialize(), which has the relatively simple task of establishing a new Google Maps API geocoder, updating my flag, and calling another function.

The geocoder will transform a user's address into a longitude and latitude that I can use with the PHP script created in Part 1 of this series.

var geocoder, map;

function initalize(){
	geocoder = new google.maps.Geocoder();
	mapsRunning = true;
	nearStepTwo();	
}

Next, I need to code nearStepTwo(). This function captures the user input and submits it for geocoding.

function nearStepTwo(){
	geocoder.geocode({'address': cusLoc.value}, function(results, status){
		if(status == google.maps.GeocoderStatus.OK){
			var latitude = results[0].geometry.location.b;
			var longitude = results[0].geometry.location.c;
			cusStartAddress = new google.maps.LatLng(latitude, longitude);
			nearStepThree('http://localhost/Test-scripts/dutch_bros/dutch-bros-form.php?latitude=' + latitude + '&longitude=' + longitude, function(data){nearStepFour(data)});
			
		}
		else{
			alert('geocoding error');
		}
	});	
}

At first blush, this function might look a bit confusing, so I will try to take it step by step.

I started by passing the address that the user submitted to the Google API geocoder and asked the API to return both the geocoded results and the status of the request, meaning was it successful.

geocoder.geocode({'address': cusLoc.value}, function(results, status){

The conditional statement, checks to learn if in fact the request worked. If it did work, I get to the task of retrieving the latitude and longitude, if not I alert the user that there have been a geocoding error.

if(status == google.maps.GeocoderStatus.OK){
			…
			
		}
		else{
			alert('geocoding error');
		}

If, in fact, the request returned results, I capture those results in two local variables. I know from the Google API documentation that geometry.location.b returns the latitude value and geomerty.location.c returns the longitude value.

var latitude = results[0].geometry.location.b;
var longitude = results[0].geometry.location.c;

I also create a global variable, that contains both the latitude and longitude as a Google Maps object so that I can use it later to get driving directions from the customer's location to the nearest Dutch Bros. location. To help me remember what this variable represents, I named it cusStartAddress for the customer's starting address.

cusStartAddress = new google.maps.LatLng(latitude, longitude);

Next, I pass a URL and a callback function to another function, nearStepThree(), which I have yet to code. The interesting thing to note here is that the URL contains latitude and longitude information which I can pass to my PHP script.

nearStepThree('http://localhost/Test-scripts/dutch_bros/dutch-bros-form.php?latitude=' + latitude + '&longitude=' + longitude, function(data){nearStepFour(data)});

Summing Up This Installment

In this article, I have demonstrated the code required to capture user input, geocode that input, and prepare to pass that input via a URL to my PHP script.

In the next installment, I will make an Ajax request, collect the XML that request returns, and begin to parse the XML so that I can use it to show the user the list of Dutch Bros. locations sorted by distance.

Related Articles

Search Terms

0 Comments

Rss-sm