Web International Awards

payday loan

11

AUG 2010 17

Build a POI map using jQuery & Google Maps v3

UPDATE 09.09.10: This tutorial doesn't describe how to show in the same time multiple POIs on the map. If you wish a tutorial on how to display multiple POI on the map in the same time, read the revised version of the tutorial.

This is the incipient work from a bigger project that I worked on which uses Google Maps. I decided to share it with you as it can be used in a variety of ways and places. You can use it to locate around a map your company's offices, stores, museums or any other interest points you need to present to your website's visitors.

The tutorial is fairly simple as it doesn't include advanced programming or CSS rules. Having that said, here's a screenshot of the final product.

Tutorial preview

As you can see the application, if I can call it that way, has a sidebar that contains a list of POIs (Point of Interest), a diagnosis header that displays information about what's going on and a map. Let's code the HTML structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<div id="home-wrapper">
	<div id="logo">
		<a href="http://www.webraptor.eu" target="_self"><img src="logo.jpg" width="245" height="40" alt="WebRaptor" /></a>
	</div>
	<div id="home-messages">
		Trying to determine your location...Please allow browser to share location if prompted
	</div>
	<span class="clear">&nbsp;</span>
	<div id="home-sidebar">
		<h1>Our offices locations</h1>
		<ul>
			<li><a href="#" rel="40.453577,-3.68763, 
			<strong>Venue: </strong>Estadio Santiago Bernabeu<br />
			<strong>Address: </strong>Avenida de Concha Espina; No 1; 28036; Madrid<br />
			<strong>Phone: </strong>+34 (91) 398 4300<br />
			<strong>Fax: </strong>+34 (91) 344 0695<br />
			<strong>Email: </strong><a href='mailto:realmadrid@club.realmadrid.com'>realmadrid@club.realmadrid.com</a><br />
			" target="_self">Estadio Santiago Bernabeu</a></li>
			<li><a href="#" rel="41.934115,12.45575, 
			<strong>Venue: </strong>Stadio Olimpico<br />
			<strong>Address: </strong><br />
			<strong>Phone: </strong><br />
			<strong>Fax: </strong><br />
			<strong>Email: </strong><a href='mailto:'></a><br />
			" target="_self">Stadio Olimpico - Rome</a></li>
		</ul>
	</div>
 
	<div id="map-wrapper">
		<div id="map">
 
		</div>	
	</div>
</div>

The role of the home-wrapper div is to hold the contents of the page centered in the browser window. The home-messages div is the one that holds the diagnosis messages in place, the home-sidebar div holds the POIs list while map-wrapper and map serve as a map placeholder.

As you can see, the li items inside the unordered list located in the sidebar contain all information that's provided for each point of interest. No external files or database queries are used. The information is contained within a rel attribute of the anchor tag that's inserted in each li item.

The above HTML code is to be placed inside the body of the page, while the following into the header, as it contains links to CSS files and javascript pointers.

1
2
3
4
5
6
7
<link rel="stylesheet" href="css.css" type="text/css" media="screen" title="no title" charset="utf-8" />
<script type="text/javascript" src="http://www.google.com/jsapi?key={APIKEY}"></script>
<script type="text/javascript">
	google.load("jquery", "1.4.2");	  
</script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="js/OfficeLocation.js" type="text/javascript" charset="utf-8"></script>

The CSS file isn't complicated at all.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*		{ margin:0; padding:0; border:0; outline:0; font-weight:inherit; font-size:inherit; }
body		{ font-family:Geneva, “Lucida Sans”, “Lucida Grande”, “Lucida Sans Unicode”, Verdana, sans-serif; font-size:62.5%; }
.clear 	{ display:block; clear:both; }
 
