Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps Not Working in jQuery Tabs

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.

like image 376
Joe Avatar asked Feb 26 '12 23:02

Joe


4 Answers

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.

like image 83
Jason Maggard Avatar answered Nov 04 '22 01:11

Jason Maggard


I abandoned the plugins and went with the google maps shortcode that has been released for the theme I'm using. While I lose the custom markers functionality, the theme developers were finally able to help get this all working. They added the following code to the shortcode PHP file.

jQuery('ul.tabs_framed').data('tabs').onClick(function(e,index) {
    resizeMap(" . 'map'.$map_id .") 
});
function resizeMap(m) {
    x = m.getZoom();
    c = m.getCenter();
    google.maps.event.trigger(m, 'resize');
    m.setZoom(x);
    m.setCenter(c);
};

This code triggers a map reload when the tab containing the map is clicked. It also recenters the map. This solution solved the problem for me and the google maps now display in the jquery tabs. Hopefully some of the more javascript-savvy users here (and plugin developers!!!) can adapt this solution to their own maps-in-tabs issues.

like image 32
Joe Avatar answered Nov 04 '22 02:11

Joe


When developing a website which included a map tab content I ran into the same issue. The site is http://samet.com.ar (in spanish, click on the map icon or the 'ubicacion' link). The same error you mention arose whenever the tab div loaded together with the other ones in its tab group. I've found out that if I could manage to give it some time to load after the other tabs did, then there wouldn't be any problem.

I could afford to do that because anyway I gave some 3.5 sec for the wrapper to show up in order to get all the background photos loaded and the map is in an invisible tab at load time, so I don't need it to show up right away.

The map tab then loads as a callback function right after the whole wrapper does. If you inspect the page, look for id 'pane-container'. Inside 'panes' you'll find the map div loaded at the end.

The relevant jQuery code I'm using in the index.php page is as follows:

<script type='text/javascript'>
   ( function( $ ) {
     // for SOF post --- previous code deleted ---
     $( "#wrapper" ).delay( 3500 ).fadeIn( "slow",function() {
     // Animation complete
     <?php $post_map = get_posts('name=map');?>
     $( "#map" ).delay( 1000 ).append( <?php echo "'".$post_map[0]->post_content."'"; ?> );
            } );
 } )( jQuery );
</script>

I hope this helps somehow. Forgot to mention that the map code is embedded as a content in a specific post. (BTW, the map marker is located on the upper right on purpose to show the main access roads.)

Cheers!

like image 44
rogercut Avatar answered Nov 04 '22 01:11

rogercut


The problem (as stated above and in other places) is that the map div must be visible in order to work. So load the map in a tab that is visible. Then if you wish, change to the tab you want to display.

To do this I added a one-time event listener to the map. Inside that function I changed to the first tab. During the load, you do see the map area for about a second before the tab is changed. The advantage is that the user has to do nothing for this to work.

google.maps.event.addListenerOnce(map, 'tilesloaded', function() {
     $("#Tabs").tabs('select',0);
});
like image 22
user1631533 Avatar answered Nov 04 '22 00:11

user1631533