Google Maps Not Working in jQuery Tabs
Asked Answered
M

13

7

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.

Martyrize answered 26/2, 2012 at 23:13 Comment(4)
Can you link the API for that tabs.js? That would help us more than the minified file itself.Trici
@LPP - it looks like the minified file, jQuery Tools 1.2.5 Tabs, is from flowplayer.org/tools/tabs. Download doesn't seem to work, but I did find this link to Github github.com/jquerytools/jquerytools/tree/master/src/tabsMartyrize
You can accomplish the same thing without using the heavy-weight jQuery Tools very simple. Have you thought about it?Selhorst
I am using a wordpress theme that I cannot change. The tabs feature is built in (shortcode). If you know another way to make this work, please let me know.Martyrize
M
7

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.

Martyrize answered 15/4, 2012 at 21:11 Comment(0)
J
11

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.

Jereme answered 25/9, 2013 at 20:23 Comment(1)
+1. Good work. I modified it a little bit and did the following: setTimeout(function(){ initMap(); }, 200); This lets me call teh native script without having issues with resizingIbert
M
7

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.

Martyrize answered 15/4, 2012 at 21:11 Comment(0)
P
1

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!

Pilau answered 3/3, 2012 at 15:14 Comment(0)
B
1

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);
});
Butene answered 28/8, 2012 at 21:55 Comment(0)
L
1

No of the above answers are completely correct. The problem occurs because the map canvas is set to width:0; height:0 by default before loading and then expects you to either pass the dimension or get the dimensions from the parent, as this is inside jQuery tabs there are no dimensions.

As mentioned above bind to the click event of your tab and set the map_canvas dimension then call the google.maps.event.trigger()

 $(function(){

$('#maptab').bind('click',function() {
            var w = $('#map_view').width();
            var h = $('#map_view').height();
            $('#map_canvas').css({ width: w, height: h });
           google.maps.event.trigger(map, 'resize');

        });

});
Lafontaine answered 28/9, 2013 at 19:13 Comment(0)
C
1

Before I have the same problem for implementing google-map inside tabs, specially when the map is not in the first selection. But I have tried and it's work with a simple solution like this :

Make a simple js function :

<script type="text/javascript">

function ResetMap() {
google.maps.event.trigger(map, 'resize');
}

</script>


<li><a href="#tab1">Select Tab1</a></li>
<li onClick="ResetMap();"><a href="#tab2">Select Google Map</a></li>

<div class="tab1-content" id="tab1">Content tab1</div>
<div class="tab2-content" id="tab2"><?php include_once ('google-map.php') ?></div>
Cacilie answered 7/4, 2014 at 16:59 Comment(0)
M
1

I solved this for the bootstrap Tab. It is just the matter of calling resize map function right after the map container is displayed.

I have added the following out side the initialize() function:

jQuery('.nav-tabs a[href="#my-map"]').on('shown.bs.tab', function(){
         google.maps.event.trigger(map, 'resize');
         map.setZoom(15); //You need to reset zoom
         map.setCenter(myLatlng); //You need to reset the center
    });
Milliard answered 20/10, 2014 at 10:58 Comment(0)
N
1

This might not work for everyone! One solution that worked for me was to have the hidden tabs display but somewhere "not visible" to the user. This will allow the map to render even though is not in first/active tab. Find a way to target the hidden tabs ONLY:

.tab-hidden{
    position: absolute !important;
    left: -10000px !important; /* maybe not that much */
    display:block !important;
    width:100% !important; /* I found this to be very important*/
}

Map width 100% and not a fixed width.

Nea answered 6/2, 2015 at 15:56 Comment(0)
T
0

Give this a try:

Change

<li><a href="#">Map Tab</a></li> 

to

<li><a href="#" id="maptab">Map Tab</a></li>

Then add this javascript

$(document).ready(function(){
  $('#maptab').bind('onClick', function() {
    google.maps.event.trigger(map, 'resize');
  });
});

In a script tag at the top of the page. What this should do for you:

By adding the id attribute to the tab link, you're explicitly specifying there's a map in there. You're then listening for the onClick event provided by the jQuery tabs library that fires when a tab is selected, which triggers re-sizing the map.

