This is common difficulty most of developers face when using jQuery Mobile and Google Maps. jQuery Mobile is based on Ajax navigation to load, render and show pages. Unlike HTTP, where all elements are loaded and shown at once.
A page in jQuery Mobile passes through several page events, it starts with pagebeforecreate
and ends with pageshow
-pagechange
is last but rarely used-. During those events, a page gets enhanced/rendered but still not fully ready to be shown, as height of main divs is still unset.
However, on pageshow
height of main divs is set and defined, except for content div data-role="content"
which depends on elements within.
This being said, initializing Google Maps should occur during pageshow
event. Using any other event will load an incomplete map. Another note, height of content div should be reset in order to fully accommodate map. I have written in details a full solution for all jQuery Mobile versions.
CSS - Remove content's div padding
and set map's div height
and width
.
#map-canvas {
width: 100%;
height: 100%;
}
.ui-content {
padding: 0;
}
JS - Initialize map on pageshow
event. If it's a full page map (no toolbars), reset content div's height
and width
based on viewport. Remember that content div's dimensions should be reset on orientationchange
and throttledresize
events.
$(document).on("pageshow", "#mapPage", function () {
$(".ui-content", this).css({
height: $(window).height(),
width: $(window).width()
});
InitilizeMap();
});
You can also use .one()
instead of .on()
if you want to initialize it one time only.
Bonus - Back button for full page map, to be appended on idle
event after map is fully initialized.
google.maps.event.addListenerOnce(map, 'idle', function (e) {
$("#map-canvas").append($("<a href='#' data-role='button' data-rel='back' class='forMap'>Back</a>").hide().fadeIn(300));
$(".forMap").buttonMarkup({
mini: true,
inline: true,
corners: false
});
});
google.maps.event.addListener(map, 'dragstart', function (e) {
$(".forMap").animate({
"opacity": 0.3
}, 300);
});
google.maps.event.addListener(map, 'dragend', function (e) {
$(".forMap").animate({
"opacity": 1
}, 700);
});
Back button CSS
.forMap {
position: absolute;
top:0;
left:0;
}
Demo
References: