Reputation: 6370
I'm using Twitter's Bootstrap, and want to show a Google Map in a popover.
The way it works right now I'm doing something like this
$ ->
$('.thumbnails a.js-popover').popover
html: true,
content: ->
uid = $(this).data('profileUid')
popover_container = $('.popover-contents:data(profileUid=' + uid + ')')
_.each window.Maps, (map) ->
google.maps.event.trigger map, 'resize' // I hoped this would re-draw the map
popover_container.html()
The popover loads it's content from a .popover-contents
div which is hidden, and connected to the a
with data attributes (so that I can find the correct popover to show)
The map works perfectly when not in a popover, and I think it's connected with being copied via html()
in jQuery to another DOM element. Twitter's bootstrap doesn't provide a modal opened
callback, and I'm genuinely not sure how to make the maps work.
As you can see the map works correctly on the full profile page, the markup is the same (rails partial), and the javascript is shared, too - I can only assume the GoogleMaps API really doesn't like having it's dom messed with, and is thus causing issues.
Upvotes: 2
Views: 5677
Reputation: 2309
The problem is that google maps api requires visible element for container, so you should call the api inside the shown.bs.modal event handler. Something like this:
$picker.popover({
html: true,
content: '<div class="superPopover">'
});
$picker.on('shown.bs.popover', function () {
var $container = $('.superPopover');
new google.maps.Map($container[0]);
});
Upvotes: 0
Reputation: 16510
If you're using popovers, your best bet might be to use google's static API and avoid the headaches associated with an interactive map. Borrowing a very simple case from the documentation, you might do something like this:
var options = { content: '<img src="http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=14&size=512x512&maptype=roadmap&sensor=false">' };
$('#example').popover(options)
Wrapping it up into a reusable function yields:
var getMap = function(opts) {
var src = "http://maps.googleapis.com/maps/api/staticmap?",
params = $.extend({
center: 'New York, NY',
zoom: 14,
size: '512x512',
maptype: 'roadmap',
sensor: false
}, opts),
query = [];
$.each(params, function(k, v) {
query.push(k + '=' + encodeURIComponent(v));
});
src += query.join('&');
return '<img src="' + src + '" />';
}
var content = getMap({center: 'Fritz-Walter Stadion, Kaiserslautern'});
$('#example').popover({ content: content })
Upvotes: 6
Reputation: 6370
*Another valid answer might be found here, but it's not the solution I took. *
It seems to be widely accepted that rendering a Google map in an invisible DOM element leads to rendering bugs, and the solution (cribbed from http://sethmatics.com/articles/classipress-hidden-map-tab-and-redraw-google-map-canvas/ ) appears to look something like this:
jQuery('.tabprice ul.tabnavig li a').click(function() {
if(jQuery(this).attr('href') == '#priceblock1') {
//the element has to be visible on the page for google maps to render properly
jQuery('#priceblock1').show();
//rebuild the google map canvas to the proper size
google.maps.event.trigger(map, 'resize');
//ClassiPress javascript function to build map at address
codeAddress();
}
});
I do think it might be worth moving the dom element a long way off the left/right/bottom of the screen in order to avoid it flashing to the user, or doing something with Z-Indexing to make sure that the user doesn't see an unwelcome popup.
In my case, however the static maps API as suggested by rjz was perfect.
Upvotes: 1