Enter the Google Map

Our guest blogger Chinedu Efoagui is a Sun Certified Java Programmer as well as a Sun Certified Business Component Developer with a Masters degree in Computer Science from the University of Hertfordshire. He is very passionate about technology and envisions a world entirely driven by it.

His interests include Object Oriented Analysis and Design, Java/.NET technology, Functional programming, Database technology and Open Source efforts.

When he is not fooling around with his computer, he likes to analyse chess games and write fiction.


https://profiles.google.com/chinedubond/

http://twitter.com/chinedubond

Requirements

Pretty Fast Internet Connection.

JQuery 1.4+

Assumed Knowledge of XML, XSLT, JavaScript

Introduction

Google Maps is an exciting technology. Since it was first lunched, it has been applied in lots of interesting ways e.g. in measuring actual sizes of buildings to resolving border conflicts! Over the years,I have had very good experience using Google Maps . I developed http://www.theveryplace.com/ – a website that uses a lot of Google Map features which give users the ability to get driving instructions and other location based stuff. Anyway, this blog entry won’t be as far reaching in showing what can be achieved using Google maps.

Before we go to the sample application proper, let me follow tradition and display a “hello world” example. We will be using JQuery- a popular JavaScript library, to simply the code. To run the hello world example, copy and paste the code below and view it on your browser. Also, you can just open the hello.html included in downloadable sample app.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>

<html>

<head>

<title>Ezenna Group of Companies Ltd</title>

<style type=”text/css”>
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#zamap { height: 400px,width:600px}
</style>

<script type=”text/javascript” src=”js/jquery.min.js”>

</script>

<script type=”text/javascript”

src=”http://maps.google.com/maps/api/js?v=3.2&sensor=false”>

</script>

<script type=”text/javascript”>

$(document).ready(function () {

showmap();

});

function showmap(){

//Lagos Nigeria

var latlng = new google.maps.LatLng(6.43616,3.41647 );

var myOptions = {

zoom: 12,

center: latlng,

mapTypeControlOptions: {

style: google.maps.MapTypeControlStyle.DROPDOWN_MENU

},

mapTypeId: google.maps.MapTypeId.ROADMAP

};

var map = new google.maps.Map(document.getElementById(“zamap”), myOptions);

}

</script>

</head>

<body><div id=”zamap” ></div></body>

</html>

Step 1.

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”>

The strict XHTML declaration instructs the browser to show the html document as is so the browser load the page faster than transitional declaration for instance because there is no extra step of validating html document.

Step 2.

<style
type=“text/css”>
html
{ height:
100%
}
body
{ height:
100%; margin:
0px; padding:
0px
}
#zamap { height: 400px,width:600px}
</style>

The CSS describes how the html document will be shown. the height, margin and also describes the height and width of the <div id=”zamap”> which acts as a placeholder for our map.

Step 3.

<script type=”text/javascript”

src=”http://maps.google.com/maps/api/js?v=3.2&sensor=false”>

</script>

This script tag loads the Google Maps Api necessary to create the map and version is 3.2 and sensor is false which means that the device does NOT use a sensor e.g. GPS to detect the user’s location.

STEP 4.

$(document).ready(function () {

showmap();

});

What this JQuery function pretty much does is execute any function or code after the entire HTML document has been fully rendered. In this case it runs the showMap function which has the instructions to create the Google Map. Note: Don’t forget to load the JQuery like so.

<script type=”text/javascript” src=”js/jquery.min.js”>

STEP 5

var latlng = new google.maps.LatLng(6.43616,3.41647 );

Inside the showMap function, the first step in creating a Map is to declare the latitude and longitude coordinates of the location, in this case, the city of Lagos Nigeria. The latlng of the location (Lagos) has already been got through a process known as Geocoding. Google Maps comes with that feature but I won’t talk about it since it is beyond the scope of this blog. If one doesn’t know what latitude and longitude are then you might want to get a geography lesson or better still google it.

Steps 6.

var myOptions = {

zoom: 12,

center: latlng,

mapTypeControlOptions: {

style: google.maps.MapTypeControlStyle.DROPDOWN_MENU

},

mapTypeId: google.maps.MapTypeId.ROADMAP

};

