Gajotres.net

Using Google Maps JavaScript API v3 with jQuery Mobile

Share this article
maps
 
First let us talk about how Gmap v3 API can be used inside a classic web application, it will give us a good perspective when we switch back to jQuery Mobile. In the beginning of a map craze iframe was a standard delivery solution but as a time went by it become a outdated technology, more like an obstacle them a successful delivery technology.
 
The new JavaScript Maps API Version 3 was built from the ground up by Google to offer a clean, fast and powerful maps application development platform for both desktop Web browsers and mobile devices. The v3 API lets developers embed Google Maps in their own Web pages and is especially designed to be faster and more applicable to mobile devices, as well as traditional desktop browser applications, according to Google.
 
Unlike v2 API which worked on IE6+, Firefox 2.0+, older versions of Chrome v3 API will work on every HTML5 supported browser ranging from IE8+, Firefox 3.0 + up to iOS, Android and BlackBerry 6+ browsers. Which makes it an excellent solution for jQuery Mobile applications. But let me first show you how it works in a classic web page.
 

Classic solution


 
 
Working jsFiddle example can be found here: http://jsfiddle.net/Gajotres/T4H5X/
 
As you can see it is en extremely easy solution. It uses vanilla javascript to initialize and display the map. Map is created from numerous canvas elements and it is fully responsive.
 
<!DOCTYPE html>
<html>
    <head>
        <title>Google Maps JavaScript API v3 Example: Map Simple</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
        <meta charset="utf-8"/>
        <style>
            html, body, #map_canvas {
            margin: 0;
            padding: 0;
            height: 100%;
            }
        </style>
        <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
        <script>
            var map;
            function initialize() {
            var mapOptions = {
            zoom: 8,
            center: new google.maps.LatLng(-34.397, 150.644),
            mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            map = new google.maps.Map(document.getElementById('map_canvas'),
            mapOptions);
            }
            
            google.maps.event.addDomListener(window, 'load', initialize);
        </script>
    </head>
    <body>
        <div id="map_canvas"></div>
    </body>
</html>
 
Map container can be dynamically changed and map will automatically resize to fill new available space.
 

jQuery Mobile solution


 
 
Combine jQuery Mobile and v3 API and everything becomes a little bit complicated. Unlike classic web development jQuery Mobile pages are responsive by its nature which means page dimensions will became a problem here. During the jQuery Mobile page initialization page is constantly changing and resizing. Basically page height can be successfully calculated only during the pageshow event.
 
For those who still don’t have much experience with jQuery Mobile pageshow event is a last state to be called during the page initialization. It best jQuery counterpoint would be window ready. That means in order to successfully initialize v3 API we must do it after pages has been displayed which brakes its usefulness.
 
 
As always there’s a solution to every problem. If we have a good idea how our page is going to look we can force content div to resize according to available space even before pageshow event. This can be done with this CSS rules:
 
#content {
    padding: 0;
    position : absolute !important; 
    top : 40px !important;  
    right : 0; 
    bottom : 40px !important;  
    left : 0 !important;     
}
 
This CSS will remove classic content padding and absolutely position content div to cover all available space, giving only some space to page header. Bottom rule can be changed to 40px in case footer is also needed.
 
Working jsFiddle example can be found here: http://jsfiddle.net/Gajotres/7kGdE/
 

<!DOCTYPE html>
<html>
    <head>
        <title>jQM Complex Demo</title>
        <meta name="viewport" content="initial-scale=1, maximum-scale=1"/>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
        <style>
            #content {
                padding: 0;
                position : absolute !important; 
                top : 40px !important;  
                right : 0; 
                bottom : 40px !important;  
                left : 0 !important;     
            }
        </style>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>    
        <script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>   
        <script>
		$(document).on('pageinit', '#index',function(e,data){    
		   var minZoomLevel = 12;

		   var map = new google.maps.Map(document.getElementById('map_canvas'), {
			  zoom: minZoomLevel,
			  center: new google.maps.LatLng(38.50, -90.50),
			  mapTypeId: google.maps.MapTypeId.ROADMAP
		   });
                });
        </script> 
    </head>
    <body>
        <div data-role="page" id="index">
            <div data-theme="a" data-role="header">
                <h3>
                    First Page
                </h3>
            </div>
            
            <div data-role="content" id="content">
                <div id="map_canvas" style="height:100%"></div>
            </div>
            
            <div data-theme="a" data-role="footer" data-position="fixed">
                <h3>
                    First Page
                </h3>
            </div>
        </div>
    </body>
</html>    
 

Second jQuery Mobile solution


 
 
Unfortunately first solution will not be useful every time. Sometimes we will not know our page dimensions or what will be available space for our content div, this is where jQuery comes to help.
 
Here’s a nifty function that will calculate available content height. It can be then used to dynamically set new content height. That combined with window resize event will give you best responsiveness.
 
function getRealContentHeight() {
	var header = $.mobile.activePage.find("div[data-role='header']:visible");
	var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
	var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
	var viewport_height = $(window).height();

	var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
	if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
		content_height -= (content.outerHeight() - content.height());
	} 
	return content_height;
}
 
And here’s also a working jsFiddle example: http://jsfiddle.net/Gajotres/xbr2v/
 
 

