Add an info window to each marker when select place in list view - infowindow

// inital Locations
var myLocations = [{
name: "Istanbul",
address: "214 S Highland Ave, Pittsburgh, PA",
latlng: {
lat: 41.008238,
lng: 28.978359
}
}, {
name: "Antalya",
address: "5469 Penn Ave Pittsburgh, PA 15206",
latlng: {
lat: 36.896891,
lng: 30.713323
}
}, {
name: "Ankara",
address: "236 Fifth Ave Pittsburgh, PA 15222",
latlng: {
lat: 39.933363,
lng: 32.859742
}
}, {
name: "Trabzon",
address: "5608 Walnut St Pittsburgh, PA 15232",
latlng: {
lat: 41.002697,
lng: 39.716763
}
}, {
name: "Bursa",
address: "5841 Penn Ave Pittsburgh, PA 15206",
latlng: {
lat: 40.188528,
lng:29.060964
}
},
];
//String to display in info window
//Declare Map variable and markers array
var map;
var infoWindow;
var marker;
//Create Instance of a map from the Google maps api
//Grab the reference to the "map" id to display map
//Set the map options object properties
function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: {
lat: 38.963745,
lng: 35.243322
},
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: true,
mapTypeControlOptions: {
style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
}
});
};
// tells the view model what to do when a change occurs
function mLocation(value) {
this.name = ko.observable(value.name);
this.address = ko.observable(value.address);
this.description = ko.observable(value.description);
this.latlng = ko.observable(value.lat);
};
//ViewModel
function ViewModel() {
var self = this;
self.markers = [];
//Copies the values of initialLocations and stores them in sortedLocations(); observableArray
self.sortedLocations = ko.observableArray(myLocations);
//Adds new markers at each location in the initialLocations Array
self.sortedLocations().forEach(function(location) {
marker = new google.maps.Marker({
position: location.latlng,
map: map,
title: location.name,
icon: 'img/marker.png',
animation: google.maps.Animation.DROP
});
location.marker = marker;
var content = '<div id="iw_container">' +
'<div class="iw_title">' + name + </div>';
//Pushes each marker into the markers array
this.markers.push(marker);
});
//Map info windows to each item in the markers array
self.markers.map(function(info) {
infoWindow = new google.maps.InfoWindow({
content: content
});
//Add click event to each marker to open info window
info.addListener('click', function() {
infoWindow.open(map, this),
info.setAnimation(google.maps.Animation.BOUNCE) //Markers will bounce when clicked
setTimeout(function() {
info.setAnimation(null)
}, 2000); //Change value to null after 2 seconds and stop markers from bouncing
});
});
//Click on item in list view
self.listViewClick = function(loc) {
if (loc.name) {
map.setZoom(15); //Zoom map view
map.panTo(loc.latlng); // Pan to correct marker when list view item is clicked
loc.marker.setAnimation(google.maps.Animation.BOUNCE); // Bounce marker when list view item is clicked
infoWindow.open(map, loc.marker); // Open info window on correct marker when list item is clicked
}
setTimeout(function() {
loc.marker.setAnimation(null); // End animation on marker after 2 seconds
}, 2000);
};
// Stores user input
self.query = ko.observable('');
//Filter through observableArray and filter results using knockouts utils.arrayFilter();
self.search = ko.computed(function() {
return ko.utils.arrayFilter(self.sortedLocations(), function(listResult) {
return listResult.name.toLowerCase().indexOf(self.query().toLowerCase()) >= 0;
});
});
};
$(document).ready(function() {
initMap();
ko.applyBindings(ViewModel());
});
I would like to ask about how to add an info window to a marker in Google Maps. The condition is, I have to create a program with multiple markers on a map. But how I can give a specified info window to each marker when select in each place in the view list?

Related

infobox to pushpin via geocode, close all open infoboxs before opening new infobox

