Up and running with Google Maps API using jQuery Gmap3

I never got an opportunity to play around with the Google Maps V3 API. I usually find myself embedding Google Maps on a client’s website that simply shows their address and thats enough.

Recently, I received the task to display locations of multiple companies on a Google map. This can be done with Google Map Maker but not in my case. The company addresses were coming in from a database so I needed a dynamic solution. I also needed more control over the location marker and the content in the info window (or, as some like to call it, info bubble).

I started looking up for solutions and  Google Maps V3 API seemed to be the perfect fit for this job. What also caught my attention was Gmap3, a jQuery plugin for Google Maps. Gmap3 utilises the Google Maps API and makes the process of building custom maps alot easier. Gmap3 “abstracts” the process of generating maps which results in less code writing.

Ok, enough talk. Lets see how its done.

Setup

Head over to the Gmap3 website and download the latest version (v5.1.1 as of today). You will get a zip file containing the main JS script and a bunch of example files. All you really need is the gmap3.min.js.

Here is our basic HTML:

<html>
<script type="text/javascript" src="js/jquery-2.0.2.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript" src="js/gmap3.min.js"></script>
<head>
<title>My First Custom Google Map</title>
<body>
<div id="my_map" class="gmap"></div>
</body>
</html>

Lets also write some basic CSS:

.gmap{
width: 870px;
height: 570px;
}

A couple of things to note in the code examples above:

  • The load order of scripts is important and should be
    1. jQuery
    2. Google Maps API
    3. Gmap3
  • You need to specify a width and height for your map div. If you don’t do this, you wont see anything on the screen.

Map Initialisation

Now the fun stuff. The following code will initialise the map.

$(document).ready(function() {
$('#my_map').gmap3();
});

This is what we will get. A sweet world map.

gmap3_1

Adding our first marker

You can add a maker on the map using either the latitude, longitude value pair or  an existing address. If you provide an address, the Google Maps API will geocode the address for you … which is excellent. In this article, I am going to provide the API with an address.

$(document).ready(function() {
$('#my_map').gmap3({
marker:{
address: "266 George St, Brisbane QLD 4000"
}
});
});

Result:

gmap3_2Damn, thats as if we were looking at the marker from ISS. We need to zoom into the map to get a better sense of the location of the marker. You can do this by providing a zoom value using option parameters in Gmap3.

$(document).ready(function() {
$('#my_map').gmap3({
marker:{
address: "266 George St, Brisbane QLD 4000"
},
map:{
options:{
zoom: 16
}
}
});
});

Result:

gmap3_3

Now thats so much better.

Adding an infowindow

We will accomplish this by making two additions to our current code:

  1. Add some content to the marker to show in the infowindow.
  2. Bind a jQuery click event to the marker  to trigger the infowindow.
$(document).ready(function() {
$('#my_map').gmap3({
marker:{
events: { // events trigged by markers
click: function(marker, event, context){
var map = $(this).gmap3("get"),
infowindow = $(this).gmap3({get:{name:"infowindow"}});
if (infowindow){
infowindow.open(map, marker);
infowindow.setContent(context.data);
} else {
$(this).gmap3({
infowindow:{
anchor:marker,
options:{content: context.data}
}
});
}
}
},
address: "266 George St, Brisbane QLD 4000", data:"Welcome to Brisbane City Council"
},
map:{
options:{
zoom: 16
}
}
});
});

Result:

gmap3_4

The infowindow content accepts HTML code. So feel free to format your infowindow content using HTML tags. You can also load images into infowindows using the standard <img /> tag.

Adding multiple markers

Again, really easy. All we need is a slight syntax modification.

