Google Maps API v3 Markers only load sometimes - javascript

I have a map-making tool that is built with the Google Maps API V3. It allows users to enter two or more locations and produce a map and route. I also have a checkbox that, when clicked, shows markers indicating nearby points of interest.
When I first built the tool, I think it worked well every time. Recently, though, I've noticed that the markers do not always appear when the checkbox is clicked. The map and routing work fine, but the markers only work occasionally. This error seems to occur when they don't work:
Uncaught ReferenceError: map is not defined
It references a section of the "cmarkers" section of javascript (see below).
Background detail: This is part of a Rails web app and a webpage / layout called "Itineraries". When you land on the itineraries webpage and click on the "Map Maker" icon, the map-making tool appears. It's loaded in an i-frame, it's called "map.html.erb", and the map view lives in /views/itineraries. All of the javascript for the map maker lives in the Itineraries layout file, however.
Based on reviewing these posts, I think it might be something in the way that I've ordered or initialized the code, and I think the main culprit is likely in that "cmarkers" section of the code.
Google Maps API Sometimes Not Showing Markers
Google maps api(v3) doesn't show markers
Google Maps API v3 javascript Markers don't always load
I've tried several different changes, but each has either not worked or stopped the map from initializing. Here is the javascript; please note that the API key and other small sections are redacted. Below it is the code for the markers.
<script src="https://maps.googleapis.com/maps/api/js?key=MYAPIKEY&sensor=false"></script>
<script type='text/javascript'>
$(function(){
var directionsDisplay;
var map;
function overlaysClear() {
if (markersArray) {
for( var i = 0, n = markersArray.length; i < n; ++i ) {
markersArray[i].setVisible(false);
}
}
}
function overlaysShow() {
if (markersArray) {
for( var i = 0, n = markersArray.length; i < n; ++i ) {
markersArray[i].setVisible(true);
}
}
}
$("#showmapview").click(function() {
overlaysClear();
$('#mapeach').attr('checked', false);
});
$('#mapeach').change(function() {
if( $('#mapeach').attr("checked")) {
overlaysShow();
}
else {
overlaysClear();
}
});
cmarkers();
google.maps.event.addDomListener(window, 'load', initialize);
});
var directionsService = new google.maps.DirectionsService();
var markersArray = [];
var arrInfoWindows = null;
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
}
function calcRoute() {
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
var waypts = [];
var checkboxArray = document.getElementById("waypoints");
for (var i = 0; i < checkboxArray.length; i++) {
waypts.push({
location:checkboxArray[i].value,
stopover:true
});
}
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: optimize,
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
var route = response.routes[0];
}
});
};
function cmarkers() {
$.getJSON( "/mapeach.js", {}, function( data ) {
$.each( data, function( i, item ) {
var loc = item.mainlocation;
$("#markers").append('<li>' + loc.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+loc.latitude, +loc.longitude),
map: map,
title: loc.nickname,
});
markersArray.push(marker);
var infowindow = new google.maps.InfoWindow({
content: '<a class="clink" href="/spots/'+ loc.id +'/'+ loc.nickname +'" target="_blank">'+ loc.nickname +'</a>'
});
google.maps.event.addListener(marker, 'click', function() {
if (arrInfoWindows != null) {
arrInfoWindows.close();
}
infowindow.open(map,marker);
arrInfoWindows = infowindow;
});
});
});
};
</script>
The mapeach.js file is formatted as below:
[{"mainlocation":{"latitude":"40.706352","nickname":"First Location","id":100000,"longitude":"-73.987650"}},{"mainlocation":{"latitude":"34.061148","nickname":"Second Location","id":100001,"longitude":"-118.273067"}}]