ok, here is my code
const members = [
{name: 'Abc Ijk', order: '646545', duration: '1.20h', createdOn: '02/03/2021 09:00 - 10:00', address: '1221 test Avenue Room 112 Portland OR 97204' },
{name: 'Xyz Opq', order: '646546', duration: '3.00h', createdOn: '02/03/2021 08:00 - 11:00', address: '945 nw street 852 Portland OR 97209' }
];
function loadEmpStatus() {
// var navigationBarMode = Microsoft.Maps.NavigationBarMode;
var map = new Microsoft.Maps.Map(document.getElementById('sdy-fserv-map'), {
/* No need to set credentials if already passed in URL */
// navigationBarMode: navigationBarMode.compact,
// supportedMapTypes: [Microsoft.Maps.MapTypeId.road, Microsoft.Maps.MapTypeId.aerial, Microsoft.Maps.MapTypeId.grayscale, Microsoft.Maps.MapTypeId.canvasLight],
supportedMapTypes: [Microsoft.Maps.MapTypeId.road, Microsoft.Maps.MapTypeId.aerial],
center: new Microsoft.Maps.Location(47.624527, -122.355255),
maxZoom: 11,
minZoom: 5
});
for( let row of members ) {
console.log(row);
doGeocode( map, row );
}
}
function doGeocode( map, data ) {
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
var searchManager = new Microsoft.Maps.Search.SearchManager(map);
var requestOptions = {
bounds: map.getBounds(),
where: data.address,
callback: function (answer, userData) {
map.setView({ bounds: answer.results[0].bestView });
var pushpin = new Microsoft.Maps.Pushpin(answer.results[0].location, {
icon: 'https://www.bingmapsportal.com/Content/images/poi_custom.png',
});
// map.entities.push(new Microsoft.Maps.Pushpin(answer.results[0].location));
map.entities.push(pushpin);
var infobox = new Microsoft.Maps.Infobox(answer.results[0].location, {
title: data.name,
description: data.address, visible: false,
actions: [
{ label: 'Handler1', eventHandler: function () { console.log('Handler1'); } },
{ label: 'Handler2', eventHandler: function () { console.log('Handler2'); } },
]
});
infobox.setMap(map);
Microsoft.Maps.Events.addHandler(pushpin, 'click', function () {
infobox.setOptions({ visible: true });
});
map.entities.push(pushpin);/**/
}
};
searchManager.geocode(requestOptions);
});
}
it runs smoothly and I have geocoded pushpins with infoboxes attached and showing up nicely.
But I am failing to figure out how to make all opened infoboxes close before opening new infobox on pushpin click event.
Please help..
I highly recommend creating a single infobox and reusing it as outline in this document: https://learn.microsoft.com/en-us/bingmaps/v8-web-control/map-control-concepts/infoboxes/multiple-pushpins-and-infoboxes

How to add predefined places/markers to Leaflet Geocoder

I am using Leaflet Map with geocoder (ESRI) and Routing Machine.
I have added two markers, let's say my home and my work
var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map)
.bindPopup("work").openPopup();
var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map)
.bindPopup("home").openPopup();
Here is an example fiddle:
https://jsfiddle.net/21nmk8so/1/
How can I add this markers/point as a predefined places for ControlGeocoder?
I want to use them in search and use as a start point / end point for route calculation.
Another example for the same question: how to add custom-fake city with lat/lon and be able to search (find route) to/from that city.
I don't know if this is the best solution but it is working:
Create a custom Geocoder Class which overwrites the geocode function. There you can overwrite the result function and apply suggestions to the result.
L.CustomGeocoder = L.Control.Geocoder.Nominatim.extend({
suggestions: [],
setSuggestions(arr){
this.suggestions = arr;
},
createSuggestionFromMarker(marker){
this.suggestions.push({name: marker.options.title, center: marker.getLatLng()});
},
getResultsOfSuggestions(query){
var results = [];
this.suggestions.forEach((point)=>{
if(point.name.indexOf(query) > -1){
point.center = L.latLng(point.center);
point.bbox = point.center.toBounds(100);
results.push(point);
}
});
return results;
},
geocode(query, resultFnc, context) {
var that = this;
var callback = function(results){
var sugg = that.getResultsOfSuggestions(query);
resultFnc.call(this,sugg.concat(results));
}
L.Control.Geocoder.Nominatim.prototype.geocode.call(that,query, callback, context);
}
})
Then you have to use the new Geocoder Class:
var geocoder = new L.CustomGeocoder({});
var control = L.Routing.control({
waypoints: [],
router: new L.Routing.osrmv1({
language: 'en',
profile: 'car'
}),
geocoder: geocoder
}).addTo(map);
And finally you can add suggestions over markers and theier title option over createSuggestionFromMarker(marker) or setSuggestions(arr):
var suggestions = [
{
name: 'Test Car 1',
center: [50.27, 19.03]
},
{
name: 'Test Car 2',
center: [50.10, 18.4]
}
];
geocoder.setSuggestions(suggestions);
var marker_work = L.marker([50.27, 19.03], { title: 'MyWork'}).addTo(map);
var marker_home = L.marker([50.10, 18.4], { title: 'MyHome'}).addTo(map);
geocoder.createSuggestionFromMarker(marker_work);
geocoder.createSuggestionFromMarker(marker_home);
Update, use marker Ref instead of fix latlng
Change this two function, then the marker is referenced and it always searches from the current position of the marker:
createSuggestionFromMarker(marker){
this.suggestions.push({name: marker.options.title, marker: marker});
},
getResultsOfSuggestions(query){
var results = [];
this.suggestions.forEach((point)=>{
if(point.name.indexOf(query) > -1){
if(point.marker){
point.center = point.marker.getLatLng();
}
point.center = L.latLng(point.center);
point.bbox = point.center.toBounds(100);
results.push(point);
}
});
return results;
},
You can test this in the demo, when you drag the marker
https://jsfiddle.net/falkedesign/hu25jfd1/