Trici answered 27/2, 2012 at 0:39 Comment(2)
It didn't work. I followed your instructions, putting the ID in the link and the javascript in the header. Perhaps triggering the resize when the tab is clicked isn't the solution? Or could the js not be working correctly with the minified tabs.min.js? Any thoughts? Also, thank you for your help.Martyrize
I wasn't 100% sure the event would trigger from that, since the documentation isn't clear about what you should bind the event to. If I had more time right now, I'd probably be able to get you what you needed. One more thing to try, change the onClick to simply click and see if that works. If not, I'd look at the Google maps plugin tool you're using and make sure that allows the normal API to work.Trici
K
0

The problem is simple. Maps must render in an element that has dimensions. If you use a tab system that hides the tab content, all elements inside the tab content have no dimensions while parent is hidden. If jQuery tools css lets you do it, set the "hidden" content offscreen instead of hidden.

In order to use: google.maps.event.trigger(map, 'resize');

You need access to the intitial map object variable which is "var wpgmappitymap1" but is scoped inside the map init function. If you make it a global variable you can then put it in your resize trigger

  google.maps.event.trigger(wpgmappitymap1, 'resize');
Kidron answered 27/2, 2012 at 1:3 Comment(1)
The only CSS that appears to control that is the .tabs_framed_content{display:none;... from the code in my question. Changing that to position: absolute; left: -10000px; breaks the tabs entirely. I will look through my theme's php to see if they send info to the tabs.js that way. I don't know how to make the map object variable global. Any more specific guidance would be greatly appreciated. Thank you.Martyrize
C
0

I had the same problem and here is my solution.

I added the ajaxComplete function that is triggered when all ajax request or posts are finished.

<script type="text/javascript">   
   $(document).ajaxComplete(function(e){
         calculateRoute("from","to");            
   });        
</script>      
Czernowitz answered 12/9, 2013 at 21:51 Comment(0)
C
0

Its work for me, meet my requirement, and you may use it as reference:

<script type="text/javascript">

function setCookie (name, value, expires, path, domain, secure) {
    document.cookie = name + "=" + escape(value) +
    ((expires) ? "; expires=" + expires : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}

function getCookie (name) {
    var cookie = " " + document.cookie;
    var search = " " + name + "=";
    var setStr = null;
    var offset = 0;
    var end = 0;
    if (cookie.length > 0) {
        offset = cookie.indexOf(search);
        if (offset != -1) {
            offset += search.length;
            end = cookie.indexOf(";", offset);
            if (end == -1) {
                end = cookie.length;
            }
            setStr = unescape(cookie.substring(offset, end));
        }
    }
    if (setStr == 'false') {
        setStr = false;
    } 
    if (setStr == 'true') {
        setStr = true;
    }
    if (setStr == 'null') {
        setStr = null;
    }
    return(setStr);
}

function hidePopup() {
    setCookie('popup_state', false); 
    document.getElementById('popup').style.display = 'none';
    document.getElementById('hiding').style.display = 'block';

google.maps.event.trigger(map, 'resize');
map.setZoom( map.getZoom() );
}

function showPopup() {
    setCookie('popup_state', null);
    document.getElementById('popup').style.display = 'block';
    document.getElementById('hideup').style.display = 'none';

google.maps.event.trigger(map, 'resize');
map.setZoom( map.getZoom() );   
}

function checkPopup() {
    if (getCookie('popup_state') == null) { // if popup was not closed
        document.getElementById('popup').style.display = 'block';
        document.getElementById('hiding').style.display = 'block';

google.maps.event.trigger(map, 'resize');
map.setZoom( map.getZoom() );

  }   
}

</script>


<body onload="checkPopup();">

    <div class="map-button" id="hiding"><a href="#" onclick="showPopup(); return false;"><img src="images/map_magnify.png" alt="" title="Show Google Map" ></a></div>

    <div class="map-button" id="popup" style="display:none"> <a href="#" onclick="hidePopup(); return false;"><img src="images/map_delete.png" alt="" title="Hide Google Map" ></a>
    <div id="gmap"></div>
    </div>
</body>

Note : You can make CSS class 'map-button' for positioning the button as required. Put your own image buttom. Replace id="gmap" as yours. Hope it helps you.

Cacilie answered 24/3, 2014 at 19:49 Comment(0)
G
0

Try this in the css:

.tab-content > .tab-pane:not(.active), 
.pill-content > .pill-pane:not(.active) {
 display: block;
 height: 0;
 overflow-y: hidden;
}
Gascony answered 12/6, 2017 at 22:47 Comment(1)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Eve

© 2022 - 2024 — McMap. All rights reserved.