Simplemodal Google Map displays once but not on 2nd Click - google-maps-api-3

I've done well by my standards! I have pretty much zero knowledge of JS other than the basics of Functions etc. Ive used these pages to pull together a working script that loads Google Maps into a Modal using the SimpleModal framework. To my relief I got it working but it has one final bug that I cannot shift. The Modal loads on the first click of the HREF but if I close the modal and then try to reopen it it loads the modal with parts of the map missing. The missing map issue was a problem i thought I had already solved. My JS is
var map;
var src = 'https://sites.google.com/site/bristol2monaco/kml/route2.kml';
function initialize() {
var myLatlng = new google.maps.LatLng(51.337890,-0.813049);
map = new google.maps.Map(document.getElementById("basic-modal-content"), {
center: myLatlng,
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
loadKmlLayer(src, map);
}
function loadKmlLayer(src, map) {
var kmlLayer = new google.maps.KmlLayer(src, {
suppressInfoWindows: true,
clickable: false,
preserveViewport: true,
map: map
});
}
initialize();
and the js file that registers the 'click' contains:
jQuery(function ($) {
// Load dialog on page load
//$('#basic-modal-content').modal();
// Load dialog on click
$('#table .newbasic').click(function (e) {
$('#basic-modal-content').modal();
var center = map.getCenter();
google.maps.event.trigger(map, "resize");
map.setCenter(center);
return false;
});
});
As i thought i had already solved the missing map bug (using solutions posted here) with the (map, resize) line above none of the solutions on here help. Do i have to reinitialise the map or something. Grateful for advice.

When you call the modal to open use the onOpen Function described by Eric Martin. With using his onOpen function you will be able to use the callback feature and thusly use the google map event-listener to listen for the resize event. Once the resize event has been heard, you can reinitialize your google map thusly removing the gray areas
$("#table .newbasic").modal({
onOpen: function (dialog) {
google.maps.event.addListenerOnce(map, 'resize', function() {
//Alert TESTING IF RESIZE is heard(remove after test)
alert("heard resize onOpen");
initialize();
map.setCenter(center);
});
google.maps.event.trigger(map, "resize");
}
});

Related

google maps infoWindow click event re-renders map-canvas in Meteor

Hey Im trying to use google maps within my MeteorJS project to have google maps display on a map all customers, and then to display an infoWindow when you click on one of the markers.
problem is anytime you click on the marker it re-renders the map from scratch, i know this has to do with the the reactivity of the Session variable being set when the infoWindow is being clicked.
is there any way avoid the map being re-rendered when the session variable is changing?
thanks.
below is the JS and template im using in my project.
<template name="customers_map">
{{#constant}}
<div id="mapWrapper">
<div id="map-canvas"></div>
</div>
{{/constant}}
</template>
the code for making the google maps and markers.
Template.customers_map.rendered = function() {
$("#map-canvas").height("400px");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(p) {
Session.set("myLat", p.coords.latitude);
Session.set("myLng", p.coords.longitude);
});
}
Deps.autorun(function(){
var mapOptions = {
center: new google.maps.LatLng(Session.get("myLat"), Session.get("myLng")),
zoom: 15,
zoomControl: true,
zoomControlOptions: {style: google.maps.ZoomControlStyle.SMALL},
streetViewControl: false,
mapTypeControl: false,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.SMALL
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var infowindow = new google.maps.InfoWindow({
content: Template.customers_infoWindow()
});
Customers.find().forEach(function(customer) {
if (customer.loc != null) {
var geo = customer.geoLocation();
var marker = new google.maps.Marker({
position: new google.maps.LatLng(geo.lat, geo.lng),
title: customer.name(),
icon:'http://maps.google.com/mapfiles/ms/icons/green-dot.png'
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function() {
Session.set("customerId", customer._id);
infowindow.open(map,marker);
});
} else {
console.log(customer.name() + " has no geoLocation");
};
});
});
};
the infoWindow template
<template name="customers_infoWindow">
<h1>{{record.name}}</h1>
</template>
and the js for the infoWindow template
Template.customers_infoWindow.record = function() {
return Customers.findOne({_id: Session.get("customerId")});
}
If you create a global googlemaps object, you can access its properties from anywhere. This article has a nice example of doing this.
The overall gist is:
Create a googlemaps class with an initialize method. At the end of the initialize method, set a session variable for your map's existence. ( Session.set('map', true);)
Call create a googlemap object by calling the googlemap init method from within Template.customers_map.rendered.
It's a bit difficult to be sure without having a running version in front of me, but I think this is essentially because you have all your code in one big Deps.autorun block. Clicking one of the markers is changing the Session variable customerId, which will cause customers_infoWindow to re-render (as it's clearly a dependency), but I'm sure this is the intended behaviour.
However, since you're declaring var infoWindow in your Deps.autorun block to have an instance of that template as one of its properties, I think that changing customers_infoWindow will actually invalidate the entire Deps.autorun calculation, which means the whole block will be executed again, including the var map = new google.maps.Map(...) line, which will essentially re-render the map (even though it doesn't re-render that actual div element that contains it).
So, I would suggest splitting your code into separate Deps.autorun blocks, and making sure that anything in the same block should be re-run at the same time - clearly, this means that the Google Maps initialisation code and the infoWindow handler should be in separate blocks.
To reiterate, I think that's what's going on, but you'll have to try it and let me know...

How to call function while click <a> that inside the infoBubble content?

I am a new beginner try to add a google map in my website, and there have some problems.
I am trying to add some markers with the infobubble in the google map, then i want to add inside the infobubble content, after click on the , a function will be call, but infobubble seems different with infowindow, i have try to search many methods and still can't do this.
Here is my example:
function createMarker(point, locations, map) {
var content = '<a id="test" href="#">Deatils Information</a>';
var infoBubble = new InfoBubble({
minWidth: 300,
minHeight: 150,
padding: 15,
hideCloseButton: true,
borderRadius: 0,
content: content
});
var marker = new google.maps.Marker({
position: point,
map: map
});
google.maps.event.addListener(marker, 'click', function() {
infoBubble.open(map, marker);
});
};
I have search and find many examples,
$("#test").live("click", function(){
alert("clicked");
});
this function is only work inside the infowindow.
and
$(infoBubble.bubble_).live("click", function() {
alert('clicked!');
});
this function do not have any response,
if there any methods can do this function? Or somethings i should be read if i want to solve this problems? Please give me some hints. Thank you very much!!
Your problem is the HTML "string" in the infobubble is not part of the DOM until after the infobubble is created and rendered.
This should work:
function testClick() {
alert("clicked!");
}
and in your infowindow/infobubble:
var content = '<a id="test" href="javascript:testClick();">Deatils Information</a>';

Google maps KmlLayer times out and InfoWindow not showing

I have a google map embedded in a site that loads a kml file at https://www.getstable.org/who-can-help/therapist-map-kml using KmlLayer. Sometimes the map doesn't load up, I presume because google maps has a strict timeout, and often some of the pins on the map aren't clickable but some are with no clear reason why. Does anyone know what the timeout limit is on kmlLayer and how to increase it? Also is there any reason why sometimes some of the pins aren't clickable (ie no InfoWindow appears when you click a pin and the cursor doesn't change to a hand)?
Here's the code that shows it (some of the fields are templated):
<div id="map_canvas" style="width: 856px;height: 540px;">Loading...</div>
<script type="text/javascript" src="{protocol}://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var the_map = {
options : {
zoom:{embed:zoom_level},
center:new google.maps.LatLng({embed:latitude},{embed:longitude}),
mapTypeId: google.maps.MapTypeId.ROADMAP
},
geocoder : null,
map : null,
init : function() {
this.geocoder = new google.maps.Geocoder();
$('#map_canvas').delegate('a', 'click', function(event) {
window.location.href=$(this).attr('href');
return false;
});
},
load_map : function() {
this.map = new google.maps.Map(document.getElementById("map_canvas"), this.options);
query = encodeURI('{site_url}{embed:map_url}');
var ctaLayer = new google.maps.KmlLayer(query,{
preserveViewport:true
});
ctaLayer.setMap(this.map);
}
}
$(document).ready(function() {
the_map.init();
the_map.load_map();
});
</script>
The Google Servers have an unspecified timeout, but testing shows it to be 3-5 seconds. This timeout is not something you can affect. The solution is to make your server respond faster. This issue almost always comes down to a file that is too big (yours isn't) or from dynamically generating the KML. You need to optimize this and that may mean finding a way to create a static KML file.
Features that are not clickable are almost certainly a problem with your KML. You can validate your KML to check for this:
Feed Validator
KML Validator
You can also test your KML by loading it at maps.google.com.

Google Maps and Location

I'm building an application using CakePHP that will store events including the event location. When a user visits the application they will see a Google Map that will get their location and show events near them in the form of little pins that they can click on to view the event details.
I have some questions though:
1.) How would I store the Location in the DB? Would the actual geolocation coordinates be the best bet and how would I make it easy for a user to create an event and enter them.
2.) Once I have the events in place how do I create custom pins with the info pulled from the DB? Example like foursquare:
3.) Whilst getting the users location using HTML5 Geolocation how do I show a little loader on the map again like Foursquare does?
So far I've managed to create the Map and make the controls minified and get the location of the viewer but I'm not sure how do 3 and show a better feedback to the user for the geolocation.
If someone could help me with those other two questions as well it'd be very much appreciated as I'm finding it very confusing so far. Thanks.
var map;
function initialize() {
var myOptions = {
zoom: 8,
panControl: false,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map_canvas'),
myOptions);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Location found using HTML5.'
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
1) Store the actual coordinates of the location and any extra meta data (if you have it) like place name, foursquare_id, date, etc. Storing it this way will make using the data later on straightforward, such as plotting on a map or location name lookup. This will be your Location model.
Create an Event model which you can then associate to a Location. You could hack together some nice interactive functionality using event handlers on your map markers.
Something like: "the user clicks a location on the map, up pops a box asking them would like like to create a new event at this location, marker is added to the map and a form appears where they can populate the event details, etc, etc." You get the idea.
Have a look at the Marker documentation.
2) You can set a custom image for the map markers using ImageMarker Class. Take a look at the huge set of examples for ideas of what's possible.
3) The navigator.geolocation.getCurrentPosition() method as I understand it, is asynchronous. The first argument is the successCallback.
With this in mind, you could set an overlay on your map: "Finding your location", then make the call to getCurrentPosition(). In your successCallback function, you would then hide the overlay.