I was able to solve this problem by moving the cmarkers code inside the initialize. I think that the javascript wasn't making clear that the map variable in the initialize was also the map variable in the cmarkers function (sorry if the language isn't precise; I'm not great in js). See below:
function initialize() {
var rendererOptions = {
draggable: true,
panel:document.getElementById('directions_panel')
};
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
var mapOptions = {
zoom: 6,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
directionsDisplay.setMap(map);
cmarkers();
function cmarkers() {
$.getJSON( "/mapeach.js", {}, function( data ) {
$.each( data, function( i, item ) {
var loc = item.mainlocation;
$("#markers").append('<li>' + loc.nickname + '</li>');
var marker = new google.maps.Marker({
position: new google.maps.LatLng(+loc.latitude, +loc.longitude),
map: map,
title: loc.nickname,
});
markersArray.push(marker);
var infowindow = new google.maps.InfoWindow({
content: '<a class="clink" href="/spots/'+ loc.id +'/'+ loc.nickname +'" target="_blank">'+ loc.nickname +'</a>'
});
google.maps.event.addListener(marker, 'click', function() {
if (arrInfoWindows != null) {
arrInfoWindows.close();
}
infowindow.open(map,marker);
arrInfoWindows = infowindow;
});
});
});
};
Special credit to this post for giving me the idea: can't see google marker

Related

Google Map API is Extremely Slow

So I'm setting up a dynamic Google map on all of the pages on the site to show the locations you can see on every page to help users understand the locations.
It works, but works EXTREMELY slow, so slow that if it has about 40+ it can take around 1 minute to load the map and if it's more locations than that on a page it just get stuck and does not load the map.
Here is a link to see the map:
http://www.exchange-currency.org/wakefield/
And Here's the code as it is on the website, you can also see the code with view source but note the addresses are from a string with php, you can see the output on the view source of the page.
<script type="text/javascript" src="http://maps.google.com/maps/api/js?q=<?php the_title(); ?>&key=AIzaSyDeyknfWm0qmejgXZh_VXihNcHbidewODQ"></script>
<script type="text/javascript">
var delay = 10;
var infowindow = new google.maps.InfoWindow();
var latlng = new google.maps.LatLng();
var mapOptions = {
zoom: 4,
center: latlng,
scrollwheel: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var bounds = new google.maps.LatLngBounds();
function geocodeAddress(address, next) {
geocoder.geocode({address:address}, function (results,status)
{
if (status == google.maps.GeocoderStatus.OK) {
var p = results[0].geometry.location;
var lat=p.lat();
var lng=p.lng();
createMarker(address,lat,lng);
}
else {
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
nextAddress--;
delay++;
} else {
}
}
next();
}
);
}
function createMarker(add,lat,lng) {
var contentString = add;
var marker = new google.maps.Marker({
position: new google.maps.LatLng(lat,lng),
map: map,
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
bounds.extend(marker.position);
}
var locations = [<?php echo $locationAddresses; ?>];
var nextAddress = 0;
function theNext() {
if (nextAddress < locations.length) {
setTimeout('geocodeAddress("'+locations[nextAddress]+'",theNext)', delay);
nextAddress++;
} else {
map.fitBounds(bounds);
}
}
theNext();
</script>
What can I do to make it work in a normal speed so its actually usable?
Here's a link to a page with more locations so you'll see what I'm talking about:
http://www.exchange-currency.org/montreal/
Thanks!
Edit:
Also if there is a way to make it load async and with clusters instead of multiple markers that would be great, can't seem to get it figured out =/

How to show geolocated tweets on a map

I have been playing around with the twitter API getting random tweets or even geo tagged tweets and also with the google maps API. However I want to combine this two and try and show geo tagged tweets on a google map. Here is my code for getting the geo tagged Tweets which work fine.
var geo = (geo.coordinates[0], geo.coordinates[1])
//var geo = (34.052234, -118.243685)
client.get('search/tweets', { q:string.teamname, geocode: geo, count: 5},
function searchTweets(err, data, response) {
for(var index in data.statuses){
var tweet = data.statuses[index];
console.log(tweet.text);
console.log(tweet.geo.coordinates)
}
});
On a different file, I generated a map based on Longitude and Latitude, and I had the understanding that once I had retrieved the coordinates for the tweets, I could represent the tweets on a Google Map in the same way. However, my code is not working. My question is, how would I combine both pieces of code to generate a map which is marked with geo located Tweets?
function initialize() {
var myLatlng = new google.maps.LatLng(geo.coordinates[0], geo.coordinates[1]);
var mapOptions = {
center: myLatlng
zoom: 10,
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Tweet});
var infowindow = new google.maps.InfoWindow({
content: 'Geo tagged Tweet',
maxWidth:200 });
infowindow.open(map,marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker); });
}
google.maps.event.addDomListener(window, 'load', initialize);
I would do something like this (untested - I'm just writing down some thoughts).
1) You should strip down init so that it just contains the map set up. Ensure map is declared outside of the function, and include a call to the function that fetches your data using the lat/lng data.
var map;
function initialize() {
var lat = geo.coordinates[0];
var lng = geo.coordinates[1]
var myLatlng = new google.maps.LatLng(lat, lng);
var mapOptions = { center: myLatlng, zoom: 10 }
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
getData(lat, lng, processData);
}
2) You wrap your data fetching code in a new function declaration, which accepts lat/lng data, and a callback.
function getData(lat, lng, callback) {
client.get('search/tweets', { q:string.teamname, geocode: geo, count: 5},
function searchTweets(err, data, response) {
callback(data.statuses);
}
)
};
3) Process the tweet information. For each tweet create a marker (add the marker to an array of markers) and update the map
function processData(data) {
var markers = [];
for (var i = 0, l = data.length; i < l; i++) {
var marker = new google.maps.Marker({
id: i,
position: myLatlng(data[i].geo.coordinates[0], data[i].geo.coordinates[1),
map: map,
title: "Tweet"
});
markers.push(marker);
var infowindow = new google.maps.InfoWindow({
content: data[i].text,
maxWidth: 200
});
infowindow.open(map, marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
}
}

Google map markers overlapping and not visible [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I have trouble with my google map script where the markers on a same location overlapped and not visible to user.
I tried to edit my script using OverlappingMarkerSpiderfier available in this link https://github.com/jawj/OverlappingMarkerSpiderfier. But overlapping issue exist.No improvement occured.
<script type="text/javascript">
var geocoder;
var map;
// initializing the map
function initialize()
{
// define map center
var latlng = new google.maps.LatLng(40.44694705960048,-101.953125);
// define map options
var myOptions =
{
zoom: 3,
center: latlng,
mapTypeId: google.maps.MapTypeId.MAP,
scaleControl: true,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.SMALL
},
mapTypeControl: false,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
};
// initialize map
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// add event listener for when a user clicks on the map
google.maps.event.addListener(map, 'click', function(event) {
findAddress(event.latLng);
});
}
// finds the address for the given location
function findAddress(loc)
{
geocoder = new google.maps.Geocoder();
if (geocoder)
{
geocoder.geocode({'latLng': loc}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
if (results[0])
{
address = results[0].formatted_address;
// fill in the results in the form
document.getElementById('lat').value = loc.lat();
document.getElementById('long').value = loc.lng();
document.getElementById('address').value = address;
}
}
else
{
alert("Geocoder failed due to: " + status);
}
});
}
}
// initialize the array of markers
var markers = new Array();
// the function that adds the markers to the map
function addMarkers()
{
// get the values for the markers from the hidden elements in the form
var lats = document.getElementById('lats').value;
var lngs = document.getElementById('lngs').value;
var addresses = document.getElementById('addresses').value;
var names = document.getElementById('names').value;
var descrs = document.getElementById('descrs').value;
var photos = document.getElementById('photos').value;
var user_names = document.getElementById('user_names').value;
var user_locs = document.getElementById('user_locs').value;
var las = lats.split(";;")
var lgs = lngs.split(";;")
var ads = addresses.split(";;")
var nms = names.split(";;")
var dss = descrs.split(";;")
var phs = photos.split(";;")
var usrn = user_names.split(";;")
var usrl = user_locs.split(";;")
// for every location, create a new marker and infowindow for it
for (i=0; i<las.length; i++)
{
if (las[i] != "")
{
// add marker
var loc = new google.maps.LatLng(las[i],lgs[i]);
var marker = new google.maps.Marker({
position: loc,
map: window.map,
title: nms[i]
});
markers[i] = marker;
var contentString = [
'<div id="tabs">',
'<div id="tab-1">',
'<p><span>'+nms[i]+'</span></p>',
'<p><img src="./photos/'+phs[i]+'"/></p>'+
'</div>',
'<div id="tab-3">',
'<p><img src="images/b-line.jpg"/></p>',
'</div>',
'</div>'
].join('');
var infowindow = new google.maps.InfoWindow;
bindInfoWindow(marker, window.map, infowindow, contentString);
}
}
}
// make conection between infowindow and marker (the infowindw shows up when the user goes with the mouse over the marker)
function bindInfoWindow(marker, map, infoWindow, contentString)
{
google.maps.event.addListener(marker, 'mouseover', function() {
map.setCenter(marker.getPosition());
infoWindow.setContent(contentString);
infoWindow.open(map, marker);
$("#tabs").tabs();
});
}
// highlighting a marker
// make the marker show on top of the others
// change the selected markers icon
function highlightMarker(index)
{
// change zindex and icon
for (i=0; i<markers.length; i++)
{
if (i == index)
{
markers[i].setZIndex(10);
markers[i].setIcon('http://www.google.com/mapfiles/arrow.png');
}
else
{
markers[i].setZIndex(2);
markers[i].setIcon('http://www.google.com/mapfiles/marker.png');
}
}
}
</script>
Thanks in advance.
Refer OverlappingMarkerSpiderfier and this

