I'm unsure how to explain this properly, but I basically want to display markers via Google API on a map and have a link on them to directions to that location. However, currently it only works if the user allows their location to be tracked.
What I want to do is to have basically those markers in both situations, where user does and does not allow their location to be tracked, but just the link would be changed.
So if the user allows their location to be tracked, the link would be
var reittiohjeet = "https://www.google.fi/maps/dir/"+pos+"/"+osoite;
And if the user rejects their location to be tracked, the link would be
var reittiohjeet2 = "https://www.google.fi/maps/dir/current+location/"+osoite;
I tried creating alternative function that would be ran in the if(navigator.geolocation)'s else clause, but that didn't seem to do anything at all.
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(60.174,24.927),
zoom: 8
};
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
// Luo marker
var image = 'user-location.png';
var userMarker = new google.maps.Marker({
position: pos,
map: map,
icon: image
});
map.setCenter(pos);
setMarkers(map, shops, pos);
}, function() {
handleNoGeolocation(true);
});
} else {
handleNoGeolocation(false);
}
}
function setMarkers(map, locations, pos) {
for (var i = 0; i < locations.length; i++) {
var shop = locations[i];
var myLatLng = new google.maps.LatLng(shop[1], shop[2]);
var nimi = shop[0];
var osoite = shop[5];
var puhelinnumero = shop[3];
var verkkosivu = shop[4];
var reittiohjeet = "https://www.google.fi/maps/dir/"+pos+"/"+osoite;
var content = "<div class='content'><h3>"+nimi+"</h3><strong>Osoite:</strong> "+osoite+"<br /><strong>Puhelinnumero:</strong> "+puhelinnumero+"<br /><strong>Verkkosivu:</strong> <a href='"+verkkosivu+"' target='_blank'>"+verkkosivu+"</a><br /><br /><a href='"+reittiohjeet+"'>Reittiohjeet</a></div>";
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: shop[0]
});
var infowindow = new google.maps.InfoWindow()
google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){
return function() {
infowindow.setContent(content);
infowindow.open(map,marker);
};
})(marker,content,infowindow));
}
}
The statement in the else-clause will only be executed when the browser doesn't support geolocation.
When the user denies access the function defined as 2nd argument of getCurrentPosition will be executed.
Note: in Firefox this will not work as expected, see: Firefox 11 and GeoLocation denial callback
Related
Hello fellow Stackoverflow members.
I have offered to help out our local communities emergency volunteer group with an improved alert map for notifying members of incidents close by to our town.
I have been using the google maps api, along with the google places api.
I have managed to bring in their news alert JSON data, match it with their custom icons, and display it on the map successfully. However I am now struggling to get the places searchBox to update the map based on the address users are entering into the search.
NB: The search is auto-completing fine, but the map is not updating. Current error is "map.fitBounds is not a function"
My reference link which I have been using to try and get the places search integrated: https://github.com/googlemaps/js-samples/blob/737eb41e78f9cad28e2664b68450676e91424219/dist/samples/places-searchbox/inline.html
I have attached my code below. With a comment where I have added the latest edits to the code for the search function. A fresh perspective would be greatly appreciated.
UPDATE: I have compiled a JSFiddle for easier handling:
https://jsfiddle.net/mcmacca002/zvghd0nu/
Thank you and appreciated.
// BUILD GOOGLE MAPS:
var GoogleMap = {
map: null,
markers: {},
init: function(lat, lng, places) {
var self = this;
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(lat, lng)
};
this.map = new google.maps.Map(document.getElementById('map'), mapOptions);
this.infowindow = new google.maps.InfoWindow({
size: new google.maps.Size(50, 50)
});
// SEARCH STARTS HERE (ALONG WITH ISSUES):
var searchBox = new google.maps.places.SearchBox(document.getElementById('pac-input'));
google.maps.event.addListener(searchBox, 'places_changed', function() {
searchBox.set('map', null);
var places = searchBox.getPlaces();
var bounds = new google.maps.LatLngBounds();
var i, place;
for (i = 0; place = places[i]; i++) {
(function(place) {
var marker = new google.maps.Marker({
position: place.geometry.location
});
marker.bindTo('map', searchBox, 'map');
google.maps.event.addListener(marker, 'map_changed', function() {
if (!this.getMap()) {
this.unbindAll();
}
});
bounds.extend(place.geometry.location);
}(place));
}
map.fitBounds(bounds);
searchBox.set('map', map);
map.setZoom(Math.min(map.getZoom(),12));
});
// END OF SEARCH HERE.
$.each(places, function() {
self.addMarker(this);
});
this.setCenterPoint();
},
// Create map markers
addMarker: function(place) {
var self = this;
var marker = new google.maps.Marker({
position: new google.maps.LatLng(place.coordinate.latitude, place.coordinate.longitude),
map: self.map,
title: place.name,
icon: place.image
});
console.log(place);
// Create information event for each marker
marker.info_window_content = 'TEST'
self.markers[place.id] = marker
google.maps.event.addListener(marker, 'click', function() {
self.infowindow.setContent(marker.info_window_content)
self.infowindow.open(self.map, marker);
});
},
// Update map markers
updateMarkers: function(records) {
var self = this;
$.each(self.markers, function() {
this.setMap(null);
})
$.each(records, function() {
self.markers[this.id].setMap(self.map);
});
//Set map center
if (records.length) self.setCenterPoint();
},
// Set centre point for map
setCenterPoint: function() {
var lat = 0,
lng = 0;
count = 0;
//Calculate approximate center point based on number of JSON entries
for (id in this.markers) {
var m = this.markers[id];
if (m.map) {
lat += m.getPosition().lat();
lng += m.getPosition().lng();
count++;
}
}
if (count > 0) {
this.map.setCenter(new google.maps.LatLng(lat / count, lng / count));
}
}
};
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places"></script>
<input id="pac-input" class="controls" type="text" placeholder="Search Box">
<div class="container" id="map" style="height:900px;"></div>
You have an error, because you have a wrong reference to this. I updated your Jsfiddle here: https://jsfiddle.net/k23auboq/ but I will also show you what went wrong down below.
init: function(lat, lng, places) {
// ...
var searchBox = new google.maps.places.SearchBox(document.getElementById('pac-input'));
google.maps.event.addListener(searchBox, 'places_changed', () => { // if you pass an arrow function here instead, 'this' will be taken from the outer context
searchBox.set('map', null);
var places = searchBox.getPlaces();
var bounds = new google.maps.LatLngBounds();
var i, place;
for (i = 0; place = places[i]; i++) {
var marker = new google.maps.Marker({
position: place.geometry.location
});
marker.bindTo('map', searchBox, 'map');
google.maps.event.addListener(marker, 'map_changed', function() {
if (!this.getMap()) {
this.unbindAll();
}
});
bounds.extend(place.geometry.location);
}
this.map.fitBounds(bounds); // this.map.fitBounds(...) now exists and works
searchBox.set('map', map);
this.map.setZoom(Math.min(map.getZoom(), 12));
});
// ...
},
To simplify it a bit take a look at the following examples:
function Test() {
this.map = 'test map';
this.callbackAction = function (callback) {
callback();
}
this.action = function () {
this.callbackAction(function () { // callback passed as 'function'
console.log(this.map);
});
}
return this;
}
const instance = new Test();
instance.action();
vs
function Test() {
this.map = 'test map';
this.callbackAction = function (callback) {
callback();
}
this.action = function () {
this.callbackAction(() => { // callback passed as 'ARROW function'
console.log(this.map);
});
}
return this;
}
const instance = new Test();
instance.action();
I have updated the answer which was provided above. The answer was technically correct, however using the bounds method will zoom the map down to level 1.
Here is a solution which should work for you. I have not been able to add a pin to the searched location. Hopefully somebody else may be able to help you there as I have only applied what I have learned using leaflet.js which is slightly different to Google maps, and am only still learning Javascript.
var GoogleMap = {
map: null,
markers: {},
init: function(lat, lng, places) {
var self = this;
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(lat, lng),
draggable: true
};
this.map = new google.maps.Map(document.getElementById('map'), mapOptions);
this.infowindow = new google.maps.InfoWindow({
size: new google.maps.Size(10, 10)
});
// SEARCH STARTS HERE:
var searchBox = new google.maps.places.SearchBox(document.getElementById('pac-input'));
google.maps.event.addListener(searchBox, 'places_changed', () => {
searchBox.set('map', null);
var places = searchBox.getPlaces();
var bounds = new google.maps.LatLngBounds();
var i, place;
for (i = 0; place = places[i]; i++) {
var marker = new google.maps.Marker({
title: places.name,
zoom: 4,
position: place.geometry.location
});
marker.bindTo('map', searchBox, 'map');
google.maps.event.addListener(marker, 'map_changed', function() {
if (!this.getMap()) {
this.unbindAll();
}
bounds.extend(place.geometry.location);
});
marker.setPosition(place.geometry.location);
}
// ADDING PANTO FOR RETAINING THE MAP ZOOM LEVEL - INSTEAD OF SETZOOM :D
this.map.panTo(marker.getPosition());
});
// WHICH THEN ENABLES YOU TO REMOVE THIS:
// this.map.fitBounds(bounds);
// searchBox.set('map', map);
// this.map.setZoom(Math.min(map.getZoom(), 12));
// END OF SEARCH HERE.
How to display google map after every x seconds without google map refresh?
1.Markers latLong are coming from database.
2.Allocate that markers on google map.
3.Markers's latLong changes after 30 second.
Problem is google map get refreshed. All I want google map should display without refresh with updated LatLong.
Here is my code.
<script>
function initMap() {
var infowindow = new google.maps.InfoWindow();
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 19.9518684, lng: 73.7354084}
});
var image = '<?php echo $getImagePath; ?>'
for (var o in markers) {
lat = markers[ o ].lat;
lng = markers[ o ].lng;
address = markers[ o ].address;
var my = new google.maps.LatLng(lat, lng);
//console.log(my);
var marker = new google.maps.Marker({
position: my,
map: map,
icon: image,
});
google.maps.event.addListener(marker, 'click', function () {
infowindow.setContent("'" + address + "'");
infowindow.open(map, marker);
});
}
}
</script>
I tried google.maps.event.addDomListener(window, "load", initMap); and window.onload = initMap; but didn't work.
Can any one help me out?
I hope this small rewrite of your code will help you on your way. As it stands, there's a lot of information not present in the question, so I can only guess
// note these are globals because they are set in initMap and used outside of it
var image = '<?php echo $getImagePath; ?>';
var map;
var infowindow;
var markers = [/* some initially loaded markers loaded as if by majick unicorn farts */];
function initMap() {
infowindow = new google.maps.InfoWindow();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: {lat: 19.9518684, lng: 73.7354084}
});
doMarkers(true);
}
function doMarkers(firstLoad) {
markers.forEach(marker => {
var lat = marker.lat;
var lng = marker.lng;
marker.my = new google.maps.LatLng(lat, lng);
if (firstLoad) { // marker has no marker the first time because it's not on a map yet
marker.marker = new google.maps.Marker({
position: marker.my,
map: map,
icon: image,
});
google.maps.event.addListener(marker.marker, 'click', function () {
infowindow.setContent("'" + marker.address + "'");
infowindow.open(map, marker.marker);
});
} else { // move existing marker
marker.marker.setPosition(marker.my);
}
}
}
function magicallyFindAndUpdateMarkerDataUsingUnicornFarts(marker) {
// find corresponding marker in markers array
// update lat, lng and address
}
function doSomeAjaxToGetNewMarkerPositionsAndCallCallback(cb) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'someURI');
xhr.onload = function() {
var data = JSON.parse(xhr.responseText);
data.forEach(function(marker) {
magicallyFindAndUpdateMarkerDataUsingUnicornFarts(marker);
});
cb()
}
xhr.send();
}
setInterval(function () {
doSomeAjaxToGetNewMarkerPositionsAndCallCallback(function() {
doMarkers(false);
});
}, 30000);
Of course, I can't see how markers are loaded (into markers in your code), nor can I tell you what doSomeAjaxToGetNewMarkerPositionsAndCallCallback or magicallyFindAndUpdateMarkerDataUsingUnicornFarts should be, because you haven't shown any code regarding markers at all
Trying to get Google Places API to notice my location and apply the functions below. Very new to this and not sure what I am doing wrong below as the API and all the functions works initially, but after I'm asked for my location, it shows where I am but nothing else works/aren't working together.
Cordova Geolocation plugin I added to my ionic app:
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-geolocation.git
App.js
app.controller("MapController", function($scope, $ionicLoading) {
var map;
var infowindow;
var request;
var service;
var markers = [];
google.maps.event.addDomListener(window, 'load', function() {
var center = new google.maps.LatLng(42.3625441, -71.0864435);
var mapOptions = {
center:center,
zoom:16
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
navigator.geolocation.getCurrentPosition(function(pos) {
map.setCenter(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
var myLocation = new google.maps.Marker({
position: new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude),
map: map,
title: "My Location"
});
});
$scope.map = map;
request = {
location: center,
radius: 1650,
types: ['bakery', 'bar']
};
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);
});
}
});
});
When you get the position, you update the map's location, but you don't run a new Nearby Search.
So I think you want to call service.nearbySearch(...) in the getCurrentPosition callback.
You may also want to have your nearbySearch callback keep an array of the markers created via createMarker, so you can remove them when you run a new search (e.g. by calling marker.setMap(null) on each old marker).
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);
});
}
}
I am using google map which shows marker with information window...in which i display address but i want to show the name as well in information window when a marker is clicked. Any help will be highly appreciated.
function load()
{
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(-37.816667,144.966667), 10);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
var geocoder = new GClientGeocoder();
GDownloadUrl("shops.xml", function(data) {
var xml = GXml.parse(data);
shop = xml.documentElement.getElementsByTagName("shop");
for (var i = 0; i < shop.length; i++) {
var name= shop[i].getElementsByTagName("name");
name = name[0].childNodes[0].nodeValue;
var address= shop[i].getElementsByTagName("address");
address = address[0].childNodes[0].nodeValue;
geocoder.getLocations(address, addToMap);}
}); }
function addToMap(response)
{
place = response.Placemark[0];
point = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
function createMarker(point,address)
{
var marker = new GMarker(point);
GEvent.addListener(marker, "click", function()
{
map.openInfoWindowHtml(point, address);
});
return marker;
}
map.addOverlay(createMarker(point, response.name));
}
Use API v3 and in your marker setup set the tite of the marker to "name" then after adding the click listener you will be able to refer to the title of the clicked marker - if that is what you wanted.
//get your point and name whatever way you plan to do it
...
function createMarker(point,name){
var marker = new google.maps.Marker({
position: point,
map: map,
title: name,
}) ;
var content='Whatever info you want plus'+name;
var infowindow = new google.maps.InfoWindow({
content: content
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
return marker;
}
Please check the closures as I wrote it just now.
K