I\'m using Jquery Mobile 1.0 and Google Maps v3 to load a user location map. The map loads fine when accessed via direct url but when accessed from a link, it chokes up and not
Interesting, I need to use "pageshow"
rather than "pageinit"
when navigating from another page.
When using "pageinit"
, the on
function is run, but the callback function to draw the map is not.
When using "pageshow"
as in $( document ).on( "pageshow", "#map-page", function() {
, then the callback draw map is run just fine by jQuery.
So, while I would prefer to use "pageinit"
, that just doesn't work for me.
If you navigate to this page from another page, jQM only pulls in the JS within your div[data-role="page"] tags, so if your JS is in your <head>
tags that won't be pulled in, this is what is causing your issues.
Also yes you should use pageinit instead of pageshow, pageshow will re-fire if you navigate back to a page etc... if you have issues with a page being loaded more than once and multiple pages with the same id, there's a clever trick to use the last div[data-role="page"]
jQuery("div:jqmData(role='page'):last").bind('pageinit', function(){
So for a trouble free answer try this:
<div data-role="page" id="basic_map">
<script type="text/javascript">
$("div:jqmData(role='page'):last").bind('pageinit', function() {
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position){
initialize(position.coords.latitude,position.coords.longitude);
});
}
});
function initialize(lat,lng) {
var latlng = new google.maps.LatLng(lat, lng);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
}
</script>
<div data-role="header">
<h1>map test 901</h1>
</div>
<div id="map_canvas"></div>
</div>
I encountered the same issue and couldn't fixed it with JQM event's model.
Finally I fixed it by adding rel="external"
to all the anchors that are linking to a page with a google map. This solution desactivates pages transitions and preloaders.
Quick and dirty but... it works now.
Amazing response of lulalala - thank you for solving my issue. I changed the HTML code (class="gmap_canvas" instead of id="gmap_canvas") according to his answer. In addition I added
google.maps.event.trigger(map, "resize");
to show the map properly.
See also function showMap for details.
In the html I changed the div tag for the map into:
<div data-role="content">
<div id="container" class="container">
<div class="gmap_canvas"></div>
</div>
</div><!-- div content -->
and I added a rel="external" - Attribute to all of the anchor tags:
<div data-role="navbar" data-theme="b">
<ul>
<li><a id="karteLink" href="index.html" data-icon="karte" data-transition="fade" rel="external">KARTE</a></li>
<li><a id="listeLink" href="liste.html" data-icon="liste" data-transition="fade" rel="external">LISTE</a></li>
<li><a id="optionsLink" href="favoriten.html" data-icon="options" data-transition="fade" rel="external">OPTIONEN</a></li>
</ul>
</div><!-- /navbar -->
My code (jquery)
var activePage;
$( '#karte' ).live( 'pageinit',function(event){
activePage = $(event.target);
initialize();
});
function initialize() {
// prepare Geocoder
clearOverlays();
var geocoder = new google.maps.Geocoder();
navigator.geolocation.getCurrentPosition(function(position) {
var myLatlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var myOptions = { // default map options
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
showMap(myOptions);
google.maps.event.trigger(map, "resize");
findPlaces();
});
}
function showMap( options ) {
canvas = $('.gmap_canvas', activePage);
canvas.css({width: '100%', height: '100%', position: 'relative'});
map = new google.maps.Map(canvas[0], options);
myLatLng = options.center;
}
// clear overlays function
function clearOverlays() {
if (markers) {
for (i in markers) {
markers[i].setMap(null);
}
markers = [];
infos = [];
}
}
// clear infos function
function clearInfos() {
if (infos) {
for (i in infos) {
if (infos[i].getMap()) {
infos[i].close();
}
}
}
}
// find custom places function
function findPlaces() {
var cur_location = myLatLng;
// prepare request to Places
var request = {
location: cur_location,
radius: radius,
type: [type],
keyword: [keyword]
};
// send request
service = new google.maps.places.PlacesService(map);
service.search(request, createMarkers);
}
// create markers (from 'findPlaces' function)
function createMarkers(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
// if we have found something - clear map (overlays)
//Eigene Winzer von der Datenbannk holen
$.getJSON(urlInit, function(data){
$.each(data.winzer, function(restaurant, daten){
var locationObject = new Object;
locationObject.name = daten.name;
locationObject.geometry = new Object;
locationObject.geometry.location = new google.maps.LatLng(daten.latitude,daten.longitude);
locationObject.vicinity = daten.ort;
createMark(locationObject);
});
});
// and create new markers by search result
for (var i = 0; i < results.length; i++) {
createMark(results[i]);
}
} else if (status == google.maps.places.PlacesServiceStatus.ZERO_RESULTS) {
alert('Sorry, nothing is found');
}
}
// creare single marker function
function createMark(obj) {
// prepare new Marker object
var mark = new google.maps.Marker({
position: obj.geometry.location,
map: map,
title: obj.name,
animation: google.maps.Animation.DROP
});
markers.push(mark);
// prepare info window
var infowindow = new google.maps.InfoWindow({
content: '<img src="' + obj.icon + '" /><font style="color:#000;">' + obj.name +
'<br />Rating: ' + obj.rating + '<br />Vicinity: ' + obj.vicinity + '</font>'
});
// add event handler to current marker
google.maps.event.addListener(mark, 'click', function() {
clearInfos();
infowindow.open(map,mark);
});
infos.push(infowindow);
}
I would suggest using the pageinit
event instead:
From the jQuery docs:
http://jquerymobile.com/demos/1.0.1/docs/api/events.html
pageinit
Triggered on the page being initialized, after initialization occurs. We recommend binding to this event instead of DOM ready() because this will work regardless of whether the page is loaded directly or if the content is pulled into another page as part of the Ajax navigation system.
$( '#aboutPage' ).live( 'pageinit',function(event){
alert( 'This page was just enhanced by jQuery Mobile!' );
});
I had similar issue, and I use external js file.
Several thing which I did wrong:
<body class="map"
before I run my map loading, but it should be at the JQM's div page level like <div data-role="page" class="page-map">
, since if the page is loaded via Ajax the body class will be irrelevant.class="map_canvas"
instead of id="map_canvas"
to avoid id duplication.activePage = $(event.target)
. With this I can get the correct canvas by $('.map_canvas', activePage)
. (I encountered once that the map is loaded into some hidden div)My code (coffeescript):
$(document).on "pageinit", (event) ->
activePage = $(event.target)
return if !$(activePage).is('.page-map')
createMap = (options) ->
canvas = $('.map_canvas', activePage)
canvas.css(width: '100%', height: '90%')
map = new google.maps.Map(canvas[0], options)
address = $('.address', activePage).text()
geocoder = new google.maps.Geocoder()
geocoder.geocode {address: address}, (results, status) ->
if status == google.maps.GeocoderStatus.OK
options =
zoom: 14
center: results[0].geometry.location
mapTypeId: google.maps.MapTypeId.ROADMAP
map = createMap(options)
map.setCenter(results[0].geometry.location)