How to use an existing marker for Google Maps API directionService instead of defining a new one?

I'm using Google Maps API to show directions to a location.
On page load, I set a marker on the map: (FYI: I haven't included the coordinates, but you can assume they are defined)
var destination = [xxx, yyy, 11, xxx, yyy]; //x-coord,y-coord,zoom,x-center,x-center
var dublin = [xxx, yyy, 11, xxx, yyy]; //x-coord,y-coord,zoom,x-center,x-center
var directionsService = new google.maps.DirectionsService();
var directionsDublin;
function initialize() {
directionsDublin = new google.maps.DirectionsRenderer();
var centerMap = new google.maps.LatLng(destination[3],destination[4]);
map = new google.maps.Map(document.getElementById('map-canvas'), {
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: centerMap,
zoom: destination[2]
});
marker1 = new google.maps.Marker({
position: new google.maps.LatLng(destination[0], destination[1]),
map: map
});
marker1.setAnimation(google.maps.Animation.DROP);
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
So the code above displays the map with a marker on it.
I now have a button #tNorth. Clicking it will show a route from a defined location. Clicking again will remove the route and return to the original view.
$(document).ready(function() {
$( "#tNorth" ).on( "click", function() {
if ($("#north").css('display') != 'none') {
//set zoom and center
map.setZoom(destination[2]);
map.setCenter(new google.maps.LatLng(destination[3], destination[4]));
//remove the route
directionsDublin.setMap(null);
//remove the text
$("#north").css('display':'none');
}
else {
//create travel route
var request2 = {
origin: new google.maps.LatLng(dublin[0], dublin[1]),
destination: new google.maps.LatLng(destination[0], destination[1]),
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
//display route on map
directionsDublin.setMap(map);
directionsService.route(request2, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDublin.setDirections(result);
}
});
//add the text
$("#north").css('display':'block');
}
});
});
This is my first use of the Maps API so I'm pretty happy!!
However, when the route is displayed, it places 2 new markers on the page. Since the destination marker is already on the page, it gets overlayed by the new marker.
Is there a way for me to, instead of defining destination: new google.maps.LatLng(destination[0], destination[1]), that I could instead define something like destination: marker1??
It would be nicer than displaying two markers over each other...
Use {suppressMarkers:true} in the DirectionRendererOptions to prevent the DirectionsRenderer from adding markers to the map (it will still show the route)
directionsDublin = new google.maps.DirectionsRenderer({suppressMarkers:true});

How do I get more results from Google Places / Maps

I am using google maps and I am trying out places API, but something makes me wonder...
If you load maps.google.com and go to Kuala Lumpur, then type "food" in the search-box, you will see hundreds of restaurants on the map. I would like to get these into my own maps.
Using the Places API, I have pretty much copied their example code:
function initialize() {
var plat = 3.15;
var plong = 101.7;
var ppos = new google.maps.LatLng(plat, plong);
var mapOptions = {
mapTypeId: google.maps.MapTypeId.ROADMAP,
draggable: false,
zoom: 10,
center: ppos
};
map = new google.maps.Map(document.getElementById("mapcanvas"), mapOptions);
var request = {
location: ppos,
radius: '10000'
};
infowindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
service.search(request, callback);
}
function callback(results, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: place.icon
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent("<b>" + place.name + "</b><br/>" + place.vicinity);
infowindow.open(map, this);
});
}
When I execute this code, I do get results, but only very few and only major locations like a few malls and museums. So, How do I get all that beautiful data, that I see on Google's own map?
So it turned out there were a number of problems:
Categorization is broken in Inodesia, so using keyword instead solved the problem, as in:
var request= {
location: ppos,
radius: 10000,
keyword: 'restaurant' }
keyword takes a string rather than an array, and radius takes a number rather than a string. You can see a summary of the types for the request here: http://code.google.com/apis/maps/documentation/javascript/reference.html#PlaceSearchRequest

Categories

Resources