Google forEach map.data feature not called - json

I am trying to load a GeoJSON to the google maps javascript api and then process the GeoJSON by calling map.data.forEach . I cant get the map.data.forEach function to work it seems that it is never called.
The GeoJSON gets loaded fine and is displayed on my map.
Any suggestions why map.data.forEach would not work here?
Here is my code:
var myMap;
function initialize() {
// Create a simple map.
myMap = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 8,
center: {
lat: 48.2081743,
lng: 16.3738189
}
});
}
function calculate(map) {
console.log("calculating")
map.data.forEach(function (feature) {
console.log("tester");
});
console.log("end calculating");
}
function loadGeoJson(map) {
map.data.loadGeoJson('mini.json');
}
google.maps.event.addDomListener(window, 'load', function () {
initialize();
loadGeoJson(myMap);
calculate(myMap);
});

This is caused by javascripts asynchronous nature. When you have the code
loadGeoJson(myMap);
calculate(myMap);
and loadGeoJson loads an external resource, calculate will most likely be executed before loadGeoJson has finished. It is very easy to reproduce your problem.
Unfortunately there is no callback opportunity in google.maps.Data::loadGeoJson, but if you wrap the call of calculate into a small setTimeout, then you should be good :
loadGeoJson(myMap);
setTimeout(function() {
calculate(myMap);
}, 500);
see a fiddle with your code from above -> http://jsfiddle.net/SAS6Q/

You can also use jQuery and Ajax to load your JSON synchronously to avoid setting time delays:
function loadGeoJson(map) {
$.ajax({
url: mini.json,
dataType: 'json',
async: false,
success: function(data)
{var features = map.data.addGeoJson(data);}
});
}

Related

Determine when drawing of Geojson is complete in Google Maps API

Is there an event that gets fired when drawing of all features have completed when using the loadGeoJson() method in Google Maps API?
I read that you can listen for "idle" state of the map, but it seems like the map is considered idle when the load is complete, but before features are drawn.
see fiddle below:
https://jsfiddle.net/z3tu0epb/
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: new google.maps.LatLng(40.755690, -73.975938)
});
// Load GeoJSON.
map.data.loadGeoJson(
'https://services5.arcgis.com/GfwWNkhOj9bNBqoJ/arcgis/rest/services/nybb/FeatureServer/0/query?where=1=1&outFields=*&geometryPrecision=8&outSR=4326&f=geojson');
google.maps.event.addListenerOnce(map, 'idle', function() {
alert("map is idle");
});
}
I also know about the addFeature() listener which gets fired when any feature is added to the map, but I need the alert() to run after all the features are added to the map.
Thanks,
I'm afraid there is no feasible way to capture "after drawing all features" event for Data layer. It could be possible if the Data layer had exposed the instance of Drawing manager that is used internally. In this case you could listen to the overlaycomplete event
https://developers.google.com/maps/documentation/javascript/reference#OverlayCompleteEvent
But the Data layer doesn't expose its Drawing manager instance publicly, so you cannot add a listener.
https://developers.google.com/maps/documentation/javascript/reference#Data
The unique thing that you can do is to figure out when all features were loaded (added to collection). In this case you can use a callback function of loadGeoJson(url:string, options?:Data.GeoJsonOptions, callback?:function(Array<Data.Feature>))
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: new google.maps.LatLng(40.755690, -73.975938)
});
// Load GeoJSON.
map.data.loadGeoJson(
'https://services5.arcgis.com/GfwWNkhOj9bNBqoJ/arcgis/rest/services/nybb/FeatureServer/0/query?where=1=1&outFields=*&geometryPrecision=8&outSR=4326&f=geojson',
{},
function(features) {
alert("Loaded " + features.length + " features");
});
google.maps.event.addListenerOnce(map, 'idle', function() {
alert("map is idle");
});
}
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap">
</script>
Also, feel free to file a feature request for such event in the Google issue tracker

Meteor google maps javascript api

