Google Maps Not Working in jQuery Tabs

Joe picture Joe · Feb 27, 2012 · Viewed 27k times · Source

Google maps not working when placed inside jQuery tabs is a question that's all over the web. In my research so far none of the solutions seem to work. Hopefully someone here can help...

This is a screenchot of the error in Firefox 10, Chrome 17, Safari 5.1.2, Opera 11.61. http://www.flickr.com/photos/75523633@N04/6932970713/

The error is not present in IE8 and is intermittant in 9. In Firefox, it goes away when you open FireBug.

The site is in Wordpress 3.3.1 and the map is generated/retrieved via a plugin. It does not seem to matter which maps plugin I use; the error remains the same. Based on my research, this appears to be js/jQuery problem between the tabs and the Google Map API javascript, not a Wordpress/plugin problem.

Here is my code. Right now, I'm using the wp-gmappity-easy-google-maps plugin for the maps, but I have also tried the comprehensive-google-map-plugin. Both work great outside the tabs.

HTML:

// Header calls:
<script type='text/javascript' src='http://maps.google.com/maps/api/js?sensor=false'></script>
<script type='text/javascript' src='http://xxxxxxxxxx.com/wp-content/themes/zzzzzzzzzz/scripts/tabs.min.js'></script>
// HTML Body:
<div class="tabs_framed_container">
<ul class="tabs_framed">
    <li><a href="#">Tab 1</a></li>
    <li><a href="#">Tab 2</a></li>
    <li><a href="#">Tab 3</a></li>
    <li><a href="#">Map Tab</a></li>
    <li><a href="#">Tab 3</a></li>
</ul>
<div class="tabs_framed_content">
    <h2>Tab 1 Content</h2>
    <!-- Some Content -->
</div>
<div class="tabs_framed_content">
    <h2>Tab 2 Content</h2>
    <!-- Some Content -->
</div>
    <h2>Tab 3 Content</h2>
    <!-- Some Content -->
</div>
<div class="tabs_framed_content">
    <div class="map_container">
        <div style="width:900px;margin-left:auto;margin-right:auto;">
            <div class="wpgmappity_container" id="wpgmappity-map-1" style="width:900px;height:400px;margin-left:auto;margin-right:auto;"></div>
        </div>
        <script type="text/javascript">
            function wpgmappity_maps_loaded1() {
            var latlng = new google.maps.LatLng(42.4005322,-71.2750094);
            var options = {
                center: latlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                zoomControl : true,
                zoomControlOptions :
                {
                    style: google.maps.ZoomControlStyle.SMALL,
                    position: google.maps.ControlPosition.TOP_LEFT
                },
                mapTypeControl : true,
                mapTypeControlOptions :
                {
                    style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
                    position: google.maps.ControlPosition.TOP_RIGHT
                },
                scaleControl : true,
                scaleControlOptions :
                {
                    position: google.maps.ControlPosition.TOP_LEFT
                },
                streetViewControl : true,
                streetViewControlOptions :
                {
                    position: google.maps.ControlPosition.TOP_LEFT
                },
                panControl : false,  zoom : 14
            };
            var wpgmappitymap1 = new google.maps.Map(document.getElementById('wpgmappity-map-1'), options);
            var point0 = new google.maps.LatLng(42.4005322,-71.2750093);
            var marker1_0 = new google.maps.Marker({
                icon : 'http://xxxxxxxxxx.com/wp-content/themes/zzzzzzzzzz/images/mapmarker.png',
                position : point0,
                map : wpgmappitymap1
                });
            }
            jQuery(window).load(function() {
                wpgmappity_maps_loaded1();
            });
        </script>
    </div>
</div>
<div class="tabs_framed_content">
    <h2>Tab 2 Content</h2>
    <!-- Some Content -->
</div>

Here is the relevant CSS:

.tabs_framed{padding:0;margin:0;list-style-type:none;clear:left;height:25px;border-bottom:1px solid #E5E5E5;}
.tabs_framed_container{margin-bottom:40px;}
.tabs_framed a{
    display:block; position:relative; background:#fafafa; border:1px solid #E5E5E5; padding:7px 30px; margin-right:2px;
    font-size:10px; text-decoration:none; text-transform:uppercase; letter-spacing:1px; line-height:10px; color:#777;
    opacity:1; -webkit-transition:all .5s ease; -moz-transition:all .5s ease; -o-transition:all .5s ease; transition:all .5s ease;
}
.tabs_framed a:hover{color:#20548B;text-decoration:none;background:#fff;}
.tabs_framed a.current{color:#000;cursor:default;border-bottom:1px solid #fff;background:#fff;}
.tabs_framed li,{padding:0;margin:0;list-style-type:none;float:left;}
.tabs_framed_content{display:none;background-color:#fff;border:1px solid #E5E5E5;border-width:0 1px 1px 1px;padding:30px 30px 15px 30px;}

div.wpgmappity_container img { 
    background-position: 0% 0%;
    background-color: none !important;
    max-width: none !important;
    background-image: none !important;
    background-repeat: repeat !important;
    background-attachment: scroll !important;
}

Here is a link to the file that governs my tabs: http://themes.mysitemyway.com/awake/wp-content/themes/awake/lib/scripts/tabs.min.js

flowplayer.org/tools/forum/25/79274 is one solution I found (scroll to bottom). However, the checkResize and resizeMap no longer work (see api reference at code.google.com/apis/maps/documentation/javascript/reference.html#Map, scroll down a little to "Events" and find google.maps.event.trigger(map, 'resize') which is apparently the replacement code). www.raymondcamden.com/index.cfm/2009/6/5/jQuery-Tabs-and-Google-Maps is another writeup that is too old.

I've seen this proposed:

jQuery(document).ready(function(){
jQuery('.tabs_container').bind('tabsshow', function(event, ui) {
    if (ui.panel.id == "map-tab") {
        google.maps.event.trigger(map, 'resize');
    }
});
});

but I have no idea how to implement it (tried a few ways with no success) or if it would even work.

From all my research, it looks like you have to trigger a map resize event when the tab containing the map is selected. So far, I've had no luck adapting any of the solutions out there - espceially since I'm mot familiar with js/jQuery. It seems like someone familiar with js or jQuery could solve this.

Please help me.

Answer

Jason Maggard picture Jason Maggard · Sep 25, 2013

rogercut's answer got me where I needed to be. I am using Bootstrap tabs, nested, and could not get the map to update.

When I click on tab group 2 (#tg2), the map tab is the first one showing. I also needed to fire the resize if someone clicked the second level tab (#tab1) from within tab group 2.

The click handler works, but the problem is that on click, the tab is still hidden... By setting a small delay, it gives time for the tab to show before the resize fires off.

// Create Map
var map;
function initialize() {
  var mapOptions = {
    zoom: 8,
    center: new google.maps.LatLng(48.8582, 2.2945), //I see Paris, I see France
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
 map = new google.maps.Map(document.getElementById('map-canvas'),
  mapOptions);
}

//Bind click handlers - Here's the important part
$('a[href=#tab1], a[href=#tg2]').on('click', function() {
    setTimeout(function(){
        google.maps.event.trigger(map, 'resize');
    }, 50);
});

So, we're telling the browser to wait 50ms after the click to do the resize. In my testing, 50ms was plenty of time for the tab to show, yet short enough that it's not really noticeable to the user. In fact, my testing worked with a delay of only 1ms on the 4-5 machines I tested it on - even a dog slow laptop we had sitting in storage. 50ms is just being safe.

Hope this helps someone else.