I'm coding a demo of how I want a future search function to work. I want to query google on an address or area and return the area bounds as well as nearby places. To do this, I am using places autocomplete, geocode, and places search.
So far I am successfully getting predicted search queries resulting in the bounds being drawn as a rectangle on my map. However, when I try to implement markers for the place search result no markers are appearing on my map. I know the search is working because putting an alert in the createMarker function on each location returns several lat/lng's that coincide with my area.
I suspect that maybe the map object is not being passed to my createMarker function, but I am kind of a noob when it comes to Javascript. I tried passing an additional parameter but it didn't do much.
It should be noted that I am able to create a marker within the initialize function, when I attempt to just create one static marker.
EDIT: I have removed the type parameter for the place search request, but the code doesn't work even with the parameter ['store'].
var map;
var infowindow;
function initialize() {
var view_lat = document.getElementById('view_lat').value;
var view_lng = document.getElementById('view_lng').value;
var focus = new google.maps.LatLng(view_lat,view_lng);
var swlat = document.getElementById('swlat').value;
var swlng = document.getElementById('swlng').value;
var nelat = document.getElementById('nelat').value;
var nelng = document.getElementById('nelng').value;
var map_canvas = document.getElementById('map-canvas_embed');
var map_options = {
center: new google.maps.LatLng(parseFloat(view_lat), view_lng),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var mysw = new google.maps.LatLng(swlat,swlng)
var map = new google.maps.Map(map_canvas, map_options)
var rectangle = new google.maps.Rectangle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: map,
bounds: new google.maps.LatLngBounds(
new google.maps.LatLng(swlat, swlng),
new google.maps.LatLng(nelat, nelng))
});
var request = {
location: focus,
radius: 500
};
var place_search = new google.maps.places.PlacesService(map);
place_search.nearbySearch(request,callback)
}
Handles the result from google places search
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({
position: place.geometry.location
});
marker.setMap(map);
}
Autocomplete variables
var input = document.getElementById('location');
var options = {
componentRestrictions: {country: 'se'},
types: ['geocode']
}
var searchform = document.getElementById('searchform');
var place;
var autocomplete = new google.maps.places.Autocomplete(input, options);
Add listener to detect autocomplete selection
google.maps.event.addListener(autocomplete, 'place_changed', function () {
place = autocomplete.getPlace();
//console.log(place);
});
Add listener to search (This function isn't working, hence my work around in the initialize function)
searchform.addEventListener("submit", function() {
var newlatlong = new google.maps.LatLng(place.geometry.location.lat(),place.geometry.location.lng());
map.setCenter(newlatlong);
marker.setPosition(newlatlong);
map.setZoom(12);
google.maps.event.trigger(map, 'resize');
});
Reset the inpout box on click
input.addEventListener('click', function(){
input.value = "";
});
Call the initialize function
google.maps.event.addDomListener(window, 'load', initialize);
Indeed it looks like a problem of JavaScript's scope.
Consider these lines of your code:
function initialize() {
//...
var map = new google.maps.Map(map_canvas, map_options)
//...
}
Declaring map inside the initialize function makes your map variable unreachable out of your initialize function.
So when you try to reach it in your searchform, map.setCenter() will show in your console that map is undefined.
You could solve your issue in several ways.
declare map at the beginning of your script (before initialize is executed, anyways)
declare the searchform.addEventListener("submit", function(){}) inside your initialize() function and use it before initialize() ends its execution.
Related
Guys need a bit of help with google maps, I'm creating a tracking web app using MySQL DB coordinates, the tracking works well so far except the google map markers keep repeating when refreshed, I have set the map marker refresh using a setInterval function for every 5 seconds(for testing). I've tried clearoverlays() methods and remove map markers method(from google sample) but doesn't work. Appreciate your help, thank you
<script defer
src="https://maps.googleapis.com/maps/api/js?key="KEY"8&callback=initMap">
</script>
<script type="text/javascript">
setInterval(function () {
BindMarker();
}, 5000);
var customIcons = {
blue: { icon: 'blue48.png'},
};
var marker;
var map = null;
var infoWindow = null;
function load() {
map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(1.4370993, 110.3387572),
zoom:15,
});
infoWindow = new google.maps.InfoWindow;
}
function BindMarker() {
downloadUrl('maps1.php', function (data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var icon = customIcons["blue"] || {};
marker = new google.maps.Marker({
map: map,
animation: google.maps.Animation.BOUNCE,
position: point,
icon: icon.icon,
shadow: icon.shadow
});
}
});
}
function bindInfoWindow(marker, map, infoWindow) {
google.maps.event.addListener(marker, 'click', function () {
map.setCenter(marker.getPosition());
});
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function () {
if (request.readyState == 4) {
request.önreadystatechange = doNothing;
callback(request, request.status); }
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() { }
</script>
The functions I tried are given below( I called the remove overlays function, remove markers and also the delete markers function before BindMarker() inside the setInterval function so that it would remove the markers before binding new markers
function setMapOnAll(map) {
for (let i = 0; i < markers.length; i++) { markers[i].setMap(map); }
}
function clearMarkers() {setMapOnAll(null); }
function deleteMarkers() {clearMarkers(); markers = [];}
function clearOverlays() {
while(markers.length) { markers.pop().setMap(null); }
markers.length = 0;
}
I believe you've confounded the examples, which your attempted code shows verbatim and what your code is actually doing.
It the sample code you're drawing from, the variable markers is an array of Google Map marker objects. So this code makes sense in that regard:
function deleteMarkers() {clearMarkers(); markers = [];}
But, your code is not creating an array of those objects. Your code does not have a variable named markers that is accessible outside of the downloadUrl() function. The variable markers does show up inside that function, but it contains an HTMLCollection element - not an array of markers.
To fix this you need to create an array named markers right after the variable name marker is created.
Then, within the for loop, just after you create the marker push that marker on to the markers array. You will also have to rename the existing markers variable to something more appropriate like markerElements.
Now, the deleteMarkers() function will work as expected.
I use the following script to generate this page
function initialize() {
var mapCanvas = document.getElementById('map');
var mapOptions = {center:new google.maps.LatLng(latitudeMid,longitudeMid),zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,streetViewControl:false,mapTypeControl:true,scaleControl:true,scaleControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT}};
var map = new google.maps.Map(mapCanvas, mapOptions);
var i;
var insertion;
var previousMarker;
// -------------------------------
//show locations on the map
// -------------------------------
for (i = 0; i < fotoCount; i++) {
var myLatLng=new google.maps.LatLng(Latituden[i], Longituden[i]);
var marker = new StyledMarker({styleIcon:new StyledIcon(StyledIconTypes.MARKER,{color:'00ff00',text:Letters[i]}),position:myLatLng,map:map});
marker.set('zIndex', -i);
insertion='<img src=\"http://www.pdavis.nl/Ams/'.concat(Bestanden[i],'.jpg\"></img>');
insertion=insertion.concat('<table class=width100><tr><td>Bestand: ',Bestanden[i],'</td><td class=pright>Lokatie: ',Latituden[i],' °N., ',Longituden[i],' °E. (',Letters[i],')</td>');
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[i],'</td></tr><td colspan=3>Object: ',Objecten[i],'</td></table>');
google.maps.event.addListener(marker, 'click', function() {
$('#photo').html(insertion);
this.styleIcon.set('color', 'ff0000');
if(previousMarker!=null){previousMarker.styleIcon.set('color', '00ff00')};
previousMarker=this;
});
}
Clicking a marker should do two things: (i) turn the marker red (and any existing red marker green) and (ii) show the appropriate photo with information in the right-hand panel. The first does work, but the second always shows the photo corresponding to the last marker. Using
"alert(insertion);" shows that this is correct for each marker.
You can't do it this way because at the end of the loop, "i" will always be the last index. And of course when you click on a marker, "i" value inside the callback is the last index, so you should always have the last picture displayed.
Just put insertion code inside your click callback isn't enough because of the i value. You didn't bind anything to fix value in your callback so you will have the same problem.
The following solution use the marker object to bind the "i" value, like this you can use it in your callback.
Script tested on your page :).
Adapt it as you want !
function initialize() {
var mapCanvas = document.getElementById('map');
var mapOptions = {center:new google.maps.LatLng(latitudeMid,longitudeMid),zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,streetViewControl:false,mapTypeControl:true,scaleControl:true,scaleControlOptions:{position:google.maps.ControlPosition.TOP_RIGHT}};
var map = new google.maps.Map(mapCanvas, mapOptions);
var i;
var previousMarker;
// -------------------------------
//show locations on the map
// -------------------------------
for (i = 0; i < fotoCount; i++) {
var myLatLng=new google.maps.LatLng(Latituden[i], Longituden[i]);
var marker = new StyledMarker({styleIcon:new StyledIcon(StyledIconTypes.MARKER,{color:'00ff00',text:Letters[i]}),position:myLatLng,map:map});
marker.set('zIndex', -i);
marker.myIndex = i;
google.maps.event.addListener(marker, 'click', function() {
var insertion = "";
insertion='<img src=\"http://www.pdavis.nl/Ams/'.concat(Bestanden[this.myIndex],'.jpg\"></img>');
insertion=insertion.concat('<table class=width100><tr><td>Bestand: ',Bestanden[this.myIndex],'</td><td class=pright>Lokatie: ',Latituden[this.myIndex],' °N., ',Longituden[this.myIndex],' °E. (',Letters[this.myIndex],')</td>');
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[this.myIndex],'</td></tr><td colspan=3>Object: ',Objecten[this.myIndex],'</td></table>');
$('#photo').html(insertion);
this.styleIcon.set('color', 'ff0000');
if(previousMarker!=null){previousMarker.styleIcon.set('color', '00ff00')};
previousMarker=this;
});
}
}
insertion should be an array. This way when you iterate, in eacj iteration you are just overwriting the content of insertion. In the end you have last value from image array as insertion.
var insertionArr = [];
...
insertion=insertion.concat('<td class=pright>Genomen: ',Datums[i],'</td></tr><td colspan=3>Object: ',Objecten[i],'</td></table>');
insertionArr[marker] = insertion; // Add it to the array
google.maps.event.addListener(marker, 'click', function() {
$('#photo').html(insertionArr[this]);// get it from the array
...
});
This is not tested code.
I have 2 different events, please correct me if i am doing this wrong,
//initializing the map
google.maps.event.addDomListener(window, 'load', initialize);
//initializing the markers
google.maps.event.addListener(map, 'idle', showMarkers);
The first event is to initialize the map (set it up), the second event is for querying the database for new markers when the current map bounds change (not functional yet)
Since I have defined "map" inside the initialize function, how can I access it outside the function and pass it to the second event? As you can see i have declared it before the functions as a global variable but it is still undefined as the event argument, i have been stuck on this for days
var map;
function initialize(){
//defining map options
var mapLatlng = new google.maps.LatLng(37.09024, -100.712891);
var mapOptions = {
zoom: 4,
center: mapLatlng
}
//defining the map itself
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
}
function showMarkers(){
Parse.initialize("X","X");
var query = new Parse.Query("business_and_reviews");
var results = new Parse.Object("business_and_reviews");
query.equalTo("name","McDonalds");
query.find({
success: function(results) {
console.log(results);
for (var i = 0; i < results.length; i++) {
var object = results[i];
}
var lat = (object["attributes"]["lat"]);
var lng = (object["attributes"]["lng"]);
console.log(lat);
console.log(lng);
//adding the marker from the query
var marker = new google.maps.Marker({
position: mapLatlong,
map: map,
title: 'Hello World!'
});
},
error: function(object, error) {
}
});
}
//initializing the map
google.maps.event.addDomListener(window, 'load', initialize);
//initializing the markers
google.maps.event.addListener(map, 'idle', showMarkers);
For the second event "map" is undefined
SOlved it! put the idle event listener inside the initialize function and it works like a charm! I guess initilize isn't to initialize the page initially but runs constantly
I have been referencing a found tutorial and have stumbled upon an error using the google maps api. I am getting and error that telling me that a variable is not defined when in fact it is. I am not exactly sure what the problem is.. Please help.
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=true">
</script>
<script type="text/javascript">
var map;
var service;
function handleSearchResults (results, status)
{
console.log(results);
}
function performSearch ()
{
var request = {
bounds: map.getBounds(),
name: "McDonald's" // within the bounds find the given name
}
service.nearbySearch(request, handleSearchResults);
}
function initialize (location) //initializing geolocation function
{
console.log(location);
var currentLocation = new google.maps.LatLng(location.coords.latitude, location.coords.longitude)
var mapOptions = {
center: currentLocation,
zoom: 13
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
// To add the marker to the map, use the 'map' property
var marker = new google.maps.Marker({
position: currentLocation,
map: map // referencing google map from variable map above
});
service = new google.maps.places.PlacesService(map);
// wait until map bounds are initialized before performing search
google.maps.event.addListenerOnce(map, 'bounds_changed', performSearch);
}
$( document ).ready(function()
{
navigator.geolocation.getCurrentPosition(initialize);
});
</script>
</html>
It looks like you're running into scoping issues with that map variable since you're calling the initialize function from within the scope of the $(document.ready() callback. I made some adjustments to it in the jsfiddle below. Does that fix the issue?
jsfiddle
function handleSearchResults (results, status)
{
console.log(results);
}
function performSearch ()
{
var request = {
bounds: map.getBounds(),
name: "McDonald's" // within the bounds find the given name
}
service.nearbySearch(request, handleSearchResults);
}
function initialize (location) //initializing geolocation function
{
console.log(location);
var currentLocation = new google.maps.LatLng(location.coords.latitude, location.coords.longitude)
var mapOptions = {
center: currentLocation,
zoom: 13
};
map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
// To add the marker to the map, use the 'map' property
var marker = new google.maps.Marker({
position: currentLocation,
map: map // referencing google map from variable map above
});
service = new google.maps.places.PlacesService(map);
// wait until map bounds are initialized before performing search
google.maps.event.addListenerOnce(map, 'bounds_changed', performSearch);
}
$(document).ready(function() {
var map;
var service;
navigator.geolocation.getCurrentPosition(initialize);
})
I'm working on a Google Map in JavaScript(v3).
I need to show some markers from XML, for which I use jQuery.
Here's the object and function, might save me time explaining:
var VX = {
map:null,
bounds:null
}
VX.placeMarkers = function(filename) {
$.get(filename, function(xml) {
$(xml).find("marker").each(function() {
var lat = $(this).find('lat').text();
var lng = $(this).find('lng').text();
var point = new google.maps.LatLng(parseFloat(lat),parseFloat(lng));
VX.bounds.extend(point);
VX.map.fitBounds(VX.bounds); //this works
var marker = new google.maps.Marker({
position: point,
map: VX.map,
zoom: 10,
center: point
});
});
});
//VX.map.fitBounds(VX.bounds); //this shows me the ocean east of Africa
}
So basically my problem is that I can't figure out how to do fitbounds from outside of the .each function, and doing it inside the function calls it for every marker which looks bad.
I declare the bounds when I initialize the map... haven't included the entire code because its like 300 lines.
Shouldn't I be able to use a value that I passed to a global object?
Edit: ah, I was calling it from outside of the get function!
The second call doesn't work because it is firing before the ajax get() returns.
Place the fitBounds inside the get() handler, but outside the each() function. Like so:
var VX = {
map:null,
bounds:null
}
VX.placeMarkers = function(filename)
{
$.get
(
filename,
function(xml)
{
$(xml).find("marker").each
(
function()
{
var lat = $(this).find('lat').text();
var lng = $(this).find('lng').text();
var point = new google.maps.LatLng(parseFloat(lat),parseFloat(lng));
VX.bounds.extend(point);
//VX.map.fitBounds(VX.bounds); //this works
var marker = new google.maps.Marker
({
position: point,
map: VX.map,
zoom: 10,
center: point
});
}
);
VX.map.fitBounds(VX.bounds); //-- This should work.
}
);
//VX.map.fitBounds(VX.bounds); //this shows me the ocean east of africa
}