how would one go about calling meteor method from inside GoogleMaps.ready callback? I am using dburles:google-maps package.
On the client
GoogleMaps.ready('eventsmap', function(map) {
google.maps.event.addListener(map.instance, 'click', function(event) {
Markers.insert({lat: event.latLng.lat(), lng: event.latLng.lng()});
});
...
I tried following:
GoogleMaps.ready('eventsmap', function(map) {
google.maps.event.addListener(map.instance, 'click', function(event) {
var lat = event.latLng.lat();
var lng = event.latLng.lng();
Meteor.call("insertMarker", lat, lng, function(error, results) {
if(error) {
console.log(error.reason);
} else {
console.log(results);
}
});
});
...
On the server I have "insertMarker" method which will insert marker into Markers collection.
But got event is not defined exception. Any idea? Thank you.
Sorry guys, I just wrapped the method call inside if(event){...} conditional. It needed something to trigger the call. It works now, missed that one xD

ionic not rendering google maps on first load

I have an app that is a welcome/sign in screen and after you sign it you are taken to a tab screen with four tabs in it, the first tab of which shows a google map.
Upon first sign in the page does not display it's self but upon refresh of the page the map show's up gracefully as it was expected to do the first time. This happens EVERY time but I only get one javascript error.
error
Uncaught Error: can't load XRegExp twice in the same frame(anonymous function) # xregexp-min.js:2
code
function initialize() {
var mapOptions = {
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(
document.getElementById("map"),
mapOptions
);
var geocoder = new google.maps.Geocoder();
$scope.map = map;
$scope.centerOnMe();
}
google.maps.event.addDomListener(window, 'load', initialize);
$scope.centerOnMe = function() {
if(!$scope.map) {
return;
}
$scope.loading = $ionicLoading.show({
content: 'Getting current location...',
showBackdrop: false
});
// get user location
$cordovaGeolocation
.getCurrentPosition({
timeout:10000,
enableHighAccuracy:true
})
.then(function(position) {
$ionicLoading.hide();
// we found the position
$scope.map.setCenter(
new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude
)
);
}, function(e) {
$ionicLoading.hide();
console.log(e);
alert("Uh oh, we can't find your position! Is your GPS enabled?\n\n" + e);
});
};
edit
This is my latest javascript error, after replacing the google init with the ionic init. I understand what's happening but I don't know where I should move that function declaration to. I moved it inside the init but it still didn't work. Should I set a timeout?
TypeError: $scope.loadLocations is not a function
at initialize (controllers.js:179)
at Object.ionic.Platform.ready (ionic.bundle.js:2120)
at new <anonymous> (controllers.js:182)
at invoke (ionic.bundle.js:12468)
at Object.instantiate (ionic.bundle.js:12476)
at ionic.bundle.js:16745
at IonicModule.controller.self.appendViewElement (ionic.bundle.js:47716)
at Object.IonicModule.factory.ionicViewSwitcher.create.switcher.render (ionic.bundle.js:45973)
at Object.IonicModule.factory.ionicViewSwitcher.create.switcher.init (ionic.bundle.js:45893)
at IonicModule.controller.self.render (ionic.bundle.js:47590)
You don't need $scope.centerOnMe(); in initialize. If you do then compilation is inconsistent; refer to the examples and you will understand.
Also, ionic doesn't work well with DOM in certain cases.
Load map with $scope.init inside the container instead of function initialize().
This answer explains it in detail.
Another way to do it is by replacing google.maps.event.addDomListener(window, 'load', initialize); with ionic.Platform.ready(initialize);. Example here.

Adding custom icons with Google Maps using JSON

I can't get a custom icon to display using this code below. It just defaults to the default Google maps marker.
Any ideas where I'm going wrong?
$(function() {
$('#map_canvas').gmap({
'center':new google.maps.LatLng(54.5,-4.0),
'zoom':6,
'streetViewControl': false,
'callback':
function() {
setInterval( function() {
$.getJSON( 'URL/data_sets/json/sfuk47.php?'+ new Date().getTime(), 'category=activity', function(data) {
$.each( data.markers, function(i, m) {
$('#map_canvas').gmap(
'addMarker',{
'position': new google.maps.LatLng(m.lat, m.lng) });
});
});
}, 5000);
}
});
});
setInterval( function() {
$.ajax({
url:'URL/data_sets/json/sfuk47.php',
success: function(data) {
if (data == "refresh"){
window.location.reload();
}
}
});
}, 600000);
The JSON
{"markers":[
{"lat":59.889,"lng":1.249,"icon":"URL/icons/gl_icons/Red.png"},{"lat":59.892,"lng":1.235,"icon":"URL/icons/gl_icons/Red.png"},{"lat":56.778,"lng":-5.702,"icon":"URL/icons/gl_icons/Red.png"},{"lat":49.534,"lng":-1.814,"icon":"URL/icons/gl_icons/Red.png"},{"lat":56.608,"lng":-8.324,"icon":"URL/icons/gl_icons/Red.png"},{"lat":49.286,"lng":-2.183,"icon":"URL/icons/gl_icons/Red.png"},{"lat":49.289,"lng":-2.192,"icon":"URL/icons/gl_icons/Red.png"},{"lat":59.051,"lng":-7.525,"icon":"URL/icons/gl_icons/Red.png"},{"lat":58.965,"lng":-7.439,"icon":"URL/icons/gl_icons/Red.png"},{"lat":57.531,"lng":-6.895,"icon":"URL/icons/gl_icons/Red.png"},
{"lat":56.895,"lng":-6.372,"icon":"URL/icons/gl_icons/Red.png"}]}
Many thanks,
At first glance you're not setting the icon in the markers call. Try doing:
'addMarker',{
'position': new google.maps.LatLng(m.lat, m.lng),
'icon': m.icon });
But be aware you appear to be using API v2 which is deprecated.
Some relevant examples for API V3.

jQuery executes before Google map loads: "map is undefined"

Aside from jQuery and Google Maps, I have two scripts included in the head of my page:
<script src="js/map.js" type="text/javascript"></script>
<script src="js/site.js" type="text/javascript"></script>
map.js contains the code to initialize my map and also have the following function to place a marker on it:
function placeMarker(marker){
clearLocations();
var latlng = new google.maps.LatLng(
parseFloat(marker.lat),
parseFloat(marker.lng)
);
var marker = createMarker(latlng);
map.setZoom(14);
var latLng = marker.getPosition();
map.setCenter(latLng);
}
When I call placeMarker inside $(document).ready() in site.js, I get the error, 'map is undefined'. However when I call another function in site.js that executes when a button is clicked, placeMarker runs in its callback without a problem:
$.ajax({
url: 'ajax/json.php',
dataType: 'json',
data: 'search_string='+inpMapSearch+'&country='+Country,
success: function(data) {
console.log(data);
placeMarker(data);
}
});
Does this mean that the placeMarker function call inside $(document).ready() is trying to execute before the map is initialized? How can I run placeMarker after the map is initialized?
=== EDIT ===
As per request here is the code that initializes the map:
google.maps.event.addDomListener(window, 'load', load);
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(18.735693,-70.162651),
zoom: 8,
mapTypeId: 'roadmap',
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
});
}
Because the window load event fires after the document.ready. Hence your map is initialized after the document.ready. You could instead wrap your other code in the $(window).load
$(window).load(function(){
your code here
});