I have a script that loops and adds markers one at a time.
I am trying to get the current marker to have an info window and and only have 5 markers on a map at a time (4 without info windows and 1 with)
How would I add an id to each marker so that I can delete and close info windows as needed.
This is the function I am using to set the marker:
function codeAddress(address, contentString) {
var infowindow = new google.maps.InfoWindow({
content: contentString
});
if (geocoder) {
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,
position: results[0].geometry.location
});
infowindow.open(map,marker);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
}
JavaScript is a dynamic language. You could just add it to the object itself.
var marker = new google.maps.Marker(markerOptions);
marker.metadata = {type: "point", id: 1};
Also, because all v3 objects extend MVCObject(). You can use:
marker.setValues({type: "point", id: 1});
// or
marker.set("type", "point");
marker.set("id", 1);
var val = marker.get("id");
Just adding another solution that works for me.. You can simply append it in the marker options:
var marker = new google.maps.Marker({
map: map,
position: position,
// Custom Attributes / Data / Key-Values
store_id: id,
store_address: address,
store_type: type
});
And then retrieve them with:
marker.get('store_id');
marker.get('store_address');
marker.get('store_type');
I have a simple Location class that I use to handle all of my marker-related things. I'll paste my code below for you to take a gander at.
The last line(s) is what actually creates the marker objects. It loops through some JSON of my locations, which look something like this:
{"locationID":"98","name":"Bergqvist Järn","note":null,"type":"retail","address":"Smidesvägen 3","zipcode":"69633","city":"Askersund","country":"Sverige","phone":"0583-120 35","fax":null,"email":null,"url":"www.bergqvist-jb.com","lat":"58.891079","lng":"14.917371","contact":null,"rating":"0","distance":"45.666885421019"}
Here is the code:
If you look at the target() method in my Location class, you'll see that I keep references to the infowindow's and can simply open() and close() them because of a reference.
See a live demo: http://ww1.arbesko.com/en/locator/ (type in a Swedish city, like stockholm, and hit enter)
var Location = function() {
var self = this,
args = arguments;
self.init.apply(self, args);
};
Location.prototype = {
init: function(location, map) {
var self = this;
for (f in location) { self[f] = location[f]; }
self.map = map;
self.id = self.locationID;
var ratings = ['bronze', 'silver', 'gold'],
random = Math.floor(3*Math.random());
self.rating_class = 'blue';
// this is the marker point
self.point = new google.maps.LatLng(parseFloat(self.lat), parseFloat(self.lng));
locator.bounds.extend(self.point);
// Create the marker for placement on the map
self.marker = new google.maps.Marker({
position: self.point,
title: self.name,
icon: new google.maps.MarkerImage('/wp-content/themes/arbesko/img/locator/'+self.rating_class+'SmallMarker.png'),
shadow: new google.maps.MarkerImage(
'/wp-content/themes/arbesko/img/locator/smallMarkerShadow.png',
new google.maps.Size(52, 18),
new google.maps.Point(0, 0),
new google.maps.Point(19, 14)
)
});
google.maps.event.addListener(self.marker, 'click', function() {
self.target('map');
});
google.maps.event.addListener(self.marker, 'mouseover', function() {
self.sidebarItem().mouseover();
});
google.maps.event.addListener(self.marker, 'mouseout', function() {
self.sidebarItem().mouseout();
});
var infocontent = Array(
'<div class="locationInfo">',
'<span class="locName br">'+self.name+'</span>',
'<span class="locAddress br">',
self.address+'<br/>'+self.zipcode+' '+self.city+' '+self.country,
'</span>',
'<span class="locContact br">'
);
if (self.phone) {
infocontent.push('<span class="item br locPhone">'+self.phone+'</span>');
}
if (self.url) {
infocontent.push('<span class="item br locURL">'+self.url+'</span>');
}
if (self.email) {
infocontent.push('<span class="item br locEmail">Email</span>');
}
// Add in the lat/long
infocontent.push('</span>');
infocontent.push('<span class="item br locPosition"><strong>Lat:</strong> '+self.lat+'<br/><strong>Lng:</strong> '+self.lng+'</span>');
// Create the infowindow for placement on the map, when a marker is clicked
self.infowindow = new google.maps.InfoWindow({
content: infocontent.join(""),
position: self.point,
pixelOffset: new google.maps.Size(0, -15) // Offset the infowindow by 15px to the top
});
},
// Append the marker to the map
addToMap: function() {
var self = this;
self.marker.setMap(self.map);
},
// Creates a sidebar module for the item, connected to the marker, etc..
sidebarItem: function() {
var self = this;
if (self.sidebar) {
return self.sidebar;
}
var li = $('<li/>').attr({ 'class': 'location', 'id': 'location-'+self.id }),
name = $('<span/>').attr('class', 'locationName').html(self.name).appendTo(li),
address = $('<span/>').attr('class', 'locationAddress').html(self.address+' <br/> '+self.zipcode+' '+self.city+' '+self.country).appendTo(li);
li.addClass(self.rating_class);
li.bind('click', function(event) {
self.target();
});
self.sidebar = li;
return li;
},
// This will "target" the store. Center the map and zoom on it, as well as
target: function(type) {
var self = this;
if (locator.targeted) {
locator.targeted.infowindow.close();
}
locator.targeted = this;
if (type != 'map') {
self.map.panTo(self.point);
self.map.setZoom(14);
};
// Open the infowinfow
self.infowindow.open(self.map);
}
};
for (var i=0; i < locations.length; i++) {
var location = new Location(locations[i], self.map);
self.locations.push(location);
// Add the sidebar item
self.location_ul.append(location.sidebarItem());
// Add the map!
location.addToMap();
};
Why not use an cache that stores each marker object and references an ID?
var markerCache= {};
var idGen= 0;
function codeAddress(addr, contentStr){
// create marker
// store
markerCache[idGen++]= marker;
}
Edit: of course this relies on a numeric index system that doesn't offer a length property like an array. You could of course prototype the Object object and create a length, etc for just such a thing. OTOH, generating a unique ID value (MD5, etc) of each address might be the way to go.
Marker already has unique id
marker.__gm_id
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.
I need some help with Google maps.
I am not able to reduce the zoom level in google maps after fitbound.
The problem is that I am getting a very highly zoomed google map. I have tried setting the zoom level to 5 (as you can see in the codes) but this has no effect to the very highly zoomed map.
I want to achieve this
But right now its coming like this : http://redstoneinfotech.com/OSAcontact/
Here is the map.js
window.map = {
map_type: 'ROADMAP',
map_zoom: 5,
map_style: 'blackwhite',
map_scrollable: 'on',
marker: 'show',
label: ['Castle Hill', 'Sydney', 'Melbourne', 'Milton', 'Brooklyn Park', 'Wangara '],
address: '',
latlng: ['-33.7301484, 150.9626532', '-33.8473567, 150.6517813',
'-37.970154, 144.4926753 ', ' - 27.4691402, 152.9962768 ',
' - 34.9303517, 138.5346949 ', ' - 31.7928896, 115.8157212 '
],
center_latlng: '',
markerURL: 'assets/images/marker.png',
auto_center: true,
};
'use strict';
jQuery(document).ready(function($) {
$('.google-map').each(function() {
var mapDiv = $(this);
var mapData = window[mapDiv.attr('id')];
function createMap() {
var style = [{
'stylers': [{
'saturation': -100
}]
}];
var options = {
zoom: parseInt(mapData.map_zoom, 5),
scrollwheel: false,
draggable: mapData.map_scrollable === 'on',
mapTypeId: google.maps.MapTypeId[mapData.map_type]
};
if (mapData.map_style === 'blackwhite') {
options.styles = style;
}
return new google.maps.Map(mapDiv[0], options);
}
// create map
var map = createMap();
// create bounds in case we dont have center map coordinates
// every time a marker is added we increase the bounds
var bounds = new google.maps.LatLngBounds();
function addMarker(position, index) {
if (mapData.marker === 'show') {
var image = {
url: mapData.markerURL,
size: new google.maps.Size(30, 48),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(10, 40)
};
var marker = new google.maps.Marker({
position: position,
icon: image,
map: map
});
// extend bounds to encase new marker
bounds.extend(position);
// add label popup to marker
if (mapData.label[index] !== undefined) {
var infoWindow = new google.maps.InfoWindow({
content: mapData.label[index]
});
google.maps.event.addListener(marker, 'click', function(e) {
infoWindow.open(map, this);
});
}
}
}
// centre map
var centerMapWithCoordinates = !mapData.auto_center;
if (centerMapWithCoordinates) {
if (mapData.center_latlng !== undefined) {
var center_lat_lng = mapData.center_latlng.split(',');
var center_map = new google.maps.LatLng(center_lat_lng[0], center_lat_lng[1]);
map.setCenter(center_map);
} else {
console.log('You have not set any coordinates for the map to be centered at.');
}
}
// create markers
if (mapData.address) {
// lookup addresses
var markerAddressCount = 0;
$.each(mapData.address, function(index, address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address
}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (undefined !== results[0]) {
var location = results[0].geometry.location;
var position = new google.maps.LatLng(location.lat(), location.lng());
addMarker(position, index);
}
// increment count so we can keep track of all markers loaded
markerAddressCount++;
// if all markers are loaded then fit map
if (!centerMapWithCoordinates && markerAddressCount === mapData.address.length) {
map.fitBounds(bounds);
}
} else {
console.log('Geocode was not successful for the following reason: ' + status);
}
});
});
} else if (undefined !== mapData.latlng) {
for (var i = 0; i < mapData.latlng.length; i++) {
var coordinates = mapData.latlng[i].split(',');
var position = new google.maps.LatLng(coordinates[0], coordinates[1]);
addMarker(position, i);
}
if (!centerMapWithCoordinates) {
map.fitBounds(bounds);
}
}
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
this.setZoom(5);
google.maps.event.removeListener(boundsListener);
});
});
});
I have tried with many options but none of them is working. Please help.
As much as I can see, the problem is with the Google Maps sdk. Why? because they are calling to bounds_changed callback before the fitBounds is actually ended.
That's why it causes the zoom not to work because they didn't finish to zoom it as part as the bounds changing in fitBounds.
So the solution is to put the setZoom in setTimeout. In this way, this code will run only after the execution of the current process - fitBounds.
setTimeout(() => {
this.setZoom(5);
}, 0);
It works for me. Let me know if it works for you.
I have an array like this deviceId = [005305230001JIZZZZ, 085835360001NBGJZZ, 085835360002NBGJZZ].
The info window should show the deviceId and be displayed based on which marker is clicked. I started looking at JavaScript only a few days back and can't understand how the functions work and dont have the time right now to learn becauseI have to get this done. I saw a few implementations on this, but I think they have done the adding multiple markers differently using functions, I think. I couldn't understand it so I used for loop.
The latArray and lngArray have something like this [12.1456,12.5256,11.566] and [72.145,72.4557,75.23535]
I cant figure out how to add info windows for corresponding markers.
This is the code for map:
function initMap() {
var bounds = new google.maps.LatLngBounds();
var mapDiv = document.getElementById('map');
var map = new google.maps.Map(mapDiv);
map.setCenter(new google.maps.LatLng(latArray[0],lngArray[0]));
map.setZoom(18);
for(i=0;i<latArray.length;i++)
{
marker = new google.maps.Marker({
position: new google.maps.LatLng(latArray[i],lngArray[i]),
map: map,
title:"This is the place.",
// icon:"phone4.png"
});
//bounds.extend(marker.getPosition());
console.log(latArray);
console.log(lngArray);
}
//map.fitBounds(bounds);
var infoWindow = new google.maps.InfoWindow({
content: contentString
});
marker.addListener('click', function() {
infoWindow.open(map, marker);
});
}
How to show info window of corresponding markers.
This is content for marker:
contentString = '<div id = "content>'
+'<p style = "color:#000000">DeviceID<p>' +
'<p>'+ deviceId[i] + '<br></p>' //deviceId is the array with content
+ '</div>'
I read something about closures but didn't understand. Please help
Edit: I just tried this. I'm getting js?callback=initMap:34 InvalidValueError: setPosition: not a LatLng or LatLngLiteral: not an Object
What i tried:
var markerArray=[];
for(i=0;i<latArray.length;i++)
{
markerArray.push("new google.maps.LatLng("+ latArray[i]+","+lngArray[i]+")");
console.log(markerArray[i]);
}
console.log(markerArray[0]);
for(i=0;i<latArray.length;i++)
{
marker = new google.maps.Marker({
position: markerArray[i],
map: map,
title:"This is the place.",
// icon:"phone4.png"
});
var infoWindow = new google.maps.InfoWindow({
content: contentString[i]
});
marker.addListener('click', function(marker,contentString) {
infoWindow.open(map, marker);
});
}
So I will not bother you with the explanation how closures work (as you are saying your not interested in it now), I just supply you the solution:
// Your arrays with geo informations
var latArray = [-25.363, -26.263, -25.163];
var lngArray = [131.044, 131.144, 132.044];
// Your array with device information
var deviceIdArray = ["AAA", "BBB", "CCC"];
// Just create map according to the first geo info
var map = new google.maps.Map(document.getElementById("map"), {
center: {lat: latArray[0], lng: lngArray[0]},
zoom: 6
});
// Loop throuhg all geo info
latArray.forEach(function(lat, i) {
// For each one create info window
var infoWindow = new google.maps.InfoWindow({
content: '<div id="content>'
+ '<p style="color:#000000">DeviceID<p>'
+ '<p>'+ deviceIdArray[i] + '</p>'
+'</div>'
});
// For each one create marker
var marker = new google.maps.Marker({
map: map,
position: {lat: latArray[i], lng: lngArray[i]}
});
// Click on the currently created marker will show the right info window
marker.addListener("click", function() {
infoWindow.open(map, marker);
});
});
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3"></script>
<div id="map"></div>
Take a look at my function with map. It takes json object with some data from PHP and 'translate' it into array and then adds content to multiple markers (it is not dynamic in real time - you have to reload page). In addition it has a search box (which opens certain info window). If you don't understand do not hestitate to ask :).
//check if document is fully loaded, seetting a container for ajax call results
$(document).ready(function() {
var tablica = [];
// ajax call for action preparing set of names, descriptions, coords and slugs needed to render deatiled markers on map
$.ajax({
url: 'map/json_prepare',
dataType: 'json',
success: function(response) {
var obj = JSON && JSON.parse(response) || $.parseJSON(response);
obj.forEach(function(item, index, array)
{
tablica.push(item);
});
//call a function rendering a map itself
var map;
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 50.06561980, lng: 19.946850},
zoom: 12
});
////////////////////////////////////////////////////////////////////////////////////////////////////
// LOOP ADDING MARKERS FROM DB WITH PROPER INFO WINDOWS (DESCRIPTION AND LINKS)
// Add a markers reference
var markers = [];
$.each(tablica, function( key, value ) {
//markers
var myLatLng = {lat: value[1], lng: value[2]};
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: value[0],
clickable: true,
animation: google.maps.Animation.DROP,
adress: value[5]
});
//infowindows
marker.info = new google.maps.InfoWindow ({
content: '<h1>'+ value[0] + '</h1>' + '<br>' + '<br>' + value[3] + '<br>' + value[5] +'<br>' + '<br>' + '' + 'Details' + '<br/>' +
'' + 'Take part in' + '<br>'
});
//eventlistener - after click infowindow opens
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, marker);
});
//event listener - after dblclick zoom on certain event is set
google.maps.event.addListener(marker, 'dblclick', function() {
map.setZoom(18);
map.setCenter(marker.getPosition());
});
markers.push(marker);
});
// End of loop adding markers from db.
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///additional event listener - rightclick to get back default zoom
google.maps.event.addListener(map, 'rightclick', function() {
map.setZoom(12);
map.setCenter(map.getPosition());
});
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//CENTRING MAP AS ALL OF MARKERS IS VISIBLE//
//create empty LatLngBounds object
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();
for (i = 0; i < tablica.length; i++) {
var marker = new google.maps.Marker({
position: new google.maps.LatLng(tablica[i][1], tablica[i][2]),
map: map
});
//extend the bounds to include each marker's position
bounds.extend(marker.position);
}
//now fit the map to the newly inclusive bounds
map.fitBounds(bounds);
/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
///SEARCH_BOX////////
///Here comes part of script adding search box
// Create the search box and link it to the UI element.
// Anchor search box and search button to the map.
var input = document.getElementById('pac-input');
var searchBox = new google.maps.places.SearchBox(input);
var button = document.getElementById('submitSearch');
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(button);
//replacing polish characters on order to search without necessity typing them
function cleanUpSpecialChars(str)
{
str = str.replace(/[Ą]/g,"A");
str = str.replace(/[ą]/g,"a");
str = str.replace(/[Ę]/g,"E");
str = str.replace(/[ę]/g,"e");
str = str.replace(/[Ć]/g,"C");
str = str.replace(/[ć]/g,"c");
str = str.replace(/[Ł]/g,"L");
str = str.replace(/[ł]/g,"l");
str = str.replace(/[Ń]/g,"N");
str = str.replace(/[ń]/g,"n");
str = str.replace(/[Ó]/g,"O");
str = str.replace(/[ó]/g,"o");
str = str.replace(/[Ś]/g,"S");
str = str.replace(/[ś]/g,"s");
str = str.replace(/[Ź]/g,"Z");
str = str.replace(/[ź]/g,"z");
str = str.replace(/[Ż]/g,"Z");
str = str.replace(/[ż]/g,"z");
return str;
}
//Function, that search in array of markers, one which fits the key word written in searchbox.
$('#submitSearch').click(function() {
//Catching searched word and preparing its value for search process
var toSearch = $(input).val().trim();
toSearch = cleanUpSpecialChars(toSearch);
toSearch = toSearch.toLowerCase();
console.log('Szukana fraza -> ' + toSearch);
var results = [];
if (toSearch.length >=3) {
// Iterate through the array
$.each(markers, function (i, marker) {
//preparing certain elemnts of marker objects for search process
markers[i].title = cleanUpSpecialChars(markers[i].title);
markers[i].adress = cleanUpSpecialChars(markers[i].adress);
markers[i].title = markers[i].title.toLowerCase();
markers[i].adress = markers[i].adress.toLowerCase();
if (markers[i].title.indexOf(toSearch) > -1 || markers[i].adress.indexOf(toSearch) > -1) {
results.push(markers[i]);
}
});
if (results.length < 1) {
console.log ('nic');
$('#message2').slideDown(500, function () {
setTimeout(function () {
$('#message2').slideUp(500);
}, 5000);
});
}
// Close all the infoWindows, before rendering Search results.
markers.forEach(function (marker) {
marker.info.close(map, marker);
});
//Opens infWindows for multiple markers found and set bounds so that all markers found are visible
results.forEach(function (result) {
result.info.open(map, result);
bounds.extend(result.position);
});
map.fitBounds(bounds);
}
else{
//what if user has typed less than three characters in searchbox -> render flash mess.
$("#message").slideDown(500, function(){
setTimeout(function(){
$("#message").slideUp(500);
},5000);
});
}
});
//Enabling key Enter for triggering a search action.
$(input).keypress(function(e){
if(e.which == 13){//Enter key pressed
$('#submitSearch').click();//Trigger search button click event
}
});
},
//////////////////////////////////////////////////////////////////////////////////////////
//obsługa błędu, jeśli nie zostanie wyświetlona mapa
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
console.log(ajaxOptions);
alert('Map is broken. Please try again later.')
}
});
});
It will not qork here because it doesn't contain data from php.
I am working with a map in which I am interested in having multiple regions selected and when those regions have been selected they only pins that show are those regions. Essentially, the site currently has the "tags" set up so when you click on a region, the corresponding tag displays under the filter. After the filter is added each marker is compared and if that marker is not in a region the tag is removed. Currently, the map was functioning when selecting a drop down item and comparing this item with the polygon region for each marker. However, the moment you add another loop for each tag the filtering no longer works. Below is my code and the website link is at http://swishercorbett.com.test.marketmagnitude.com/listings/?map=1
var DistrictVal = jQuery('#District').val();
var baths = jQuery('#baths').val();
var bedrooms = jQuery('#bedrooms').val();
//var amount = jQuery('listings_per_page')
var minprice = jQuery('#minPriceB').val();
var maxprice = jQuery('#maxPriceB').val();
jQuery('#loading').show(); //show the loading icon on start before a selection is made
/* ===================================================================================================================*/
var stopIt = [];
var bad;
var DistrictLen = jQuery('#District option').length; // determine how many items there are
for(var i = 0; i <= DistrictLen; i++) //loop through each item in the drop down
{
var optionText = jQuery('#District option').eq(i).text(); //get the text and put in variable
}
//loop through each filter tag added
// if the filter tag matches drop down selection
// make sure not to add the new tag
var districtTags = jQuery('#districtTags #districtTag')
var tagLength = districtTags.length;
for (var z = 0; z <= tagLength; z++)
{
if (districtTags.eq(z).text() == DistrictVal)
{
stopIt.push(1); //there is a match
}
else{
stopIt.push(0); // there is not a match
}
}
var bad = jQuery.inArray(1, stopIt);
if (bad == -1)
{
jQuery('#districtTags').append('<div id="tag"><div id="districtTag">'+DistrictVal+'</div><span id="remove-tag"> X</span></div>');
tags.push(DistrictVal); //get all of the tags and send them to mapChange() which is in jGMap.js
//console.log(tags);
}
jQuery('#remove-tag').live('click',function()
{
jQuery(this).parent().empty();
tags = [];
});
/* ===================================================================================================================*/
//New Ajax request indepentant from the below Ajax request which
// is only used to retrieve listings by location
infoWindow = new google.maps.InfoWindow({size: new google.maps.Size(150, 100)});
var mapOptions = {
center: new google.maps.LatLng(39.977735,-86.141566),
zoom: 11,
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map-canvas-listing"), mapOptions);
geoXml = new geoXML3.parser({map: map, singleInfoWindow: true, infowindow: infoWindow});
geoXml.parse('/wp-content/themes/swishercorbett/js/SC Map.kml');
/* ================================================================================ */
//Adds inforation to the database with the address and the latitude and longitude
jQuery.ajax({
async: 'false',
url: 'http://swishercorbett.com.test.marketmagnitude.com/wp-content/plugins/john- real-estate/mapinformation.php', //not a real page
type: 'GET',
dataType: 'json',
data: {jbaths: baths, jbedrooms: bedrooms, jminprice: minprice, jmaxprice: maxprice},
//data: {jaddr: addr, jlat: lat, jlon: lon}, //uncomment after use!
success: function(e)
{ // get each address
jQuery(e).each(function(index)
{
// e[0] is first item repeated over itself
var text = e[index][0]; //get the address of each listing
//console.log(text);
var cords = e[index][1].split(','); //get the latitude and longitude and spit
var lat = parseFloat(cords[0]); //latitude with decimal points
var lon = parseFloat(cords[1]); // longitude with decimal points
infowindow = new google.maps.InfoWindow();
marker = new google.maps.Marker( //add a new marker for each item in JSON array
{
position: new google.maps.LatLng(lat, lon), // create a new position
map: map // add the position to the map
});
/* ============================================================================ */
for(var i = 0; i<geoXml.docs[0].gpolygons.length; i++ )
{
// if any of the tags match show those districts, remove the rest
for( var z = 0; z<= tags.length; z++)
{
if( geoXml.docs[0].placemarks[i].name == tags[z] ) //DistricVal
{
if (geoXml.docs[0].gpolygons[i].Contains(marker.getPosition()) )
{ //if the marker is in the first quadriant then keep it, else remove the marker from the map
marker.setMap(map);
setTimeout(function(){ jQuery('#loading').hide(); }, 500);
}
else
{
marker.setVisible(false);
//console.log('does not contain');
}
}
else
{
//alert('there is not a kml region with that name')
}
}
}
/* ============================================================================ */
//console.log(google.maps.geometry.poly.containsLocation(cords, Midtown));
google.maps.event.addListener(marker, 'click', (function(marker, index)
{
return function()
{
infowindow.close(map,marker);
infowindow.setContent(e[index][0]);
infowindow.open(map, marker);
}
})(marker, index));
});
}
}).done(function(){
jQuery('#loading').hide();
});
Use this library to manage marker clustering and it would help optimize your map view (this answer should help integrate).
Also, the code in the snippet works well with filtering usually. You can try it out. Might just do the trick.
// Get all markers from the php document markers.php ( output
simulates json object )
$('#map-canvas').gmap().bind('init', function(evt, map) {
$.getJSON( 'http://example.php',
function(data) { $.each( data.markers, function(i, marker) {
$('#map-canvas').gmap('addMarker', {'tags': marker.tags, 'position': new google.maps.LatLng(marker.latitude, marker.longitude),'bounds': true}).click(function() {
// Declares what you want to show in the info window when marker is clicked
$('#map-canvas').gmap('openInfoWindow', { 'content': '<strong>' +
marker.title + '</strong><br/>' + marker.address + '<br/>' +
marker.phone + '<br/><br/>' + marker.tags }, this);
});
// Filter map
$('#map-canvas').gmap('find', 'markers', { 'property': 'tags',
'value': ['baths', 'bedrooms', 'minprice', 'maxprice'], 'operator':'AND' }, function(marker, isFound) {
if ( isFound ) {
marker.setVisible(true);
} else {
marker.setVisible(false);
}
});
});
});
}); // End map function
My goal is to allow the user to filter results based on the option they select at the top of the map. If anyone could help me clean up this code and make it functional I would greatly appreciate your efforts
This first part sets up the 4 options I would like to filter by.
<div id="Filters" style="margin:5px;background:#f4f4f4;border:1px solid #888;padding:5px 5px 5px 10px;">
<label style="color:#555;font-size:12px; font-weight:bold;" for="tags">Filter by: </label>
<select id="tags" style="outline:none;">
<option value="all">All</option>
<option value="Western">Western</option>
<option value="Central">Central</option>
<option value="Eastern">Eastern</option>
</select>
</div>
(function() {
// Creating an array that will contain hhs icons
var hhsIcons = [];
hhsIcons['Eastern'] = new google.maps.MarkerImage('{!$Resource.markerE}' );
hhsIcons['Western'] = new google.maps.MarkerImage('{!$Resource.markerW}' );
hhsIcons['Central'] = new google.maps.MarkerImage('{!$Resource.markerC}' );
window.onload = function() {
// Create object literal containing the properties of the map
var options = {
zoom:5,
center: new google.maps.LatLng(37.09, -95.71),
mapTypeId: google.maps.MapTypeId.ROADMAP,
mapTypeControl: false
};
// Create the map
var map = new google.maps.Map(document.getElementById('map'),
options);
var homeControlDiv = document.createElement('DIV');
var homeControl = new HomeControl(homeControlDiv, map);
homeControlDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(homeControlDiv);
var eastControlDiv = document.createElement('DIV');
var eastControl = new EastOnly(eastControlDiv, map);
eastControlDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(eastControlDiv);
var jsonData = {'jsonaccounts':
[
<apex:repeat value="{!Accounts}" var="abc">
{
'lat': '{!abc.Latitude__c}',
'lng': '{!abc.Longitude__c}',
'hhs': '{!abc.HHS_Region__c}'
},
</apex:repeat>
]};
var accountname = [];
var director = [];
var vp = [];
var division = [];
//Add field data for each account into respective arrays
<apex:repeat value="{!Accounts}" var="acc">
accountname.push("{!acc.name}");
director.push("{!acc.hhs_director__r.name}");
vp.push("{!acc.area_vp__r.name}");
division.push("{!acc.HHS_Region__c}");
</apex:repeat>
// Create a variable that will hold the InfoWindow object
var infowindow;
var markers = [];
// Loop through the jsondata
for (var i = 0; i < jsonData.jsonaccounts.length; i++) {
var jsonaccounts = jsonData.jsonaccounts[i];
// Create marker data
var myMarkerData = { // collecting all custom data that you want to add
region : jsonaccounts.hhs, // to the marker object within an array.
}
When I add the markers, I think I need to make categories for each so it will let me filter by the specific category
// Adding the markers
var marker = new google.maps.Marker({
position: new google.maps.LatLng(jsonaccounts.lat,
jsonaccounts.lng),
map: map,
icon: hhsIcons[jsonaccounts.hhs],
data: myMarkerData
});
marker.region = jsonaccounts.hhs;
markers.push(marker);
alert(markers[i].region);
// Wrap the event listener inside an anonymous function
// that we immediately invoke and passes the variable i to.
(function(i, marker) {
// Create the event listener. It now has access to the values of
// i and marker as they were during its creation
google.maps.event.addListener(marker,
'click', function() {
if (!infowindow) {
infowindow = new google.maps.InfoWindow();
}
// Set the content of the InfoWindow
infowindow.setContent('<b>' + accountname[i] + '</b>' +
'<br/>Director: ' + director[i] +
'<br/>VP: ' + vp[i] +
'<br/>Division: ' + division[i] +
// Tie the InfoWindow to the marker
infowindow.open(map, marker);
});
})(i, marker);
}
}; })();
I am not sure if this code is useful, but it was where I left off
marker.region = region;
markers.push(marker); function
hide(region) {
for (var i=0; i<map.markers.length; i++) {
if (map. markers[i].region == region) {
map.markers[i].setVisible(false);
}
}
</script>
In your last code block you use map.markers while it should be just markers.