22 COMMENTS ON THIS POST To “Using Google Maps JavaScript API v3 with jQuery Mobile”

  • Peter

    August 5, 2013 at 13:29

    Nice tutorial!
    I would like to add a marker with infowindow, it’s possible?

  • Dragan Gaić

    Gajotres

    September 9, 2013 at 14:23

    You can easily add infowindow, just google it, there are a lot of available tutorials.

  • Julia

    September 22, 2013 at 16:51

    Thanks for all your tutorials! They help so much.

    I have a question: is it wrong to use Google maps in a multi-HTML template? I have a dynamic page with a map that produces markers. Since JQM loads pages in the DOM of the initial page, it’s possible to have several maps within the DOM.

    • Dragan Gaić

      Gajotres

      September 22, 2013 at 18:49

      You can have as much pages containing maps as you want. There only one problem I can think off, Google Maps API V3 cant successfully preinitialize map in non-active pages. So when other map pages are shown you will always see a brief loading flash. Also take care that div’s containing your maps have unique id’s.

      If you also don’t like map preinitialization problem you can take a look at other map frameworks like Leaflet. It works just fine with jQuery Mobile and unlike GMap API V3 this one don’t suffer from page height problem. More information can be found here: http://www.gajotres.net/jquery-mobile-and-leaflet-integration/

  • Chuck

    September 27, 2013 at 01:39

    I have a very similar problem to the one that you discuss, but unfortunately your solution doesn’t work for me. I’m hoping that you might know how to solve my issue.

    I have a jquery mobile site that has two pages. The map needs to reside on the second page, but I want to initialize it (and then get its bounds) it upon pageinit of the index page.

    It should come as no surprise to you that the google map on the second page is sized incorrectly. Here is a fiddle showing the problem: http://jsfiddle.net/EPVe6/. I’ve tried using css to set the size of the map_canvas, but I haven’t had any luck.

    What do you think? Is it possible??

    • Dragan Gaić

      Gajotres

      September 27, 2013 at 09:49

      Unfortunately I don’t know a solution for this problem. It can be fixed partially, if you initialize map in a first page you will need to trigger map resize during the second page pageshow event. This is the closest solution that I know.

      Here’s a working example: http://jsfiddle.net/Gajotres/TyKCR/

      In this example map can be used even before second page is shown. But there’s one downside, when second page is shown map will resize to cover available space. This alone is jQuery Mobile problem
      and only way to solve it requires second page to be enhanced at the app load and currently it can’t be done. I had an idea to try to do this manually (manually enhance second page content and add classes) but I never found time to do that.

      I hope this solves your problem.

  • Chuck

    September 27, 2013 at 15:46

    I really appreciate you taking a look at this problem. Unfortunately, resizing on the second page load doesn’t solve my problem because I need the accurate map bounds before the second page load. My solution (which is specific to my application) is to change the flow so that on the index page I geolocate the user’s location manually establish a set range from that center-point. When the user navigates to the map page I’ll set the map bounds to include all of the range. Not the best approach from a ux perspective, but it will get the job done.

    Thanks again!

  • RredCat

    October 3, 2013 at 20:05

    Thanks for your article. But in my case it didn’t work without jquery.

    • Dragan Gaić

      Dragan Gaić

      October 4, 2013 at 15:24

      Thanks for your replay, can you tell me more about your solution? Maybe I can help you make a pure CSS solution. On the other hand jQuery solution is also not bad, I just don’t like using javascript if there’s a CSS solution.

  • Sergiy

    October 7, 2013 at 18:19

    Thanks for article!

    It really works in jsFiddle, but it doesn’t if you copy the code to local html-file. Could you please check that and attach html-file here?
    Thanks.

  • Sergiy

    October 7, 2013 at 18:29
    • Dragan Gaić

      Dragan Gaić

      October 7, 2013 at 18:33

      I was proactive, you will find downloadable map example somewhere in this article, so take a look.

  • Krishna

    October 8, 2013 at 11:51

    I have used the above solution but the problem i am facing is page is showing as it is loading after that no response. If include the below script the page doesn’t load else the back page appears. If anyone has faced this problem pls let me know:

    $(document).on(‘pageinit’, ‘#index’,function(e,data){
    var minZoomLevel = 12;

    var map = new google.maps.Map(document.getElementById(‘map_canvas’), {
    zoom: minZoomLevel,
    center: new google.maps.LatLng(38.50, -90.50),
    mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    });

  • Krishna

    October 11, 2013 at 11:21

    I am receiving following error any help pls.

    10-11 06:55:29.580: E/Web Console(2048): Uncaught ReferenceError: google is not defined at file:///android_asset/www/RegisteredUsers.htm:3

    • Dragan Gaić

      Dragan Gaić

      October 11, 2013 at 11:32

      You are missing:

      <script type=”text/javascript” src=”http://maps.google.com/maps/api/js?sensor=true”></script>

  • Israel

    January 6, 2014 at 16:33

    Thanks, this solved my problem with jquery mobile, google maps and phonegap, great.

  • Joe

    January 14, 2014 at 07:57

    Sometimes, the whole map doesn’t load. It happened in this fiddle: http://jsfiddle.net/Gajotres/TyKCR/. I’ve also seen it happen on my app from time to time. Do you know why, or how to prevent this?

    • Dragan Gaić

      Dragan Gaić

      January 14, 2014 at 13:27

      Unfortunately this is a GMap – jQuery Mobile blocking error. Sometimes it works and sometimes not, form my experience blame is on a Google side.

  • Hyginus

    January 18, 2014 at 07:22

    Hi Guys,

    Good to come in to this page, I am having a very seriously issue with Gmap, I have 3 pages I want to show my map. only the first page of my map will load fully is I navigate back and click the next page my map size will be weird,..showing half top left. I am using Jquery mobile and phonegap… I am not sure if this was the same case with anyone here, I really need a help to fix this.

    I will appreciate any help.

    Thanks

    • Dragan Gaić

      Dragan Gaić

      February 7, 2014 at 14:17

      Have you managed to fix this problem? Do you still need my help?

  • Ace

    March 5, 2014 at 08:39

    Doesn’t work for me :(

    • Dragan Gaić

      Dragan Gaić

      March 5, 2014 at 09:10

      What is not working for you?

Leave a Reply


+ one = seven