I am creating a neighbourhood map using google maps API.I have added some locations and created markers. I want to add a search filter feature, such that the user can search those locations by their name. It should include a text input field or drop-down menu that filters the map markers and list items to locations matching the text input or selection.
The list items filtering works fine but the markers(locations) are not filtered.
So I want to ask how can I use setVisible() property to hide and display the markers in my code.
This is the filter module:
function viewModel(markers) {
var self = this;
self.filter = ko.observable(''); // this is for the search box
self.items = ko.observableArray(locations);
self.filteredItems = ko.computed(function() {
var filter = self.filter().toLowerCase();
if (!filter) {
return self.items();
} else {
return ko.utils.arrayFilter(self.items(), function(id) {
return stringStartsWith(id.title.toLowerCase(), filter);
});
}
});
This is the full code of my .js file.
var map;
var locations = [
{title: 'The Red Fort', location: {lat: 28.6562, lng: 77.2410}},
{title: 'Humayun\'s Tomb', location: {lat: 28.5933, lng: 77.2507}},
{title: 'India Gate', location: {lat: 28.6129, lng: 77.2295}},
{title: 'Lotus Temple', location: {lat: 28.5535, lng: 77.2588}},
{title: 'Akshardham Temple', location: {lat: 28.6127, lng: 77.2773}},
{title: 'Lodhi Gardens', location: {lat: 28.5931, lng: 77.2179}},
{title: 'Raj Ghat', location: {lat: 28.6406, lng: 77.2495}},
{title: 'Jama Masjid', location: {lat: 28.6507, lng: 77.2334}},
{title: 'Gurudwara Bangla Sahib', location: {lat: 28.6264, lng:
77.2091}},
{title: 'Qutub Minar', location: {lat: 28.5244, lng: 77.1855}},
];
var center =[{lat : 28.5244, lng : 77.1855}];
var markers = []; // Creating a new blank array for all the listing markers.
var styles = [
{
featureType: 'water',
stylers: [
{ color: '#19a0d8' }
]
},{
featureType: 'administrative',
elementType: 'labels.text.stroke',
stylers: [
{ color: '#ffffff' },
{ weight: 6 }
]
},{
featureType: 'administrative',
elementType: 'labels.text.fill',
stylers: [
{ color: '#e85113' }
]
},{
featureType: 'road.highway',
elementType: 'geometry.stroke',
stylers: [
{ color: '#efe9e4' },
{ lightness: -40 }
]
},{
featureType: 'transit.station',
stylers: [
{ weight: 9 },
{ hue: '#e85113' }
]
},{
featureType: 'road.highway',
elementType: 'labels.icon',
stylers: [
{ visibility: 'off' }
]
},{
featureType: 'water',
elementType: 'labels.text.stroke',
stylers: [
{ lightness: 100 }
]
},{
featureType: 'water',
elementType: 'labels.text.fill',
stylers: [
{ lightness: -100 }
]
},{
featureType: 'poi',
elementType: 'geometry',
stylers: [
{ visibility: 'on' },
{ color: '#f0e4d3' }
]
},{
featureType: 'road.highway',
elementType: 'geometry.fill',
stylers: [
{ color: '#efe9e4' },
{ lightness: -25 }
]
}
];
function initMap() {
// Constructor creates a new map
map = new google.maps.Map(document.getElementById('map'), {
center: center[0],
zoom: 13,
styles: styles,
mapTypeControl: false
});
var largeInfowindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
var defaultIcon = makeMarkerIcon('0091ff'); // this is the default marker icon.
var highlightedIcon = makeMarkerIcon('FFFF24'); // this is the state of the marker when highlighted.
var activeIcon = makeMarkerIcon('0F0');
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location; // Get the position from the location array.
var title = locations[i].title;
marker(locations);
}
// Create a marker per location, and put into markers array.
function marker(locations)
{var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
id: i,
});
locations[i].marker = marker; // we made marker a property of the locations and stored info of each marker
wikiLink(locations[i]);
markers.push(marker); // Push the marker to our array of markers.
// Create an onclick event to open an infowindow at each marker.
marker.addListener('click', function() {
populateInfoWindow(this, largeInfowindow);
this.setIcon(activeIcon);
});
bounds.extend(markers[i].position);
/*
marker.addListener('mouseover', function() {
this.setIcon(highlightedIcon);
});
*/
marker.addListener('mouseout', function() {
this.setIcon(defaultIcon);
});
}
// Extend the boundaries of the map for each marker
map.fitBounds(bounds);
function wikiLink(location) {
location.url = '';
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + title + '&format=json&callback=wikiCallback';
//If you cant get a wiki request, throw an error message.
/*
var wikiError = setTimeout(function() {
location.url = 'Unable to find the request';
}, 8000);
*/
$.ajax({
url: wikiUrl,
dataType: "jsonp",
jsonp: "callback",
success: function(response) {
console.log(response);
var url = response[3][0];
console.log(url);
location.marker.wikiurl = url;
console.log(location.url);
//clearTimeout(wikiError);
}
})
.fail(function (jqXHR, textStatus, error) {
error = 'Unable to find the request';
alert("Post error: " + error);
});
}
}
// This function populates the infowindow when the marker is clicked. We'll only allow
// one infowindow which will open at the marker that is clicked, and populate based
// on that markers position.
function populateInfoWindow(marker, infowindow) {
// Check to make sure the infowindow is not already opened on this marker.
if (infowindow.marker != marker) {
infowindow.setContent(''); // Clearing the infowindow content to give the streetview time to load.
infowindow.marker = marker;
// Making sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function() {
infowindow.marker = null;
});
// In case the status is OK, which means the pano was found, computing the position of the streetview image, then calculate the heading, then get a
// panorama from that and set the options
var getStreetView = function(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var nearStreetViewLocation = data.location.latLng;
var heading = google.maps.geometry.spherical.computeHeading(
nearStreetViewLocation, marker.position);
infowindow.setContent('<div>' + marker.title + '</div><hr><div id="pano"></div><div><a href=' + marker.wikiurl + '> Click here for more info </a></div>');
var panoramaOptions = {
position: nearStreetViewLocation,
pov: {
heading: heading,
pitch: 30
}
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'), panoramaOptions);
} else {
infowindow.setContent('<div>' + marker.title + '</div><hr>' + '<div>No Street View Found</div>');
}
};
var streetViewService = new google.maps.StreetViewService();
var radius = 500;
// Use streetview service to get the closest streetview image within 50 meters of the markers position
streetViewService.getPanoramaByLocation(marker.position, radius, getStreetView);
infowindow.open(map, marker); // Open the infowindow on the correct marker.
}
}
// This function takes in a COLOR, and then creates a new marker icon of that color.
// The icon will be 21 px wide by 34 high, have an origin of 0, 0 and be anchored at 10, 34).
function makeMarkerIcon(markerColor) {
var markerImage = new google.maps.MarkerImage(
'http://chart.googleapis.com/chart?chst=d_map_spin&chld=1.15|0|'+ markerColor +
'|40|_|%E2%80%A2',
new google.maps.Size(21, 34),
new google.maps.Point(0, 0),
new google.maps.Point(10, 34),
new google.maps.Size(21,34));
return markerImage;
}
function viewModel(markers) {
var self = this;
self.filter = ko.observable(''); // this is for the search box, takes value in it and searches for it in the array
self.items = ko.observableArray(locations); // we have made the array of locations into a ko.observableArray
self.filteredItems = ko.computed(function() {
var filter = self.filter().toLowerCase();
if (!filter) {
return self.items();
} else {
return ko.utils.arrayFilter(self.items(), function(id) {
return stringStartsWith(id.title.toLowerCase(), filter);
});
}
});
var stringStartsWith = function (string, startsWith) {
string = string || "";
if (startsWith.length > string.length)
return false;
return string.substring(0, startsWith.length) === startsWith;
};
// this should show the infowindow if any place on the list is clicked
this.showInfoWindow = function(place) {
google.maps.event.trigger(place.marker, 'click');
};
}
$(function(){
ko.applyBindings(new viewModel());
});
This is .html file
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Map of my favourite city - New Delhi</title>
<link href="css/map_styles.css" rel="stylesheet">
<link href="css/styles.css" rel="stylesheet">
<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/knockout-3.4.1.js"></script>
</head>
<body>
<div id="mySidenav" class="sidenav">
<span class="menu-title">List of places</span>
<input type="text" data-bind="textInput: filter" placeholder="Search from the list">
<ul class="" style="list-style-type: none;" data-bind="foreach: filteredItems">
<li>
<span data-bind="text: title, click: $parent.showInfoWindow"></span>
</li>
</ul>
×
</div>
<div id="main">
<h2>Famous places in New Delhi</h2>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ Click here</span>
</div>
<div id="map"></div>
<div id="map-error" class="map-error"></div>
<script src="js/newmap.js"></script>
<script src="js/maperror.js"></script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCwUdUoC9ZiRbFC3et89fPK3tXIVO8D2sI&callback=initMap"
onerror="mapError()"></script>
<script>
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
</script>
</body>
</html>
Thanks for this question :) It was an interesting exercise. I'm not sure my answer will satisfy you, because it re-initializes the map every time a filter is done. I'm not sure how to get around that, because the viewModel and the initMap method are separate. But it does what you asked for.
Modified your initMap() method to take an array parameter, holding boolean values. If the array is not defined the markers' visibility are defaulted to true
Modified the viewModel, by creating an array to hold boolean values. The array is emptied every time the viewModel is called, and the markers are spliced to hold the original values only (One of the areas I'm sure you can improve on). Inside your ko.utils.arrayFilter() method, if returned value is true, I push a true value to the array as well. At the end of the array, I call the initMap() method again, with this array as input. Now only the locations which are filtered out as true in the search will be visible on re-initializing.
While applying the bindings I provided markers variable as input to the viewModel. (I think you had already intended to do this, but forgot).
Update:
Concerning the error you're getting in the comment, it's because I replaced your lines
<script src="js/newmap.js"></script>
<script src="js/maperror.js"></script>
with an empty <script> tag and placed the entire JS code in there. To avoid confusion, I'll remove all the snippets of code I had put above and show the entire file here:
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type='text/javascript' src='knockout-3.4.2.js'></script>
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<style>
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<div id="mySidenav" class="sidenav">
<span class="menu-title">List of places</span>
<input type="text" data-bind="textInput: filter" placeholder="Search from the list">
<ul class="" style="list-style-type: none;" data-bind="foreach: filteredItems">
<li>
<span data-bind="text: title, click: $parent.showInfoWindow"></span>
</li>
</ul>
×
</div>
<div id="main">
<h2>Famous places in New Delhi</h2>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ Click here</span>
</div>
<div id="map"></div>
<div id="map-error" class="map-error"></div>
<script>
var map;
var locations = [
{title: 'The Red Fort', location: {lat: 28.6562, lng: 77.2410}},
{title: 'Humayun\'s Tomb', location: {lat: 28.5933, lng: 77.2507}},
{title: 'India Gate', location: {lat: 28.6129, lng: 77.2295}},
{title: 'Lotus Temple', location: {lat: 28.5535, lng: 77.2588}},
{title: 'Akshardham Temple', location: {lat: 28.6127, lng: 77.2773}},
{title: 'Lodhi Gardens', location: {lat: 28.5931, lng: 77.2179}},
{title: 'Raj Ghat', location: {lat: 28.6406, lng: 77.2495}},
{title: 'Jama Masjid', location: {lat: 28.6507, lng: 77.2334}},
{title: 'Gurudwara Bangla Sahib', location: {lat: 28.6264, lng:
77.2091}},
{title: 'Qutub Minar', location: {lat: 28.5244, lng: 77.1855}},
];
var center = [{lat: 28.5244, lng: 77.1855}];
var markers = []; // Creating a new blank array for all the listing markers.
var styles = [
{
featureType: 'water',
stylers: [
{color: '#19a0d8'}
]
}, {
featureType: 'administrative',
elementType: 'labels.text.stroke',
stylers: [
{color: '#ffffff'},
{weight: 6}
]
}, {
featureType: 'administrative',
elementType: 'labels.text.fill',
stylers: [
{color: '#e85113'}
]
}, {
featureType: 'road.highway',
elementType: 'geometry.stroke',
stylers: [
{color: '#efe9e4'},
{lightness: -40}
]
}, {
featureType: 'transit.station',
stylers: [
{weight: 9},
{hue: '#e85113'}
]
}, {
featureType: 'road.highway',
elementType: 'labels.icon',
stylers: [
{visibility: 'off'}
]
}, {
featureType: 'water',
elementType: 'labels.text.stroke',
stylers: [
{lightness: 100}
]
}, {
featureType: 'water',
elementType: 'labels.text.fill',
stylers: [
{lightness: -100}
]
}, {
featureType: 'poi',
elementType: 'geometry',
stylers: [
{visibility: 'on'},
{color: '#f0e4d3'}
]
}, {
featureType: 'road.highway',
elementType: 'geometry.fill',
stylers: [
{color: '#efe9e4'},
{lightness: -25}
]
}
];
function initMap(array) {
// Constructor creates a new map
map = new google.maps.Map(document.getElementById('map'), {
center: center[0],
zoom: 13,
styles: styles,
mapTypeControl: false
});
var largeInfowindow = new google.maps.InfoWindow();
var bounds = new google.maps.LatLngBounds();
var defaultIcon = makeMarkerIcon('0091ff'); // this is the default marker icon.
var highlightedIcon = makeMarkerIcon('FFFF24'); // this is the state of the marker when highlighted.
var activeIcon = makeMarkerIcon('0F0');
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location; // Get the position from the location array.
var title = locations[i].title;
marker(locations);
}
// Create a marker per location, and put into markers array.
function marker(locations)
{
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
id: i,
visible: (array ? array[i] : true)
});
locations[i].marker = marker; // we made marker a property of the locations and stored info of each marker
wikiLink(locations[i]);
markers.push(marker); // Push the marker to our array of markers.
// Create an onclick event to open an infowindow at each marker.
marker.addListener('click', function () {
populateInfoWindow(this, largeInfowindow);
this.setIcon(activeIcon);
});
bounds.extend(markers[i].position);
/*
marker.addListener('mouseover', function() {
this.setIcon(highlightedIcon);
});
*/
marker.addListener('mouseout', function () {
this.setIcon(defaultIcon);
});
}
// Extend the boundaries of the map for each marker
map.fitBounds(bounds);
function wikiLink(location) {
location.url = '';
var wikiUrl = 'https://en.wikipedia.org/w/api.php?action=opensearch&search=' + title + '&format=json&callback=wikiCallback';
//If you cant get a wiki request, throw an error message.
/*
var wikiError = setTimeout(function() {
location.url = 'Unable to find the request';
}, 8000);
*/
$.ajax({
url: wikiUrl,
dataType: "jsonp",
jsonp: "callback",
success: function (response) {
console.log(response.length);
var url = response[3][0];
//console.log(url);
location.marker.wikiurl = url;
//console.log(location);
//clearTimeout(wikiError);
}
})
.fail(function (jqXHR, textStatus, error) {
error = 'Unable to find the request';
alert("Post error: " + error);
});
}
}
// This function populates the infowindow when the marker is clicked. We'll only allow
// one infowindow which will open at the marker that is clicked, and populate based
// on that markers position.
function populateInfoWindow(marker, infowindow) {
// Check to make sure the infowindow is not already opened on this marker.
if (infowindow.marker != marker) {
infowindow.setContent(''); // Clearing the infowindow content to give the streetview time to load.
infowindow.marker = marker;
// Making sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function () {
infowindow.marker = null;
});
// In case the status is OK, which means the pano was found, computing the position of the streetview image, then calculate the heading, then get a
// panorama from that and set the options
var getStreetView = function (data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var nearStreetViewLocation = data.location.latLng;
var heading = google.maps.geometry.spherical.computeHeading(
nearStreetViewLocation, marker.position);
infowindow.setContent('<div>' + marker.title + '</div><hr><div id="pano"></div><div><a href=' + marker.wikiurl + '> Click here for more info </a></div>');
var panoramaOptions = {
position: nearStreetViewLocation,
pov: {
heading: heading,
pitch: 30
}
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('pano'), panoramaOptions);
} else {
infowindow.setContent('<div>' + marker.title + '</div><hr>' + '<div>No Street View Found</div>');
}
};
var streetViewService = new google.maps.StreetViewService();
var radius = 500;
// Use streetview service to get the closest streetview image within 50 meters of the markers position
streetViewService.getPanoramaByLocation(marker.position, radius, getStreetView);
infowindow.open(map, marker); // Open the infowindow on the correct marker.
}
}
// This function takes in a COLOR, and then creates a new marker icon of that color.
// The icon will be 21 px wide by 34 high, have an origin of 0, 0 and be anchored at 10, 34).
function makeMarkerIcon(markerColor) {
var markerImage = new google.maps.MarkerImage(
'http://chart.googleapis.com/chart?chst=d_map_spin&chld=1.15|0|' + markerColor +
'|40|_|%E2%80%A2',
new google.maps.Size(21, 34),
new google.maps.Point(0, 0),
new google.maps.Point(10, 34),
new google.maps.Size(21, 34));
return markerImage;
}
function viewModel(markers) {
var self = this;
self.filter = ko.observable(''); // this is for the search box, takes value in it and searches for it in the array
self.items = ko.observableArray(locations); // we have made the array of locations into a ko.observableArray
var arrayofMarkersForVisibility = [];
self.filteredItems = ko.computed(function () {
if (markers.length>10) markers.splice(10,10);
var filter = self.filter().toLowerCase();
if (!filter || filter =="") {
arrayofMarkersForVisibility = [];
for (var i in markers){
//markers[i].setVisible(true);
arrayofMarkersForVisibility.push(true);
}
initMap(arrayofMarkersForVisibility);
return self.items();
} else {
arrayofMarkersForVisibility = [];
for (var i in markers){
arrayofMarkersForVisibility.push(false);
//markers[i].setVisible(false);
}
return ko.utils.arrayFilter(self.items(), function (id) {
var somestring = stringStartsWith(id.title.toLowerCase(), filter);
if (somestring){
arrayofMarkersForVisibility[id.marker.id]=true;
//markers[i].setVisible(true);
}
if (id.marker.id ==markers.length-1) initMap(arrayofMarkersForVisibility);
return somestring;
});
}
});
var stringStartsWith = function (string, startsWith) {
string = string || "";
if (startsWith.length > string.length)
return false;
return string.substring(0, startsWith.length) === startsWith;
};
// this should show the infowindow if any place on the list is clicked
this.showInfoWindow = function(place) {
google.maps.event.trigger(place.marker, 'click');
};
}
$(function(){
ko.applyBindings(new viewModel(markers));
});
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCwUdUoC9ZiRbFC3et89fPK3tXIVO8D2sI&callback=initMap"></script>
<script>
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
</script>
</body>
</html>
I'm going to initalize infowindows (for google map markers) through angular controller (i'm using ng-map module)
NgMap.getMap().then (map) ->
$scope.map = map
for marker in markers
latLng = new (google.maps.LatLng)(marker.latitude, marker.longitude)
#initialize infoWindows through google map api, not ng-map module
contentString = 'is an example string'
infoWindow = new (google.maps.InfoWindow)(content: contentString)
$scope.dynMarkers.push new (google.maps.Marker)(position: latLng)
marker.addListener 'click', ->
infoWindow.open map, marker
$scope.markerClusterer = new MarkerClusterer(map,$scope.dynMarkers, {})
I have an error in console:
marker.addListener is not a function
I can't use an ng-map 'infowindow' DOM element in my view.
What's wrong?
marker object needs to be of google.maps.Marker type, try to replace:
$scope.dynMarkers.push new (google.maps.Marker)(position: latLng)
marker.addListener 'click', ->
infoWindow.open map, marker
with
markerObject = new (google.maps.Marker)(position: latLng) #<-Marker object
$scope.dynMarkers.push markerObject
markerObject.addListener 'click', ->
infoWindow.open map, markerObject
Example
angular.module('mapApp', ['ngMap'])
.controller('mapController', function ($scope, NgMap) {
NgMap.getMap().then(function (map) {
$scope.map = map;
$scope.dynMarkers = [];
$scope.markers.forEach(function (marker) {
var latLng = new google.maps.LatLng(marker.latitude, marker.longitude);
var contentString = 'is an example string'
var infoWindow = new (google.maps.InfoWindow)({ content: contentString });
var dynMarker = new google.maps.Marker({ position: latLng });
$scope.dynMarkers.push(dynMarker);
google.maps.event.addListener(dynMarker, 'click', function () {
infoWindow.open(map,dynMarker);
});
});
var mcOptions = { imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m' };
$scope.markerClusterer = new MarkerClusterer(map, $scope.dynMarkers, mcOptions)
});
$scope.markers = [
{ id: 1, name: 'Oslo', latitude: 59.923043, longitude: 10.752839 },
{ id: 2, name: 'Stockholm', latitude: 59.339025, longitude: 18.065818 },
{ id: 3, name: 'Copenhagen', latitude: 55.675507, longitude: 12.574227 },
{ id: 4, name: 'Berlin', latitude: 52.521248, longitude: 13.399038 },
{ id: 5, name: 'Paris', latitude: 48.856127, longitude: 2.346525 }
];
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<script src="https://googlemaps.github.io/js-marker-clusterer/src/markerclusterer.js"></script>
<div ng-app="mapApp" ng-controller="mapController">
<ng-map default-style="true" zoom="3" center="59.339025, 18.065818">
</ng-map>
</div>
OBJECT
var malls = [{
id: 0,
name: 'Leclerc',
lastname: 'Paris,France',
address:'Boulevard Rahal El Meskini Casablanca Maroc',
]
},
{
/*Malls B*/
id: 1,
name: 'Carefour',
lastname: 'Toulouse,France',
address:'Angle Zaid Ou Hmad Rue Sidi Belyout, Casablanca Maroc', }, ];
MY CONTROLLER
var address = "";//document.getElementById('address').value;
var id_mall ="";
var malls = Malls.all();
for (var i = 0; i < malls.length; i++) {
mall = malls[i];
addMarker(mall);}
function addMarker(address) {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 14,
center: latlng
}
id = mall.id;
address = mall.address;
console.debug(address);
map = new google.maps.Map(document.getElementById('map'), mapOptions);
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
title: 'shopping center',
position: results[0].geometry.location,
url:'#/tab/malls/'+id
});
google.maps.event.addListener(marker, 'click', function() {
window.location.href=marker.url;
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
//google.maps.event.addDomListener(window, 'load', initialize);
}
I have 2 markers, and when I click on a marker , I receive :tab/malls/1 and the other the same thing normally have to be /tab/malls/0 and tab/malls/1 ,
I did not find the solution.
Please need help
Your object code appears malformed: there is an unmatched ] character on line 8. Try deleting this character and running it.
I'm trying to get an array of latitudes and longitudes from the php arrays $lat and $long which are being retrieved by a database.
<?php
...
$lat[$latlongindex] = $results_row['latitude'];
$long[$latlongindex] = $results_row['longitude'];
echo "
<script type=\"text/javascript\">
var locations = $latlongindex;
var jslat = <?php echo json_encode($lat); ?>;
var jslong = <?php echo json_encode($long); ?>; // <----------Line 58
var map = new GMaps({
div: '#map',
lat: 39.833,
lng: -98.583,
width: '900px',
height: '500px',
zoom: 4,
zoomControl : true,
zoomControlOpt: {
style : 'SMALL',
position: 'TOP_LEFT'
},
panControl : false,
});
//------------------------------------------------ADD MARKERS--------------
for (var i = 0; i<locations; i++) {
map.addMarker({
position: new google.maps.LatLng( jslat[i], jslong[i] ),
});
}
</script>
"; // <--------------------------------Line 83
}
}
?>
Just as a quick check I can echo json_encode($lat) and json_encode($long) and they are displayed correctly but when I try use them inside the javascript I get "Notice: Array to string conversion" in lines 58 and 83. If I explicitly state the location like:
var jslat = [];
jslat[0] = $lat[0];
It will run correctly but obviously just shows the first marker. Thus I know I can access the elements of the $lat and $long arrays. I feel like this is a simplistic error but can't seem to find anything on stack that is a similar issue.
Any help would be great. Thanks.
// MAP CODE
$qry_country_map = 'Select name, refugee, lat, lng FROM '.$table_name.' WHERE 1 AND status = 1';
$country_data_map = $wpdb->get_results($qry_country_map , ARRAY_A);
//echo "<pre>";print_r($country_data_map);exit;
$array_string = "[";
for($m=0;$m<count($country_data_map);$m++) {
$array_string .= "['".$country_data_map[$m]['name']."', '".$country_data_map[$m]['name']."','".$country_data_map[$m]['refugee']."','".$country_data_map[$m]['lat']."', '".$country_data_map[$m]['lng']."'],";
}
$array_string = substr($array_string, 0,-1);
$array_string .= "]";
?>
<style>
#map{
height: 400px;
}
a[href^="http://maps.google.com/maps"]{display:none !important}
.gmnoprint a, .gmnoprint span {
display:none;
}
.gmnoprint div {
background:none !important;
}
</style>
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<div id="map"></div>
<script type="text/javascript">
var marker_image = '<?php echo $plugin_image_url;?>';
// Define your locations: HTML content for the info window, latitude, longitude
var locations = <?php echo $array_string;?>;
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(26.3351, 17.2283),
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
panControl: false,
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var styles = [
{
featureType: "landscape",
stylers: [
{ visibility: "on" },
{ color: "#FFFFFF"}
]
},
{
featureType: "water",
stylers: [
{ visibility: "on" },
{ color: "#CCCCCC"}
]
},
{
featureType: "administrative",
elementType: "geometry.fill",
stylers: [
{ visibility: "off" }
]
},
{
featureType: "all",
elementType: "labels",
stylers: [
{ visibility: "off" }
]
}
];
map.setOptions({styles: styles});
var infowindow = new google.maps.InfoWindow({
maxWidth: 160
});
var marker;
var markers = new Array();
// Add the markers and infowindows to the map
for (var i = 0; i < locations.length; i++)
{
if(locations[i][3]!='' && locations[i][4]!='' && locations[i][2]!='')
{
var scale;
if(locations[i][2]<100)
scale = locations[i][2];
else if(locations[i][2]>100 && locations[i][2]<500)
scale = locations[i][2]/25;
else if(locations[i][2]>500 && locations[i][2]<1000)
scale = locations[i][2]/60;
else if(locations[i][2]>1000 && locations[i][2]<10000)
scale = locations[i][2]/275;
else if(locations[i][2]>10000 && locations[i][2]<100000)
scale = locations[i][2]/1600;
else if(locations[i][2]>100000 && locations[i][2]<500000)
scale = locations[i][2]/7500;
else if(locations[i][2]>500000 && locations[i][2]<1000000)
scale = locations[i][2]/10500;
scale = Math.round(scale);
if(scale!=0)
{
//console.log(scale);
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][3], locations[i][4]),
map: map,
icon: {
url: marker_image,
scaledSize: new google.maps.Size(scale, scale),
size:new google.maps.Size(scale, scale)
}
});
//ADD EVENT TO SHOW INFOWINDOW
google.maps.event.addListener(marker, 'mouseover', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
//marker.setIcon(new google.maps.MarkerImage('http://192.168.5.33/map-marker-hover.png'));
//marker.icon.scaledSize = new google.maps.Size(scale,scale);
//marker.icon.size = new google.maps.Size(scale,scale);
}
})(marker, i));
//ADD EVENT TO HIDE INFOWINDOW
google.maps.event.addListener(marker, 'mouseout', (function(marker, i) {
return function() {
infowindow.close(map, marker);
//marker.setIcon(new google.maps.MarkerImage('http://192.168.5.33/map-marker.png'));
//marker.icon.scaledSize = new google.maps.Size(scale,scale);
//marker.icon.size = new google.maps.Size(scale,scale);
}
})(marker, i));
}
}
}
</script>
See the variable named $array_string i have created it in php and then just echo in js to make a js array and then i have looped with the lat and long to display markers.
i have coded some things for the custom marker image and marker size scaling according to value and effect on mouseover and mouseout.
You just need to copy paste this code make minute changes and you are done.
Let me know if something goes wrong :)
Currently, I am displaying 500-600 Markers on Google map, with their names as tooltip. Now,
I need to display the tool-tip of all overlapping markers as comma-separated i.e. Marker1, Marker2, Marker3 etc. if Marker1, Marker2, Marker3 are overlapped on map.
I found many other different examples on google map at internet especially at GeoCodeZip, but not of my requirement.
if this requirement is once filled, Am afraid of performance issues on zoom changed events, as tooltip needed to be updated (if overlapping is changed).
Update1 : I have already show Overlapping Marker spiderfier to client but not acceptable.
Does anyone have right path or working example ?
Thanks
-Anil
The core of this is to find the pixel distance between LatLngs. Then before adding each marker check the pixel distance between it and any existing markers. If there is another marker nearby add to the title otherwise create a new marker. jsFiddle
function init() {
var mapOptions = {
center: new google.maps.LatLng(0, -0),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
// to get the pixel position from the latlng
// https://stackoverflow.com/questions/1538681/how-to-call-fromlatlngtodivpixel-in-google-maps-api-v3
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
google.maps.event.addListenerOnce(map, 'idle', function() {
if (overlay.getProjection()) {
var points = [
{ latlng: new google.maps.LatLng(40, -100), title: '1' },
{ latlng: new google.maps.LatLng(40.125, -100.125), title: '2' },
{ latlng: new google.maps.LatLng(40.25, -100.25), title: '3' },
{ latlng: new google.maps.LatLng(40.5, -100.5), title: '4' },
{ latlng: new google.maps.LatLng(40.75, -100.75), title: '5' },
{ latlng: new google.maps.LatLng(41, -101), title: '6' },
{ latlng: new google.maps.LatLng(35, -95), title: '7' },
{ latlng: new google.maps.LatLng(45, 105), title: '8' },
{ latlng: new google.maps.LatLng(25, -115), title: '9' },
{ latlng: new google.maps.LatLng(55, -85), title: '10' },
{ latlng: new google.maps.LatLng(30, -34), title: '11' }
];
// for each point
var markers = [];
points.forEach(function (point) {
var nearby = false;
var pointPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(point.latlng);
markers.forEach(function(marker) {
var markerPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(marker.getPosition());
// check for marker 'near by'
if (Math.abs(pointPixelPosition.x - markerPixelPosition.x) < 10 || Math.abs(pointPixelPosition.y - markerPixelPosition.y) < 10) {
nearby = true;
marker.setTitle(marker.getTitle() + ', ' + point.title);
}
});
// create new marker
if (!nearby) {
markers.push(new google.maps.Marker({ map: map, position: point.latlng, title: point.title }));
}
});
}
map.setCenter(new google.maps.LatLng(39.8282, -98.5795));
});
}