When is remove_at event in Google Maps API v3 triggered?

I am working on google map api v3 and want to add a feature of editing the polyline. As of the google documentation. There are 3 events fired when a polyline is in edit mode.
insert_at
set_at
remove_at
I know when first two events are fired and am able to get the edited coordinates as well. I also want to delete a node but not sure how it works?. Can anyone tell me when will the event "remove_at" will be fired ?
According to the documentation these events belong to class google.maps.MVCArray. You can find there also a description of remove_at event:
This event is fired when removeAt() is called. The event passes the
index that was passed to removeAt() and the element that was removed
from the array.
But I'm not sure you can use these events to handle changes while editing the Polyline. That's very interesting, please let us know if it works and how!
'remove_at' will be triggered when you undo an edit to an existing overlay that results in control point(s) getting removed.
I've created a fiddle to demonstrate this.
From the fiddle:
var myLatlng = new google.maps.LatLng(60.629765, 6.424094);
var myOptions = {
zoom: 14,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var drawMan = new google.maps.drawing.DrawingManager({
map: map,
drawingControl: false,
polygonOptions: {
editable: true,
draggable: true
}
});
drawMan.setDrawingMode(google.maps.drawing.OverlayType.POLYGON);
google.maps.event.addListener(drawMan, 'overlaycomplete', function (event) {
// When draw mode is set to null you can edit the polygon you just drawed
drawMan.setDrawingMode(null);
google.maps.event.addListener(event.overlay.getPath(), 'remove_at', function () {
alert('remove_at triggered');
});
});

Resources