Step 7

var map = new google.maps.Map(document.getElementById(“zamap”), myOptions);

Takes the initialization settingstored in the myOptions variable, and id of the div which we get the reference of via the document.getElementById method and loads the MAP on the div.

<div id=”zamap” ></div>

Remember the DIV acts a placeholder for the Google Map.

The Options variable holds the Map initialization variables like the “zoom”. “Center” indicates the actual location from the latlng coordinates. “mapTypeId” here is initialized as “RoadMap”., there are other options like terrain , satellite, hybrid. “MapTypeControlOptions “shows the MapType options as a dropdown menu if one wishes to conserve space.

Behold The Map!

Figure 1 showing the Google Map

If you can see the image above then congratulations, for creating your first Google map.

Right now the Map does not look like much. It just shows Lagos. We will now proceed to adding a marker to indicate exactly where we are in Lagos.

//adding a marker

var marker = new google.maps.Marker({

position:latlng,

map: map,

title: “I am here!”

});

The piece code displays the marker on the map by setting the position to the latlng coordinates and the map to the map variable and we will create a title for the marker.

One can change the marker icon. That I will illustrate in the sample app so stay tuned.

Hover your mouse above the marker to see the title.

So see the marker below:

Figure 2 showing a marker

Now I promised a hello world example and not a “I am here” so we will take the tutorial a notch up by display an Infowindow with the Famous words.

//add an infowindow

var infocontentDiv = ‘<div id=”content”>’+

‘Hello World!’+

‘</div>’;

var infowindow = new google.maps.InfoWindow({

content: infocontentDiv

});

//event listener to open the infowindow on click

google.maps.event.addListener(marker, ‘click’, function() {

infowindow.open(map,marker);

});

The variable infocontentwindow holds the content we would like to display.

google.maps.InfoWindow creates an Infowindow and uses the infocontentwindow as its content.

Since we want the infowindow to open when the marker is clicked on, we add the event listener to the marker.

Click on the marker and VOILA! The infowindow pops up with the”Hello world” message.

Figure 3 Showing the “Hello World” Infowindow

Now I will illustrate the following Google Maps capability such as detecting user location, populating several locations on a single map using a sample project as a case study. This application will be called “Ezenna Group of Companies”. Legend has it that Ezenna as a typical Igbo man, had so many businesses scattered all over the world. Since they were so many, he forgot the whereabouts of some of them. Fortunately for him, he met an I.T consultant who advised him (at a huge cost) to get a directory of all his businesses so they will easy to find. I won’t tell you who the consultant was; I am sure by now you have a pretty good idea.

To make everything simple, the data of Ezenna’s business will be stored in xml instead of a RDBMS.

See below at a snippet of the xml

<STORE id=”1″>

<NAME>YouLike Clothes</NAME>

<DESCRIPTION>Best collection of designer clothes and accessories. Cool Perfumes, watches in stock.</DESCRIPTION>

<TYPE>Boutique</TYPE>

<LOGO>clothes.png</LOGO>

<LOCATION>

<Address>No 12 Aba Road, Port-Harcourt</Address>

<CITY>Rivers</CITY>

<COORDINATES>

<LAT>4.83573</LAT>

<LONG>7.03035</LONG>

</COORDINATES>

</LOCATION>

</STORE>

It contains attributes describing store such as name, description, location and so on. We shall employ JQuery to load and manipulate our XML data to show all the locations on the map. So enough talking, let’s see some code.

$(document).ready(function () {

// showmap();

$.ajax({

type:”GET”,

url:”stores.xml”,

datatype:”xml”,

success:showEzennaStoresOnTheMap

});

});

We use the ajax to asynchronously fetch the xml data.

To loop through the data, we use find method to get all the <STORE> tags and iterates through and initializes the Store properties leike name,description and so on.