#logo	{ display:block; width:245px; height:40px; line-height:40px; float:left; text-align:center; }
#home-wrapper	{ display:block; width:930px; margin:0px auto; padding:25px 10px; font-size:12px; }
#home-messages	{ display:block; width:645px; height:40px; line-height:40px; float:right; padding:0 10px; margin:0 0 25px 10px; background-color:#FFFFCC; border:1px solid #EEEEBB; }
#home-sidebar		{ display:block; width:243px; height:400px; float:left; padding:0 0 20px 0; margin:0 10px 25px 0; background-color:#FFFFCC; border:1px solid #EEEEBB; }
#map-wrapper		{ display:block; width:645px; height:400px; float:right; padding:10px; background-color:#FFFFCC; border:1px solid #EEEEBB; }
#map			{ display:block; width:645px; height:400px; padding:0px; }	
#infowin-overlay	{ display:block; width:400px; height:80px; }
#infowin-overlay strong	{ display:block; float:left; clear:left; font-weight:bold; width:100px; }
 
h1	{ font-size:15px; padding:10px 0; text-align:center; background:#EEEEBB; color:#339933; }
ul 	{ list-style:none; }
li a	{ display:block; padding:5px 10px; color:#999; }

What's new in the CSS file is the infowin-overlay identifier used, which is nowhere to be found in our HTML file. That's due to the fact that it is the identifier of the overlay window that is displayed once a visitor clicks a POIs marker on the map. The overlay is added to the DOM by the javascript code that follows, which contains all that's required for the tutorial to be complete and working at warp speed.

Map overlay preview

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var map; // global var to store the google map
var centerCoord = new google.maps.LatLng(46.782101,23.643855); // tulghesului street, Cluj-Napoca
var centerCoord = new google.maps.LatLng(40.453577,-3.68763); // Estadio Santiago Bernabeu, Madrid
var browserDetectedLocation = null;
 
// global variables used throughout the js functionality
var markersArray = [];
var infoWindow = new google.maps.InfoWindow({});
 
 
function setLocation()
{
	// try to get user location via W3C standard Geolocation in browsers or via Google Gears
	if(navigator.geolocation) 
	{
	    navigator.geolocation.getCurrentPosition(function(position) 
		{
			blueIcon = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
			browserDetectedLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
			map.setCenter(browserDetectedLocation);
			var marker = new google.maps.Marker({
			      position: browserDetectedLocation, 
			      map: map, 
			      title: 'You are here',
			 	  icon: blueIcon
			});
			$('#home-messages').text("Location detected. Please wait...");
	    }, function() {
	     // error getting location, though supported
			$('#home-messages').text("Your location cannot be detected.");
	    });
	} else if (google.gears) 
	// if location not found using W3C standard try with Google Gears if browser supports it
	{
	    var geo = google.gears.factory.create('beta.geolocation');
	    geo.getCurrentPosition(function(position) 
		{
			blueIcon = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
			browserDetectedLocation = new google.maps.LatLng(position.latitude,position.longitude);
			map.setCenter(browserDetectedLocation);
			var marker = new google.maps.Marker({
			      position: browserDetectedLocation, 
			      map: map, 
			      title: 'You are here',
				  icon: blueIcon
			});
 
			$('#home-messages').text("Location detected. Please wait...");
	    }, function() {
			// error getting location, though supported
			$('#home-messages').text("Your location cannot be found.");
	    });
	} 
	else	
	{
		// Browser doesn't support Geolocation
		$('#home-messages').text("Your location cannot be found.");
	}	
}
 
function InitMap(options, mapIdentifier, defaultLocation, detectLocation)
{ // function to initialize map
	var settings = // json variable for default settings
	{
		zoom: 15,
		center: defaultLocation,
		mapTypeId: google.maps.MapTypeId.SATELLITE
	};
	if (options!=null) settings = options; // if no options provided, start the map with default settings
	map = new google.maps.Map(document.getElementById(mapIdentifier), settings);
 
	map.setCenter(defaultLocation);
	if(detectLocation==true) setLocation(); // try to get user location via W3C standard Geolocation in browsers or via Google Gears
	else
	{
		$('#home-messages').text("Click an office on the left to view its location.");
	}
 
	return map;
}
 
function handle_clicks()
{
	$('#home-sidebar ul li a').live('click',function(){
		clearOverlays();
		var coordString = $(this).attr('rel');
		var coordTitle = $(this).text();
		var coordArray = coordString.split(',');
		var update2Location = new google.maps.LatLng(coordArray[0],coordArray[1]);
		map.setCenter(update2Location);
		addMarker(update2Location,coordTitle,coordArray[2]);
 
  		$('#home-messages').text("Viewing: "+coordTitle);
	});
}
 
function addMarker(m_position,m_title,m_infowindow) {
	marker = new google.maps.Marker({
	  	position: m_position,
	  	map: map,
		title: m_title
	});
	markersArray.push(marker);
  	var mark = markersArray.pop();
	google.maps.event.addListener(mark, 'click', function() {
		infoWindow.open(map,mark);
		var stringContent = m_infowindow;
		infoWindow.setContent("<div id=\"infowin-overlay\""+stringContent+"</div>");
 
		overlayHeight = $('#infowin-overlay').height();
		overlayWidth = $('#infowin-overlay').width();
		$('#infowin-overlay').parent().css('height',overlayHeight);
		$('#infowin-overlay').parent().css('width',overlayWidth);
	});
 
	markersArray.push(mark);
}
 
function clearOverlays() {
  if (markersArray) {
    for (i in markersArray) {
      markersArray[i].setMap(null);
    }
  }
}
/* end of functions */
 
$(document).ready(function(){
 
	if($('#map').get(0))
	{ // only initialize the map if map is located inside the page
		map = InitMap(null,'map', centerCoord, true); // initialize the map on default location
		handle_clicks(); // click events handling by jQuery	
	}
 
});

I've added comments to the most important lines of jQuery above. The setLocation() function tries to detect user location and center the map around his location. The InitMap() function is used to get the entire thing rolling, and takes a couple of arguments that allows you to set the default location displayed when the map loads, as well as to enable or disable user location tracking.

The handle_clicks() function is used to track clicks on the items contained in the sidebar list and move the map around on top of the clicked point of interest. addMarker() is used to add a marker to the map, marker which represents the location of a POI and which users can click to have a detailed overlay displayed. Finally, clear_overlays() clears existing overlays to avoid duplicated content.

Demo

I've prepared a demo of the tutorial over here.

If you enjoyed this article you can stay updated to new content via our RSS feed or by email.

Published on Wednesday, August 11th, 2010 at 5:26 pm in jQuery.

About Bogdan Pop

Bogdan Pop is a young Romanian entrepreneur who runs WebRaptor. He is a web developer with awesome design skills, who enjoys writing about everyday's work and usability. He relaxes by taking photos every once in a while and by mixing french electronic music. Connect with him via Twitter.
 
  1. Marcel says: August 17th, 2010 at 10:53 am

    Hi, great tutorial, exactly what i was looking for. Is it possible to display all of the POI at the same time? Thank you!

  2. Bogdan Pop says: August 18th, 2010 at 5:42 am

    Hi Marcel, yes you can. Just comment the clearoverlays() function call and that should do it.

  3. kishan says: August 23rd, 2010 at 2:13 pm

    Thanks for such a nice article.
    I want to use this in my application, i just want to know how can I pass an address field instead of Latitude/Longitude(40.453577,-3.68763)? and how can I use this for showing multiple contacts on single map?
    Please let me know your comments over this. Thanks in advance.

  4. Bogdan Pop says: August 25th, 2010 at 9:25 am

    Hi Kishan, glad you found it useful.

    In order to use a terrestrial address instead of a lat/lng coordinate you would have to use the Geocoder to translate your address to lat/lng coordinates.

    Here’s the reference for the Geocoder API: http://code.google.com/apis/maps/documentation/javascript/reference.html#Geocoder

    Please note that the number of requests you can send to the geocoder per second is limited, so if you have a database that stores addresses, you should modify it and add lat/lng to it so that you can use these instead.

    If the Geocoder fails due to large number of requests, your users will see a js popup with some Geocoder specific error.

    In terms of adding multiple items in the same time on the map, you would have to create an array and store each marker in the array. This way you can avoid duplicate markers.

    If duplicate markers doesn’t bother you, you can remove the clearOverlays() function and markers will be appended to the map.

  5. Bogdan Pop says: August 25th, 2010 at 9:27 am

    Oh, and as many of you have requested, Hopefully by next week I’ll write a new article on having multiple POIs on the same map without any tricks.

  6. mrmema says: September 8th, 2010 at 9:01 am

    Hi Thank for sharing. There is a way to see all the markers when the map is loading?
    Thanks em

  7. Bogdan Pop says: September 8th, 2010 at 9:17 pm

    Hi Emanuel,

    What exactly do you mean by: “There is a way to see all the markers when the map is loading?”

    Do you want all the markers to stay visible on the map while clicking different links in the sidebar?

  8. mrmema says: September 9th, 2010 at 3:14 am

    Hi thanks, yes correct, when the page load i would like to have all marks visible

  9. Bogdan Pop says: September 9th, 2010 at 9:01 am

    @Emanuel
    Check out the new tutorial. It is a revised version of this one, which allows multiple POIs at the same time, and also shows user’s location. Here’s the link: http://bit.ly/aXUpZz

  10. david Lewendon says: June 14th, 2011 at 5:52 pm

    hi i dont supose you could show us how to call the data fron a json file rather than in the html?
    THanks for a great tutorail it’s good to see someone who can follow it up and reply to comments nice one:)

  11. Bogdan Pop says: June 17th, 2011 at 10:50 pm

    Hi David,

    Sorry for the delay. What do you mean call the data from json rather than html?

    Data used is from json files, processed by jQuery.

  12. julius ham says: February 20th, 2012 at 4:35 pm

    hi Bogdan, i have a special request for help.
    instead me i would like to get the data of lat lon stored in mysql db. After making a search of say id of lat lon the resulting lat lon is googlemapped.

  13. Bogdan Pop says: February 26th, 2012 at 3:48 pm

    Hi Julius, you can modify the html and output content from the database in the office location list. That would basically mean displaying data from the database, be it mysql, sqlite or anything else.

  14. Robert Austin says: May 28th, 2012 at 8:15 pm

    Hi Bogdan

    just want to say what a great find this is, I have been playing around with different code to try and do something like this website http://econym.org.uk/gmap/example_categories.htm

    but i couldn’t get this one working with geolocation, so i was wondering if it was possible with your code. As you can see in the link above if you click on say Theatres it gives you a list of Theatres and if you click on golf courses it gives you a list of golf courses and so on

    i hope this makes sense and look forward to your reply

    kind regards

    Robert

  15. Bogdan Pop says: May 31st, 2012 at 3:48 pm

    Hi Robert,

    You just need 2 arrays to store the different markers (or a matrix if you want to store n categories of markers)

    Then you need the buttons (classic, css, radio, whatever suits you) and attach on click events to them and loop through the markersArray that contains those specific markers and show them on the map.

  16. Robert Austin says: June 1st, 2012 at 12:59 pm

    Hi Bogdan

    Thank you for your reply, I’m sorry but how would I do what you suggest I forgot to put in my last message that I’m also new to javascript so not sure on where to start

    Sorry for sounding dumb

  17. 45 Useful jQuery Tutorials And Techniques For Better UI says: October 2nd, 2013 at 2:48 pm

    […] 39. Build a POI map using jQuery & Google Maps v3 […]





Save time next time! You won't have to fill out all these fields again. Register in just a few clicks and then login.


If you do not have a username, you can register in just a few clicks.