make multiple markers draggable

I use an Array to create a couple of markers in my leaflet map for Photos with Geolocations which works fine:
for (var p of ArrayofData) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
mymap.addLayer(marker);
}
to enable users to change their photo location I need them to drag those markers around and then I can read the new location:
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
As all of my markers have the same constructor it seems as if this script only works with the last marker. All others are draggable but do not give back any feedback when released.
Does anybody know, how I can access all of them?
You can do that by adding those drag event handlers inside your for loop.
for (var p of data) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
map.addLayer(marker);
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
}
Also I highly recommend that you keep track of your markers by adding them to an array.
var markers = [];
for (var p of data) {
var lat = p.lat;
var lon = p.lon;
var markerLocation = new L.LatLng(lat, lon);
var marker = new L.Marker(markerLocation,{
draggable: 'true',
id: p.Filename
});
map.addLayer(marker);
marker.on('dragend', function (e) {
// Get position of dropped marker
var latLng = e.target.getLatLng();
console.log ("id:"+e.target.options.id);
console.log ("NewLocation:"+latLng);
});
markers.push(marker);
}
Demo

Leafletjs: How to have new marker in first click then update the latlng of marker in second click

I have list of markers that want to render in the map, but I want it one by one. In first click I want to make new marker. Then when I click to another location, I want my marker to just move to the new latLng not to create another marker. Here is my code:
function (licon, coord, data) {
var self = jQuery(this);
var map = self.data("map");
var latlng = new L.LatLng(coord[0], coord[1]);
//Create Marker
if (licon) {
var leafIcon = L.icon(licon);
console.log(typeof (marker));
if (typeof (marker) === 'undefined') {
var marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
} else {
console.log('not undefined');
map.removeLayer(marker);
marker = L.marker(latlng, {
icon: leafIcon,
"markerData": data,
draggable: true
});
}
} else {
var marker = L.marker(latlng, {
"markerData": data,
draggable: true
});
}
marker.addTo(map);
return marker;
}
A quick example of the result: http://jsfiddle.net/ve2huzxw/43/
var currentMarker;
map.on("click", function (event) {
if (currentMarker) {
currentMarker.setLatLng(event.latlng);
return;
}
currentMarker = L.marker(event.latlng, {
draggable: true
}).addTo(map).on("click", function () {
event.originalEvent.stopPropagation();
});
});
document.getElementById("done").addEventListener("click", function () {
currentMarker = null;
});
You can also add a smooth transition to show the marker moving to the new position:
if (currentMarker) {
currentMarker._icon.style.transition = "transform 0.3s ease-out";
currentMarker._shadow.style.transition = "transform 0.3s ease-out";
currentMarker.setLatLng(event.latlng);
setTimeout(function () {
currentMarker._icon.style.transition = null;
currentMarker._shadow.style.transition = null;
}, 300);
return;
}
a slightly more consolidated solution some years later.
var currentMarker;
map2.on('click', function(e) {
if (currentMarker){
currentMarker.setLatLng(e.latlng)
} else {
currentMarker = new L.marker(e.latlng).addTo(map2);
};
//console.log('lat, lon: ', e.latlng.lat, e.latlng.lng);
});
leaflet now defaults to smoothly dragging the point over to the new coords.

google map info window data display

I have error about for info window data. I can't get the Please help me to check my code.
function initialize() {
map = new google.maps.Map(document.getElementById(map), {
center: new google.maps.LatLng(1.352083, 103.819836),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//var infowindow;
if (markers) {
for (var level in markers) {
for (var i = 0; i < markers[level].length; i++) {
var details = markers[level][i];
//var infowindow;
markers[level][i] = new google.maps.Marker({
title: details.name,
position: new google.maps.LatLng(
details.location[0], details.location[1]),
clickable: true,
draggable: false,
icon: details.icon
});
var infowindow = new google.maps.InfoWindow({
content: details.description,
//content : markers[level][i].description,
position: new google.maps.LatLng(details.location[0], details.location[1])
//position: markers[level][i].position
});
google.maps.event.addListener(markers[level][i], 'click', function() {
infowindow.setPosition(this.position);
alert(this.position);
//infowindow.setContent(markers[level][i].description);
infowindow.open(map,markers[level][i]);
});
}
}
}
I can't get the description data. Please help me to check my code.