$(xml).find(“STORE”).each(function(){


var id=$(this).attr(‘id’);

var name=$(this).find(‘NAME’).text();

var description=$(this).find(‘DESCRIPTION’).text();

var type=$(this).find(‘TYPE’).text();

var lat=$(this).find(‘LAT’).text();

var
long=$(this).find(‘LONG’).text();


We create the Map the usual way then add the

var bounds = new google.maps.LatLngBounds();

// Extending the bounds object with each LatLng

bounds.extend(new google.maps.LatLng(lat,long));

// Adjusting the map to new bounding box

map.fitBounds(bounds);


The bounds object adjusts the map so that the different markers fit inside the bounds being passed to it.

var marker = new google.maps.Marker({

position: new google.maps.LatLng(lat,long),

map: map,

title: name

});

The title of the marker is set to the name property of the <STORE> tag.

Figure 4 showing all of Ezenna’s stores

The Ezenna’s stores are shown on the map but there seems to be different the type of stores on the map.
So we change the marker code to reflect the marker image we’ve got.

var zapic=$(this).find(‘LOGO’).text();


imageloch=”images/”+zapic;

recycleh = new google.maps.MarkerImage(imageloch);

// Adding the markers

var marker = new google.maps.Marker({

position: new google.maps.LatLng(lat,long),

map: map,

icon: recycleh,

title: name

});

Figure 5 Showing different set of Marker Images

The icons can be downloaded here from this URL. http://code.google.com/p/google-maps-icons/

Meanwhile, the rest of the Store properties are set on the InfoWindow. As shown below with Zoom In and Zoom out link configured on it.

var infocontent=document.createElement(‘div’);

var title=document.createElement(‘strong’);

title.innerHTML =name;

var descriptionlink = document.createElement(‘p’);

descriptionlink.innerHTML=description;

var breakr = document.createElement(‘br’);

var plink = document.createElement(‘p’);

var websitelink = document.createElement(‘a’);

websitelink.innerHTML = ‘Website’;

websitelink.href = “http://www.theveryplace.com”;

websitelink.target=”_blank”;

var a = document.createElement(‘a’);

a.innerHTML = ‘ Zoom In’;

a.href = ‘#’;

// Adding a click event to the link that performs

// the zoom in, and cancels its default action

a.onclick = function() {

// Setting the center of the map to the same as the clicked marker

map.setCenter(marker.getPosition());

// Setting the zoom level to 15

map.setZoom(15);

// Canceling the default action

return
false;

};

var zoomout = document.createElement(‘a’);

zoomout.innerHTML = ‘ Zoom Out’;

zoomout.href = ‘#’;

// Adding a click event to the link that performs

// the zoom in, and cancels its default action

zoomout.onclick = function() {

// Setting the center of the map to the same as the clicked marker

map.setCenter(marker.getPosition());

// Setting the zoom level to 15

map.setZoom(5);

// Canceling the default action

return
false;

};

// Appending the link to the second paragraph element

plink.appendChild(websitelink);

plink.appendChild(a);

plink.appendChild(zoomout);

// Appending the two paragraphs to the content container

infocontent.appendChild(title);

infocontent.appendChild(descriptionlink);

infocontent.appendChild(breakr);

infocontent.appendChild(descriptionlink);

infocontent.appendChild(plink);

// Setting the content of the InfoWindow


infowindoww.setContent(infocontent);

This piece of code set the zoom level as the bounds are increased .

var listener = google.maps.event.addListener(map, “idle”, function() {

if (map.getZoom() > 16) map.setZoom(16);

google.maps.event.removeListener(listener);

});

Figure 6: showing the infowindows.

If we click on ZOOM IN .We get to see what is shown in the picture below.

User Location detection

Detecting a visitor’s location to one’s website is useful feature and has many applications in fraud management for example if the user’s credit card address is far from the location at which transaction is being carried out would be an indication of high risk transcation. Also one can get useful analytics to the demographics of one’s website visitors.

To detect user’s location, one can use gears, browser based geolocation or Ip based geolocation. Ip based geolocation is the least accurate.

To use gears, one needs to add the script tag to the header of the web page

<script type=“text/javascript”

src=“http://code.google.com/apis/gears/gears_init.js”>

</script>

For IP-based

One could use The Google API for

// Getting the position

if (google.loader.ClientLocation.latitude && google.loader.ClientLocation.longitude) {

// Defining the position

var latLng = new google.maps.LatLng(google.loader.ClientLocation.latitude,

google.loader.ClientLocation.longitude);

From my experience, I found out that Google’s client location though is bit more accurate than other offerings but in the case of Nigeria, it returns null on most IP addresses so I decided to switch to a different ip-based geolocation provider.

I assume they depend on your Google Key for something because it is one of the parameters needed.

You can get it here http://www.maxmind.com/app/geolitecity

<script type=“text/javascript” src=“http://ip-geo.appspot.com/geo_data.js?key=ABQIAAAAB1D5xVb4mI8xxT8KFKKwzRSErSB8v-HR33wr-yJFmv6d0Y_MuhTMyw2HB3rb_IKp1nyiWRjlYETbtA”>

</script>

Either way, IP-based geolocation is not very accurate. Actually, they are the least accurate as seen it the picture below which shows my location as Ikeja while I am on the Lagos Island.

Some smart mobile phones have GPS which provide very accurate location. Also GSM cell sites use triangulation to determine one’s position.

The Geolocation API specification is found at www.w3.org/TR/geolocation-API/.

To use the standard browser based geolocation API download the geo.js file which is the W3C standard. Please note that Internet explorer does NOT support this.

if (geo_position_js.init()){

geo_position_js.getCurrentPosition(setPosition, handleError,{enableHighAccuracy:false,options:6000});

}

To get around any of the hiccups associated with the lack of I.E support, Google Gears becomes a good alternative. Although, one of the problems of gears is that it is not ubiquitous. User geolocation with Gears is quite accurate as in shown in the picture. As at the time of writing this blog , I was at Lagos Island and voila , Gears shows me on the Island exactly.


To include Gears add this to the header of your webpage

<script type=”text/javascript”

src=”http://code.google.com/apis/gears/gears_init.js”>

</script>

Then the following option to your control flow.

if (google.gears) {

UseGears();

}

function UseGears() {

browserSupportFlag = true;

var geo = google.gears.factory.create(‘beta.geolocation’);

geo.getCurrentPosition(function(position) {

longir=position.longitude;

latituder=position.latitude;

}

If you are concerned about privacy issue concerning auto detection of your location, don’ be since you will have to accent to any of it.


Therefore as a rule of the thumb one should use Ip.based Geo-coding as a fall-back and either Gears or the W3C standard as the first options as shown in the sample code.


Next Steps

So we have learnt how to detect user location, transverse through xml data with JQuery, show multiple locations on a map. Some nice features I left out are getting driving directions to any of the Ezenna stores and proximity detection i.e. showing the user, the nearest Ezeani Store to the user’s location. You may want to look at see below for a working example of calculating distance between two coordinates [1]

For example, Murtala Mohammed Airport Coordinates are

Latitude= 6.57722, Longitude 3.32111

Great Circle Distance Formula using radians:

3963.0 * arccos[sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 – lon1)]

If you do NOT first convert the latitude and longitude values in the database to radians, you must include the degrees-to-radians conversion in the calculation. Substituting degrees for radians, the formula becomes:

Great Circle Distance Formula using decimal degrees:

3963.0 * arccos[sin(lat1/57.2958) * sin(lat2/57.2958) + cos(lat1/57.2958) * cos(lat2/57.2958) * cos(lon2/57.2958 -lon1/57.2958)]

OR

r * acos[sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 – lon1)]

Where r is the radius of the earth in whatever units you desire.
r=3437.74677 (nautical miles)
r=6378.7 (kilometers)
r=3963.0 (statute miles)

One can see all these concepts on display on this website –

http://www.theveryplace.com/

Get the source code for the example
here

References

1. Wikipedia http://en.wikipedia.org/wiki/Great-circle_distance

2. Google Maps Api http://code.google.com/apis/maps/documentation/javascript/

3. Developer Guide http://code.google.com/apis/maps/documentation/javascript/basics.html

4. http://code.google.com/apis/maps/documentation/javascript/overlays.html

5. Beginning Google Map API 3, Gabriel (Svennerberg, 2010)

6. W3C, www.w3.org/TR/geolocation-API/.

http://www.meridianworlddata.com/Distance-Calculation.asp