Meteor Js Google Maps not rendered - javascript

I have this event from myGroup Template:
'click #details': function(e){
// Prevent default actions
e.preventDefault();
// Get groupid
var groupId = e.target.name
group = Groups.findOne(groupId)
lat = group.destination.location.lat
lon = group.destination.location.lon
Session.set('lat', lat);
Session.set('lon', lon);
Router.go('/group/'+groupId);
}
This event, as you can see, create two session variables and then redirect to another Template called groupMap.
I have this code to run when groupMap is rendered:
Template.groupMembers.rendered = function(){
var map;
var infowindow;
var lat = Session.get("lat");
var lon = Session.get("lon");
console.log(lat,lon)
function initialize() {
var location = new google.maps.LatLng(lat, lon);
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: location,
zoom: 15
});
var request = {
location: location,
radius: 500,
types: ['store']
};
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch(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
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
google.maps.event.addDomListener(window, 'load', initialize)
};
It is a simple code that take the previous two variables and then render a map centered in lat and lon, and display some google places markers.
NOTE1: I load the googlemap api on the header
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places"></script>
My problem is: When I click on #details the event work well(create the variables and redirect), after redirect I can see the two variables displayed at the console but the map never render. If I reload the page de map render in blank because the variables disappear and if I change something in the code to trigger the Meteor hot-reload the map will render well.
What can I do to fix this ? (I need to render the map on the 1st load)

The source of your problem lies within the last line of your code:
google.maps.event.addDomListener(window, 'load', initialize)
With this line, you are basically telling your app to initialize the map when the window is loaded. (duh, right?) It's good, when you expect the page to still be loading when calling that statement. But in Meteor, this "windows is loaded" event occurs very few times during your app's runtime: when loading a page of your app "for the first time" on your browser (or pressing F5), and on hot-code reloads.
From that moment on, your app will no longer trigger any more load event on your window (as opposed to multi-pages apps, which "reload" each page as you navigate through them), unless of course you programmatically trigger one in your code.
This is why your map only shows on hot-code reloads. Only then are both your listener active and the window's loaded event being triggered, hence triggering your initialize function.
What you want in your case is to trigger the map every time the template is rendered. To achieve that, what you just need is to call your initialize() function within your rendered hook. Here's an example based on what you have (using the new correct onRendered function):
Template.groupMembers.onRendered(function(){
var map;
var infowindow;
var lat = Session.get("lat");
var lon = Session.get("lon");
console.log(lat,lon)
function initialize() {
var location = new google.maps.LatLng(lat, lon);
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: location,
zoom: 15
});
var request = {
location: location,
radius: 500,
types: ['store']
};
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch(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
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
initialize();
});

Related

Google Places API show schools and stores

Using the Google Maps API with the places library I am able to show nearby schools using the recommended method shown here.
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: pyrmont,
radius: 500,
type: ['store']
}, 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
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
Here's a working fiddle: https://jsfiddle.net/api/post/library/pure/
The problem is that if I also want to show nearby stores as well as schools, everyone seems to recommend simply doing this:
type: ['store', 'school']
While this technically works, the problem is the map just shows a bunch of meaningless default markers with no way of knowing what it what.
So my question is: How can I change the icon for the schools and stores? Ideally I would show a different icon for each different type.
It's no different than adding custom marker in regular map.Only thing is that you need to make api calls separately for each type.So even type: ['store', 'school'] would work and you get results but there is no type specifier in the results to tell whether it's a school or shop .Also you would need to create their separate callbacks for setting their separate icons
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
icon:"http://example.com/icon.png", //<-- only this line is enough for icon
map: map,
position: place.geometry.location
});
go through this for a better understanding
Moreover every result will have a default icon (as icon property), that can also be used
var marker = new google.maps.Marker({
icon:place.icon,
map: map,
position: place.geometry.location
});

JSON Data is not Showing in google map