$(document).ready(function() {
$('#my_map').gmap3({
marker:{
events: { // events trigged by markers
click: function(marker, event, context){
var map = $(this).gmap3("get"),
infowindow = $(this).gmap3({get:{name:"infowindow"}});
if (infowindow){
infowindow.open(map, marker);
infowindow.setContent(context.data);
} else {
$(this).gmap3({
infowindow:{
anchor:marker,
options:{content: context.data}
}
});
}
}
},
values: [
{ address: "266 George St, Brisbane QLD 4000", data:"Welcome to Brisbane City Council" },
{ address: "Surfers Paradise QLD", data:"Welcome to Surfers Paradise" }
]
},
map:{
options:{
zoom: 16
}
}
});
});

Result:
gmap3_5

What the ……. Where is the second marker? well … don’t worry, its there but we can’t see it. This is because we have set the zoom level at 16 and at that zoom level, the map can only fit one of the locations in the view point. Now the question is: How to set the map dynamically adjust zoom level so we can see all the  markers? Thankfully, Gmap3 has an “autofit” option which does exactly what we want. In the process, we will need to lose the zoom option in our code. Lets just comment it out.

$(document).ready(function() {
$('#my_map').gmap3({
marker:{
events: { // events trigged by markers
click: function(marker, event, context){
var map = $(this).gmap3("get"),
infowindow = $(this).gmap3({get:{name:"infowindow"}});
if (infowindow){
infowindow.open(map, marker);
infowindow.setContent(context.data);
} else {
$(this).gmap3({
infowindow:{
anchor:marker,
options:{content: context.data}
}
});
}
}
},
values: [
{ address: "266 George St, Brisbane QLD 4000", data:"Welcome to Brisbane City Council" },
{ address: "Surfers Paradise QLD", data:"Welcome to Surfers Paradise" }
]
},
map:{
options:{
//zoom: 16
}
}
}, "autofit");
});

Note the position of the “autofit” option attribute. Make sure you place it at the right spot. Its really easy to put it at the wrong spot in a confusing sea of brackets.

Result:
gmap3_6

Adding custom markers

Prepare your custom marker as a PNG file and size it correctly. In my example, I have assigned a custom PNG marker to each address. The size of the markers is 25x40px. In the JS code, you will need to specify the location of your PNG marker. Here is the code:

$(document).ready(function() {
$('#my_map').gmap3({
marker:{
events: { // events trigged by markers
click: function(marker, event, context){
var map = $(this).gmap3("get"),
infowindow = $(this).gmap3({get:{name:"infowindow"}});
if (infowindow){
infowindow.open(map, marker);
infowindow.setContent(context.data);
} else {
$(this).gmap3({
infowindow:{
anchor:marker,
options:{content: context.data}
}
});
}
}
},
values: [
{
address: "266 George St, Brisbane QLD 4000", data:"Welcome to Brisbane City Council",
options: {
icon:"images/marker-orange.png"
}
},
{
address: "Surfers Paradise QLD", data:"Welcome to Surfers Paradise",
options: {
icon:"images/marker-blue.png"
}
}
]
},
map:{
options:{
//zoom: 16
}
}
}, "autofit");
});

Result:
gmap3_7

Watch out for these errors!

In a real-world scenario, you will have other scripts loaded into your project and the Gmap3 plugin may not play nicely with them. I faced this problem when I was loading this script into a WordPress site. Other scripts in the project included Bootstrap 3, jQuery Validation, Datatables and a few others. For some reason, my project could not locate the Gmap3 function. It was properly referenced and placed in the right order. I was pulling my hair out!

This is the error I was getting in Chrome:

Uncaught TypeError: Object [object Object] has no method 'gmap3'

And the following in Firefox:

TypeError: $(...).gmap3 is not a function

If you are facing a similar situation, try replacing $(document ).ready(function() { part of your script with jQuery(document).ready(function($){. This did the trick for me. Why this works? I am not entirely sure. My guess is, the “$”  causes conflicts with other scripts in the project. Note that I was not using Prototype in the project. Maybe, a WordPress plugin was loading another version of jQuery into the DOM causing conflicts. Feel free to share your thoughts in the comments section if you know the reason 🙂