I have some JSON data which i want to appear on google map. But the thing is its showing nothing. The JSON data will load from a server where the index file is also located. when i try to debug the problems i got some errors that i didn't understood. So, here is my data:
var map, infowindow; ////
var json = $.getJSON( "file.json", function( json ) {
function initialize() {
var mapOptions = {
////
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var bounds = new google.maps.LatLngBounds();
var responses = json.ResponseData;
for(var i = 0; i <= responses.length; i++) {
// Adding a new marker for the object
var position =
new google.maps.LatLng( responses.CoordinateY, responses.CoordinateX ); ////
bounds.extend( position ); ////
var marker = new google.maps.Marker({
position: position, ////
map: map,
draggable: true,
animation: google.maps.Animation.DROP,
title: responses.BuildingName
});
// Adding a new info window for the object
var clicker = addClicker(marker, responses.BuildingName); ////
} map.fitBounds( bounds ); ////
// Adding a new click event listener for the object
function addClicker(marker, content) {
google.maps.event.addListener(marker, 'click', function() {
if (infowindow) {infowindow.close();}
infowindow = new google.maps.InfoWindow({content: content});
infowindow.open(map, marker);
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
});
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB6U22yg_ty9a4LFvJi6E0rYCyGwYt04Xk&callback=json">
</script>
<script src="https:////cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="map-canvas"></div>
the json data file link is JSON DATA
and here is the link of the html file HTML
The thing is i want to show the markers on google map. The json file will be updating all time.
Thanks
The callback in your API load is incorrect. json is not a function.

Uncaught TypeError: Cannot call method 'panTo' of undefined

I'm occasionally seeing a javascript error (Uncaught TypeError: Cannot call method 'panTo' of undefined) when loading my website. My website, for reference, is www.nolofo.com. What is supposed to happen when you load that page is to determine your location and move the map to that location. Sometimes this works just fine, other times it does not. I can't seem to figure out the pattern other than when it doesn't work I see this error message in the javascript log. Perhaps something is not being loaded in the correct order?
<script type="text/javascript">
// Check to see if this browser supports geolocation.
if (navigator.geolocation) {
// This is the location marker that we will be using on the map. Let's store a reference to it here so that it can be updated in several places.
var locationMarker = null;
var myLat = null;
var myLng = null;
// Get the location of the user's browser using the native geolocation service.
navigator.geolocation.getCurrentPosition(
function (position) {
// Check to see if there is already a location. There is a bug in FireFox where this gets invoked more than once with a cached result.
if (locationMarker){
return;
}
// Log that this is the initial position.
console.log( "Initial Position Found" );
// Assign coordinates to global variables
myLat = position.coords.latitude;
myLng = position.coords.longitude;
moveToLocation(myLat, myLng);
}
);
}
// Start the Google Maps implementation
var map;
var markersArray = [];
function initialize() {
var mapOptions = {
zoom: 13,
center: new google.maps.LatLng(40.760779, -111.891047),
mapTypeId: google.maps.MapTypeId.TERRAIN,
scaleControl: true
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
// Add all recent listing markers to map
<?php
foreach ($coordinateArray as $Key => $Value) {
$listingQuery = mysql_query("
SELECT
Listings.Lat,
Listings.Lng,
Listings.Title,
Listings.Type
FROM
Listings
WHERE
Listings.ID='$Key'
");
if (!$listingQuery) {
die('<p>Error executing query (2) with database!<br />'.
'Error: ' . mysql_error() . '</p>');
}
$listingArray = mysql_fetch_array($listingQuery);
$ListingLat = $listingArray["Lat"];
$ListingLng = $listingArray["Lng"];
$ListingTitle = addslashes($listingArray["Title"]);
$ListingType = $listingArray["Type"];
$ListingLatLng = $ListingLat . ", " . $ListingLng;
?>
// Marker
var myLatLng = new google.maps.LatLng(<?=$ListingLatLng?>);
var marker<?=$Key?> = new google.maps.Marker({
position: myLatLng,
map: map,
title: ""
});
iconFile = 'http://maps.google.com/mapfiles/ms/icons/<?=$Value?>-dot.png';
marker<?=$Key?>.setIcon(iconFile);
// Info Window
var infowindow<?=$Key?> = new google.maps.InfoWindow({
content: '<b><?=$ListingType?></b><br /><?=$ListingTitle?>'
});
google.maps.event.addListener(marker<?=$Key?>, 'click', function() {
infowindow<?=$Key?>.open(map, marker<?=$Key?>);
});
<?php } ?>
// Add a click event handler to the map object
google.maps.event.addListener(map, "click", function(event) {
// Place a marker
placeMarker(event.latLng, event.latLng.lat(), event.latLng.lng());
// Display the lat/lng in your form's lat/lng fields
//document.getElementById("lat").value = event.latLng.lat();
//document.getElementById("lng").value = event.latLng.lng();
});
// Add a click event handler to the marker object
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent("Your content here");
infowindow.open(map, this);
});
}
function placeMarker(location, lat, lng) {
// Remove all markers if there are any
deleteOverlays();
var marker = new google.maps.Marker({
position: location,
map: map
});
// Add marker in markers array
markersArray.push(marker);
var contentString = 'New Listing';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map,marker);
google.maps.event.addListener(infowindow, "closeclick", function() {
deleteOverlays(); // removes the marker
});
//map.setCenter(location);
}
// Deletes all markers in the array by removing references to them
function deleteOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
}
}
function moveToLocation(lat, lng) {
var center = new google.maps.LatLng(lat, lng);
map.panTo(center);
}
// The function to trigger the marker click, 'id' is the reference index to the 'markers' array.
function linkClick(id){
google.maps.event.trigger(markersArray[id], 'click');
}
google.maps.event.addDomListener(window, 'load', initialize);
Most likely it's because you're trying to pan the map before the map has been loaded. You run that initial geolocation script as soon as the page is loaded. Sounds like sometimes getCurrentPosition() is faster than the map load, sometimes it's not.
What you can do is run your geolocation stuff after map has been loaded. The very last line in your script is an event listener for when the map has been loaded - you can use it for other bits too.
Wrap the whole first part in a function:
function setupGeoLocator() {
// Check to see if this browser supports geolocation.
if (navigator.geolocation) {
// This is the location marker that we will be using on the map. Let's store a reference to it here so that it can be updated in several places.
var locationMarker = null;
var myLat = null;
var myLng = null;
// Get the location of the user's browser using the native geolocation service.
navigator.geolocation.getCurrentPosition(
function (position) {
// Check to see if there is already a location. There is a bug in FireFox where this gets invoked more than once with a cached result.
if (locationMarker){
return;
}
// Log that this is the initial position.
console.log( "Initial Position Found" );
// Assign coordinates to global variables
myLat = position.coords.latitude;
myLng = position.coords.longitude;
moveToLocation(myLat, myLng);
}
);
}
}
And then call it when the 'load' event fires on the map.
google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addDomListener(window, 'load', setupGeoLocator);

How to add Markers on Google maps v3 API asynchronously?

I've been following the official documentation on how to add markers on the map so far
Nevertheless, I can see only one marker at a time max. If I try to add another one, then it doesn't work (I can't even see the first one).
My process is the following:
I initialize gmaps api:
jQuery(window).ready(function(){
//If we click on Find me Lakes
jQuery("#btnInit").click(initiate_geolocation);
});
function initiate_geolocation() {
if (navigator.geolocation)
{
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyBbfJJVh0jL1X9b7XFDcPuV7nHD1HlfsKs&sensor=true&callback=initialize";
document.body.appendChild(script);
navigator.geolocation.getCurrentPosition(handle_geolocation_query, handle_errors);
}
else
{
yqlgeo.get('visitor', normalize_yql_response);
}
}
Then, I display it on the appropriate div. But when it comes to make the AJAX call, in order to get my locations of the different markers I'd like to display, It just doesn't work properly. Here is the code with a simple map displayed (since that's the only thing working for me so far).
function handle_geolocation_query(position){
var mapOptions = {
zoom: 14,
center: new google.maps.LatLng(position.coords.latitude, position.coords.longitude),
mapTypeId: google.maps.MapTypeId.SATELLITE
}
alert('Lat: ' + position.coords.latitude + ' ' +
'Lon: ' + position.coords.longitude);
$('#map-canvas').slideToggle('slow', function(){
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
});
$.when( getLakes(position.coords.latitude, position.coords.longitude)).done(function(results) {
// InitializeGoogleMaps(results);
if(results)
var data = results.map(function (lake) {
//Check if the lake has any open swims, if not, the button will not be clickable and an alert will pop up
if (lake.available>0)
clickable=true;
else
clickable=false;
return {
name: lake.name,
fishs: lake.fisheryType,
swims: lake.swims,
dist: lake.distance,
lat: lake.latitude,
long: lake.longitude,
id: lake.id,
avail: lake.available,
clickable: clickable,
route: Routing.generate('lake_display', { id: lake.id, lat: position.coords.latitude, lng: position.coords.longitude})
}
});
var template = Handlebars.compile( $('#template').html() );
$('#list').append( template(data) );
} );
};
So I'd like to add markers after the AJAX call. I've set up a function that I should call in the when()
function InitializeGoogleMaps(results) {
};
to display the markers in a foreach loop but nope, can't make it work. It looks like this :
CentralPark = new google.maps.LatLng(37.7699298, -122.4469157);
marker = new google.maps.Marker({
position: location,
map: map
});
Any help would be great !
Thanks
The main issue is that the map variable is declared only in the scope of the anonymous callback on slideToggle. First of all declare at the top-level function scope.
function handle_geolocation_query(position){
var map,
mapOptions = {
zoom: 14,
center: new google.maps.LatLng(position.coords.latitude, position.coords.longitude),
mapTypeId: google.maps.MapTypeId.SATELLITE
}
...
Then change the slideToggle callback to initialise the variable instead of redeclaring:
$('#map-canvas').slideToggle('slow', function(){
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
});
Then you should pass map as a second parameter to your InitializeGoogleMaps function and call it using InitializeGoogleMaps(results, map). See where this gets you and hit me back with any questions.

Problem with my click event on GoogleMaps integration - Pulling data from a JSON file

I have GoogleMaps integrated into my site. I'm having a problem pulling my info from my JSON file into the Info Window when the markers are clicked.
Below is my current code:
/*********** Custom GoogleMaps functions ***********/
if (document.getElementById("events-map")) {
// set json path
var markerFile = '/scripts/json/find-events.json';
// set default map properties
var defaultLatlng = new google.maps.LatLng(41.4925, -99.9018);
// zoom level of the map
var defaultZoom = 4;
// variable for map
var map;
// variable for marker info window
var infowindow;
// List with all marker to check if exist
var markerList = {};
// option for google map object
var myOptions = {
zoom: defaultZoom,
center: defaultLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
/**
* Load Map
*/
function loadMap() {
// create new map make sure a DIV with id myMap exist on page
map = new google.maps.Map(document.getElementById("events-map"), myOptions);
// create new info window for marker detail pop-up
infowindow = new google.maps.InfoWindow();
// load markers
loadMarkers();
}
/**
* Load markers via ajax request from server
*/
function loadMarkers() {
// load marker jSon data
$.getJSON(markerFile, function(data) {
// loop all the markers
$.each(data, function(i, item) {
// add marker to map
loadMarker(item);
});
});
}
/**
* Load marker to map
*/
function loadMarker(makerData) {
// create new marker location
var myLatlng = new google.maps.LatLng(markerData['xCoordinate'], markerData['yCoordinate']);
// create new marker
var marker = new google.maps.Marker({
id: markerData['id'],
map: map,
title: markerData['propertyName'] ,
position: myLatlng
});
// add marker to list used later to get content and additional marker information
markerList[marker.id] = marker;
// add event listener when marker is clicked
// currently the marker data contain a dataurl field this can of course be done different
google.maps.event.addListener(marker, 'click', function() {
// show marker when clicked
showMarker(marker.id);
});
// add event when marker window is closed to reset map location
google.maps.event.addListener(infowindow, 'closeclick', function() {
map.setCenter(defaultLatlng);
map.setZoom(defaultZoom);
});
}
/**
* Show marker info window
*/
function showMarker(markerId) {
// get marker information from marker list
var marker = markerList[markerId];
// check if marker was found
if (marker) {
// get marker detail information from server
$.getJSON(markerFile, function(data) {
// show marker window
infowindow.setContent(data);
infowindow.open(map, marker);
});
} else {
alert('Error marker not found: ' + markerId);
}
}
google.maps.event.addDomListener(window, 'load', loadMap);
}
And here is the info that is contained in my JSON file:
{
"markers":[
{
"id":"1",
"xCoordinate" : 34.048928,
"yCoordinate" : -111.093731,
"propertyName" : "Arizona",
"propertyState" : "AZ",
"propertyPhone" : "777.777.7777",
"propertyEmail" : "test#example.com"
},
{
"id":"2",
"xCoordinate" : 38.582526,
"yCoordinate" : -92.510376,
"propertyName" : "Missouri",
"propertyState" : "MO",
"propertyPhone" : "777.777.7777",
"propertyEmail" : "test#example.com"
}
]
}
In
var marker = ...
$.getJSON(markerFile, function(data) {...marker...}
the function(data) is the callback that is called asynchronously when the result of the respective AJAX call is returned. At that moment the local variable marker is no longer in scope. You should apply a closure over the marker:
$.getJSON(markerFile, function(mapMarker) {
var m = mapMarker; // save the current marker in the closure
return function(data) { // return the required callback ...
// show marker window
infowindow.setContent(data);
infowindow.open(map, m);
} (marker) // ... applied to marker
});
There is a typo in your loadMarker function:
makerData should be markerData

Categories

Resources